The link routine links the following symbols, which must be present in all felix libraries.
create_thread_frame startThe unlink routine is called to unlink the library.
Note that felix never generates variables of static, storage class, however felix has no control over used C/C++ code embedded in Felix library modules. DO NOT use static storage class for variables, or even constants which require dynamic initialisation.
1: #line 1911 "./lpsrc/flx_rtl.pak" 2: #ifndef FLX_DYNLINK 3: #define FLX_DYNLINK 4: #ifndef FLX_RTL 5: #include "flx_rtl.hpp" 6: #include "flx_gc.hpp" 7: #endif 8: #include <string> 9: using namespace std; 10: 11: // define dynamic library loader stuff, even for static linkage 12: #if defined(_WIN32) 13: #include <windows.h> 14: typedef HMODULE LIBHANDLE; 15: #define FLX_SET_NOLIBRARY(lib) lib=NULL 16: #define FLX_CHECK_NOLIBRARY(lib) (lib==NULL) 17: #define FLX_LIB_EXTENSION ".DLL" 18: #define FLX_DLSYM(x,y) (void*)GetProcAddress(x,#y) 19: #define FLX_SDLSYM(x,y) (void*)GetProcAddress(x,y) 20: #elif defined(MACOSX_NODLCOMPAT) 21: #include <mach-o/dyld.h> 22: typedef NSModule LIBHANDLE; 23: #define FLX_SET_NOLIBRARY(lib) lib=NULL 24: #define FLX_CHECK_NOLIBRARY(lib) (lib==NULL) 25: #define FLX_LIB_EXTENSION ".dylib" 26: #define FLX_DLSYM(x, y) flx::rtl::getmachosym(x,"_"#y) 27: #define FLX_SDLSYM(x, y) flx::rtl::getmachosym(x,(string("_")+string(y)).data()) 28: #else 29: // UNIX, recent OSX 30: typedef void *LIBHANDLE; 31: #define FLX_SET_NOLIBRARY(lib) lib=NULL 32: #define FLX_CHECK_NOLIBRARY(lib) (lib==NULL) 33: #if defined(__CYGWIN__) 34: #define FLX_LIB_EXTENSION ".dll" 35: #elif defined(MACOSX) 36: #define FLX_LIB_EXTENSION ".dylib" 37: #else 38: #define FLX_LIB_EXTENSION ".so" 39: #endif 40: #include <dlfcn.h> 41: #define FLX_DLSYM(x,y) dlsym(x,#y) 42: #define FLX_SDLSYM(x,y) dlsym(x,y) 43: #endif 44: 45: #ifndef FLX_STATIC_LINK 46: #define DLSYM(x,y) FLX_DLSYM(x,y) 47: #define SDLSYM(x,y) FLX_SDLSYM(x,y) 48: #else 49: #define DLSYM(x,y) (void*)&y 50: #define SDLSYM(x,y) (throw flx::rtl::link_failure_t("<static link>",y,"dlsym with static link requires name not string") 51: #endif 52: 53: // Utilities to make dynamic linkage and 54: // initialisation of Felix modules easier 55: // 56: // We provide a standard exception to report 57: // link failure (missing symbol). 58: // 59: // We provide a class flx_dynlink_t which 60: // opens a Felix shared library given a filename, 61: // and links the mandatory symbols 62: // The user may derive from this class to add 63: // linkage for extra symbols 64: // 65: // We provide a class flx_libinit_t which 66: // initialises and terminates a Felix module 67: // The user may derive from this class to add 68: // extra initialisation or termination processing. 69: // 70: // [Note: the virtuals are *deliberately* private. 71: // Be sure to make your overrides private too, 72: // so they cannot be called: 73: // they're dispatched automatically by wrappers 74: // defined in the base] 75: 76: // must be at global scope, because the users' is 77: struct thread_frame_t; 78: 79: namespace flx { namespace rtl { 80: 81: struct RTL_EXTERN flx_link_failure_t; 82: struct RTL_EXTERN flx_dynlink_t; 83: struct RTL_EXTERN flx_libinit_t; 84: 85: /// Dynamic linkage failure. 86: 87: struct RTL_EXTERN flx_link_failure_t : flx_exception_t { 88: string filename; 89: string operation; 90: string what; 91: flx_link_failure_t(string f, string o, string w); 92: virtual ~flx_link_failure_t(); 93: }; 94: 95: RTL_EXTERN LIBHANDLE 96: flx_load_library(char const *fname); 97: 98: RTL_EXTERN LIBHANDLE 99: flx_load_module(char const *fname); 100: 101: /// frame creators. 102: 103: typedef thread_frame_t *(*thread_frame_creator_t) 104: ( 105: flx::gc::generic::collector_t* 106: ); 107: 108: /// library initialisation routine. 109: 110: typedef con_t *(*start_t) 111: ( 112: thread_frame_t*, 113: int, 114: char **, 115: FILE*, 116: FILE*, 117: FILE* 118: 119: ); 120: 121: typedef con_t *(*main_t)(thread_frame_t*); 122: 123: /// dynamic object loader. 124: 125: struct RTL_EXTERN flx_dynlink_t 126: { 127: // data 128: LIBHANDLE library; 129: string filename; 130: thread_frame_creator_t thread_frame_creator; 131: start_t start_sym; 132: main_t main_sym; 133: long refcnt; 134: 135: // routines 136: void link(char const *filename) throw(flx_link_failure_t); 137: void unlink(); 138: virtual ~flx_dynlink_t(); 139: flx_dynlink_t(); 140: 141: private: 142: // the user should override this procedure to 143: // link any extra symbols. 144: // on error, throw a flx_link_failure_t, 145: // otherwise your exception will be dishonoured 146: // and a generic link_failure_t thrown anyhow 147: 148: flx_dynlink_t(flx_dynlink_t const&); // uncopyable 149: void operator=(flx_dynlink_t const&); // uncopyable 150: virtual void usr_link(); 151: // called after mandatory symbols are linked 152: }; 153: 154: /// Thread Frame Initialisation. 155: 156: struct RTL_EXTERN flx_libinit_t 157: { 158: thread_frame_t *thread_frame; 159: con_t *start_proc; 160: con_t *main_proc; 161: flx_dynlink_t *lib; 162: flx::gc::generic::collector_t *collector; 163: void create 164: ( 165: flx_dynlink_t *lib_a, 166: flx::gc::generic::collector_t *collector_a, 167: main_t main_sym, 168: int argc, 169: char **argv, 170: FILE *stdin_, 171: FILE *stdout_, 172: FILE *stderr_ 173: ); 174: 175: void destroy (); 176: 177: con_t *bind_proc(void *fn, void *data); 178: virtual ~flx_libinit_t(); 179: flx_libinit_t(); 180: 181: private: 182: flx_libinit_t(flx_libinit_t const&); 183: void operator=(flx_libinit_t const&); 184: // the user can override these procedures 185: // to perform any additional initialisation 186: // and termination required. 187: 188: virtual void usr_create(); 189: // called after standard init completes 190: 191: virtual void usr_destroy(); 192: // called before standard destroy starts 193: }; 194: 195: #ifdef MACOSX_NODLCOMPAT 196: void* getmachosym(LIBHANDLE, const char*); 197: #endif 198: 199: }} // namespaces 200: #endif 201:
1: #line 2113 "./lpsrc/flx_rtl.pak" 2: #include "flx_dynlink.hpp" 3: #include <cstring> 4: #include <cstdlib> 5: 6: #ifdef FLX_STATIC_LINK 7: extern "C" void *create_thread_frame; 8: extern "C" void *flx_start; 9: extern "C" void *flx_main; 10: #endif 11: 12: namespace flx { namespace rtl { 13: 14: #ifdef MACOSX_NODLCOMPAT 15: void* 16: getmachosym(NSModule library, const char* symname) 17: { 18: NSSymbol sym = NSLookupSymbolInModule(library, symname); 19: if(sym) 20: return NSAddressOfSymbol(sym); 21: return 0; 22: } 23: 24: #endif 25: 26: flx_link_failure_t::flx_link_failure_t(string f, string o, string w) : 27: filename(f), 28: operation(o), 29: what(w) 30: {} 31: 32: flx_link_failure_t::~flx_link_failure_t(){} 33: 34: flx_dynlink_t::~flx_dynlink_t() {} 35: flx_dynlink_t::flx_dynlink_t(flx_dynlink_t const&) {} // no copy hack 36: void flx_dynlink_t::operator=(flx_dynlink_t const&) {} // no copy hack 37: 38: flx_dynlink_t::flx_dynlink_t() : 39: library(0), 40: filename(""), 41: thread_frame_creator(NULL), 42: start_sym(NULL), 43: main_sym(NULL), 44: refcnt(0) 45: {} 46: 47: LIBHANDLE 48: flx_load_library(char const *filename) 49: { 50: LIBHANDLE library; 51: FLX_SET_NOLIBRARY(library); 52: 53: #ifndef FLX_STATIC_LINK 54: //#if defined(_WIN32) || defined(__CYGWIN__) 55: #if defined(_WIN32) 56: // stop windows showing err dialogues, ignoring error code. 57: (void)SetErrorMode(SEM_NOOPENFILEERRORBOX); 58: library = LoadLibrary(filename); 59: if(FLX_CHECK_NOLIBRARY(library)) 60: throw flx_link_failure_t(filename,"LoadLibrary","Cannot find dll"); 61: #else 62: #ifdef MACOSX_NODLCOMPAT 63: NSObjectFileImage bndl_img; 64: NSObjectFileImageReturnCode res; 65: 66: res = NSCreateObjectFileImageFromFile(filename, &bndl_img); 67: 68: if(NSObjectFileImageSuccess != res) 69: throw flx_link_failure_t(filename, "NSCreateObjectFileImageFromFile", 70: "failure to open library"); 71: 72: // don't merge globals with loader's, load programmatically 73: // return on error allows us to continue without being terminated 74: 75: unsigned long link_flags; 76: link_flags = NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_RETURN_ON_ERROR; 77: library = NSLinkModule(bndl_img, filename, link_flags); 78: 79: // even if link failed, we do this 80: NSDestroyObjectFileImage(bndl_img); 81: 82: // more info can be gleaned about link errors from NSLinkEditError 83: if(FLX_CHECK_NOLIBRARY(library)) 84: throw flx_link_failure_t(filename, "NSLinkModule", "failed to link"); 85: 86: #else 87: library = dlopen(filename,RTLD_NOW); 88: if(FLX_CHECK_NOLIBRARY(library)) 89: throw flx_link_failure_t(filename,"dlopen",dlerror()); 90: #endif 91: #endif 92: #endif 93: return library; 94: } 95: 96: LIBHANDLE 97: flx_load_module(char const *fname) 98: { 99: int n = std::strlen(fname)+strlen(FLX_LIB_EXTENSION)+1; 100: char *f = (char*)std::malloc(n); 101: std::strcpy(f,fname); 102: std::strcat(f,FLX_LIB_EXTENSION); 103: LIBHANDLE lib = flx_load_library(f); 104: std::free(f); 105: return lib; 106: } 107: 108: void flx_dynlink_t::link(char const *fname) throw(flx_link_failure_t) 109: { 110: filename=fname; 111: library = flx_load_library(fname); 112: //fprintf(stderr,"File %s dlopened at %p ok\n",fname,library); 113: 114: thread_frame_creator = (thread_frame_creator_t) 115: DLSYM(library,create_thread_frame); 116: if(!thread_frame_creator) 117: throw flx_link_failure_t(filename,"dlsym","create_thread_frame"); 118: 119: //fprintf(stderr,"Thread frame creator found at %p\n",thread_frame_creator); 120: 121: start_sym = (start_t)DLSYM(library,flx_start); 122: if(!start_sym) 123: throw flx_link_failure_t(filename,"dlsym","flx_start"); 124: 125: main_sym = (main_t)DLSYM(library,flx_main); 126: 127: //fprintf(stderr,"Start symbol found at %p\n",start_sym); 128: //fprintf(stderr,"main symbol found at %p\n",main_sym); 129: 130: refcnt = 1L; 131: 132: //fprintf(stderr,"Set refcnt to 1\n"); 133: try { usr_link(); } 134: catch (flx_link_failure_t &) { throw; } 135: catch (...) { 136: throw flx_link_failure_t 137: ( 138: filename, 139: "usr_link()", 140: "Unknown user exception" 141: ); 142: } 143: } 144: 145: void flx_dynlink_t::unlink() 146: { 147: --refcnt; 148: if(refcnt == 0) { 149: //fprintf(stderr,"closing library\n"); 150: #ifndef FLX_STATIC_LINK 151: //#if defined(_WIN32) || defined(__CYGWIN__) 152: #if defined(_WIN32) 153: FreeLibrary(library); 154: #else 155: #ifdef MACOSX_NODLCOMPAT 156: NSUnLinkModule(library, NSUNLINKMODULE_OPTION_NONE); 157: #else 158: dlclose(library); 159: #endif 160: #endif 161: #endif 162: } 163: } 164: 165: void flx_dynlink_t::usr_link(){} 166: 167: flx_libinit_t::~flx_libinit_t(){} 168: flx_libinit_t::flx_libinit_t() : 169: thread_frame (NULL), 170: start_proc (NULL), 171: main_proc (NULL), 172: lib (NULL), 173: collector(NULL) 174: {} 175: 176: flx_libinit_t::flx_libinit_t(flx_libinit_t const&){} 177: void flx_libinit_t::operator=(flx_libinit_t const&){} 178: 179: void flx_libinit_t::create 180: ( 181: flx_dynlink_t *lib_a, 182: flx::gc::generic::collector_t *collector_a, 183: main_t main_sym, 184: int argc, 185: char **argv, 186: FILE *stdin_, 187: FILE *stdout_, 188: FILE *stderr_ 189: ) 190: { 191: lib = lib_a; 192: collector = collector_a; 193: thread_frame = lib->thread_frame_creator( 194: collector 195: ); 196: //fprintf(stderr,"Incrementing refcnt\n"); 197: ++lib->refcnt; 198: collector->add_root(thread_frame); 199: start_proc = lib->start_sym(thread_frame, argc, argv, stdin_,stdout_,stderr_); 200: main_proc = main_sym?main_sym(thread_frame):0; 201: usr_create(); 202: } 203: 204: void flx_libinit_t::usr_create(){} 205: 206: void flx_libinit_t::destroy () { 207: usr_destroy(); 208: collector->remove_root(thread_frame); 209: //fprintf(stderr,"Decrementing refcnt\n"); 210: //fprintf(stderr,"Ref cnt=%ld\n",lib->refcnt); 211: --lib->refcnt; 212: //fprintf(stderr,"Ref cnt=%ld\n",lib->refcnt); 213: } 214: 215: void flx_libinit_t::usr_destroy (){} 216: 217: con_t *flx_libinit_t::bind_proc(void *fn, void *data) { 218: typedef con_t *(*binder_t)(void *,void*); 219: return ((binder_t)fn)(thread_frame,data); 220: } 221: 222: }} // namespaces 223:
1: #line 2337 "./lpsrc/flx_rtl.pak" 2: #ifndef _FLX_SYNC 3: #define _FLX_SYNC 4: 5: #include "flx_gc.hpp" 6: #include "flx_dynlink.hpp" 7: #include "flx_rtl.hpp" 8: #include <list> 9: 10: namespace flx { namespace run { 11: 12: enum fstate_t { terminated, blocked, delegated }; 13: enum fpc_t { next_fthread_pos, next_request_pos }; 14: 15: RTL_EXTERN char const * get_fstate_desc(fstate_t); 16: RTL_EXTERN char const * get_fpc_desc(fpc_t); 17: 18: struct RTL_EXTERN gc_profile_t { 19: bool debug_allocations; 20: bool debug_collections; 21: unsigned long compact; 22: unsigned long gc_freq; 23: unsigned long gc_counter; 24: unsigned long collections; 25: bool finalise; 26: flx::gc::generic::collector_t *collector; 27: 28: gc_profile_t ( 29: bool debug_allocations_, 30: bool debug_collections_, 31: unsigned long compact_, 32: unsigned long gc_freq_, 33: bool finalise_, 34: flx::gc::generic::collector_t *collector 35: ); 36: ~gc_profile_t(); 37: }; 38: 39: struct RTL_EXTERN sync_state_t { 40: bool debug_driver; 41: gc_profile_t *gcp; 42: std::list<flx::rtl::fthread_t*> *active; 43: flx::rtl::fthread_t *ft; 44: flx::rtl::_uctor_ *request; 45: fpc_t pc; 46: fstate_t fs; 47: sync_state_t ( 48: bool debug_driver_, 49: gc_profile_t *gcp_, 50: std::list<flx::rtl::fthread_t*> *active_ 51: ); 52: void frun(); 53: }; 54: 55: }} 56: 57: #endif 58:
1: #line 2396 "./lpsrc/flx_rtl.pak" 2: #include "flx_sync.hpp" 3: using namespace flx::rtl; 4: 5: namespace flx { namespace run { 6: 7: RTL_EXTERN char const *get_fstate_desc(fstate_t fs) 8: { 9: switch(fs) 10: { 11: case terminated: return "terminated"; 12: case blocked: return "blocked"; 13: case delegated: return "delegated"; 14: default: return "Illegal fstate_t"; 15: } 16: } 17: 18: RTL_EXTERN char const *get_fpc_desc(fpc_t fpc) 19: { 20: switch(fpc) 21: { 22: case next_fthread_pos: return "Next fthread pos"; 23: case next_request_pos: return "Next request pos"; 24: default: return "Illegal fpc_t"; 25: } 26: } 27: 28: 29: gc_profile_t::gc_profile_t ( 30: bool debug_allocations_, 31: bool debug_collections_, 32: unsigned long compact_, 33: unsigned long gc_freq_, 34: bool finalise_, 35: flx::gc::generic::collector_t *collector_ 36: ) : 37: debug_allocations(debug_allocations_), 38: debug_collections(debug_collections_), 39: compact(compact_), 40: gc_freq(gc_freq_), 41: gc_counter(0), 42: collections(0), 43: finalise(finalise_), 44: collector(collector_) 45: { 46: } 47: 48: gc_profile_t::~gc_profile_t() { } 49: 50: sync_state_t::sync_state_t ( 51: bool debug_driver_, 52: gc_profile_t *gcp_, 53: std::list<fthread_t*> *active_ 54: ) : 55: debug_driver(debug_driver_), 56: gcp(gcp_), 57: active(active_), 58: pc(next_fthread_pos) 59: {} 60: 61: void sync_state_t::frun() 62: { 63: // local copies are faster 64: flx::gc::generic::collector_t *collector = gcp->collector; 65: 66: // dispatch 67: if (pc == next_request_pos) goto next_request; 68: if (pc == next_fthread_pos) goto next_fthread; 69: fprintf(stderr,"BUG -- unreachable code in frun\n"); 70: abort(); 71: 72: next_fthread: 73: if (active->size() == 0) { 74: fs = blocked; 75: pc = next_fthread_pos; 76: return; 77: } 78: ft = active->front(); 79: active->pop_front(); 80: 81: next_request: 82: request = ft->run(); 83: if(request != 0) goto check_collect; 84: 85: forget_fthread: 86: if(debug_driver)fprintf(stderr,"unrooting fthread %p\n",ft); 87: collector->remove_root(ft); 88: goto next_fthread; 89: 90: delegate: 91: pc = next_request_pos; 92: fs = delegated; 93: return; 94: 95: check_collect: 96: //gcp->gc_counter++; 97: //if(gcp->gc_counter == gcp->gc_freq) 98: //{ 99: // gcp->gc_counter = 0; 100: // gcp->collections++; 101: // unsigned long n = collector->collect(); 102: // if(gcp->compact) collector->compact(true); 103: // if(gcp->debug_collections)fprintf(stderr,"collected %ld objects\n",n); 104: //} 105: 106: switch(request->variant) 107: { 108: case svc_yield: 109: { 110: if(debug_driver)fprintf(stderr,"yield"); 111: active->push_back(ft); 112: } 113: goto next_fthread; 114: 115: case svc_spawn_detached: 116: { 117: fthread_t *ftx = *(fthread_t**)request->data; 118: if(debug_driver)fprintf(stderr,"Spawn thread %p\n",ftx); 119: collector->add_root(ftx); 120: active->push_front(ftx); 121: } 122: goto next_request; 123: 124: case svc_sread: 125: { 126: readreq_t * pr = (readreq_t*)request->data; 127: schannel_t *chan = pr->chan; 128: if(debug_driver)fprintf(stderr,"Request to read on channel %p\n",chan); 129: svc_read_next: 130: { 131: fthread_t *writer= chan->pop_writer(); 132: if(writer == 0) goto svc_read_none; // no writers 133: if(writer->cc == 0) goto svc_read_next; // killed 134: { 135: readreq_t * pr = (readreq_t*)request->data; 136: readreq_t * pw = (readreq_t*)writer->get_svc()->data; 137: if(debug_driver)fprintf(stderr,"Writer @%p=%p, read into %p\n", pw->variable.get_data(),*(void**)pw->variable.get_data(), pr->variable.get_data()); 138: *(void**)pr->variable.get_data() = *(void**)pw->variable.get_data(); 139: active->push_front(writer); 140: collector->add_root(writer); 141: } 142: } 143: goto next_request; 144: 145: svc_read_none: 146: if(debug_driver)fprintf(stderr,"No writers on channel %p: BLOCKING\n",chan); 147: chan->push_reader(ft); 148: } 149: goto forget_fthread; 150: 151: case svc_swrite: 152: { 153: readreq_t * pr = (readreq_t*)request->data; 154: schannel_t *chan = pr->chan; 155: if(debug_driver)fprintf(stderr,"Request to write on channel %p\n",chan); 156: svc_write_next: 157: { 158: fthread_t *reader= chan->pop_reader(); 159: if(reader == 0) goto svc_write_none; // no readers 160: if(reader->cc == 0) goto svc_write_next; // killed 161: { 162: readreq_t * pw = (readreq_t*)request->data; 163: readreq_t * pr = (readreq_t*)reader->get_svc()->data; 164: if(debug_driver)fprintf(stderr,"Writer @%p=%p, read into %p\n", pw->variable.get_data(),*(void**)pw->variable.get_data(), pr->variable.get_data()); 165: *(void**)pr->variable.get_data() = *(void**)pw->variable.get_data(); 166: active->push_front(reader); 167: collector->add_root(reader); 168: } 169: } 170: goto next_request; 171: 172: svc_write_none: 173: if(debug_driver)fprintf(stderr,"No readers on channel %p: BLOCKING\n",chan); 174: chan->push_writer(ft); 175: } 176: goto forget_fthread; 177: 178: case svc_kill: 179: { 180: fthread_t *ftx = *(fthread_t**)request->data; 181: if(debug_driver)fprintf(stderr,"Request to kill fthread %p\n",ftx); 182: ftx -> kill(); 183: } 184: goto next_request; 185: 186: default: goto delegate; 187: } 188: fprintf(stderr,"BUG unreachable code executed\n"); 189: abort(); 190: } 191: 192: }} 193: