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 1627 "./lpsrc/flx_rtl.pak" 2: #ifndef __FLX_DYNLINK_H__ 3: #define __FLX_DYNLINK_H__ 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 FLX_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 FLX_MACOSX_NODLCOMPAT 21: #include <sys/stat.h> 22: #include <mach-o/dyld.h> 23: typedef NSModule LIBHANDLE; 24: #define FLX_SET_NOLIBRARY(lib) lib=NULL 25: #define FLX_CHECK_NOLIBRARY(lib) (lib==NULL) 26: #define FLX_LIB_EXTENSION ".dylib" 27: #define FLX_DLSYM(x, y) flx::rtl::getmachosym(x,"_"#y) 28: #define FLX_SDLSYM(x, y) flx::rtl::getmachosym(x,(string("_")+string(y)).data()) 29: #else 30: // UNIX, recent OSX 31: typedef void *LIBHANDLE; 32: #define FLX_SET_NOLIBRARY(lib) lib=NULL 33: #define FLX_CHECK_NOLIBRARY(lib) (lib==NULL) 34: #if FLX_CYGWIN 35: #define FLX_LIB_EXTENSION ".dll" 36: #elif FLX_MACOSX 37: #define FLX_LIB_EXTENSION ".dylib" 38: #else 39: #define FLX_LIB_EXTENSION ".so" 40: #endif 41: #include <dlfcn.h> 42: #define FLX_DLSYM(x,y) dlsym(x,#y) 43: #define FLX_SDLSYM(x,y) dlsym(x,y) 44: #endif 45: 46: #ifndef FLX_STATIC_LINK 47: #define DLSYM(x,y) FLX_DLSYM(x,y) 48: #define SDLSYM(x,y) FLX_SDLSYM(x,y) 49: #else 50: #define DLSYM(x,y) (void*)&y 51: #define SDLSYM(x,y) (throw flx::rtl::link_failure_t("<static link>",y,"dlsym with static link requires name not string") 52: #endif 53: 54: // Utilities to make dynamic linkage and 55: // initialisation of Felix modules easier 56: // 57: // We provide a standard exception to report 58: // link failure (missing symbol). 59: // 60: // We provide a class flx_dynlink_t which 61: // opens a Felix shared library given a filename, 62: // and links the mandatory symbols 63: // The user may derive from this class to add 64: // linkage for extra symbols 65: // 66: // We provide a class flx_libinit_t which 67: // initialises and terminates a Felix module 68: // The user may derive from this class to add 69: // extra initialisation or termination processing. 70: // 71: // [Note: the virtuals are *deliberately* private. 72: // Be sure to make your overrides private too, 73: // so they cannot be called: 74: // they're dispatched automatically by wrappers 75: // defined in the base] 76: 77: // must be at global scope, because the users' is 78: struct thread_frame_t; 79: 80: namespace flx { namespace rtl { 81: 82: struct RTL_EXTERN flx_link_failure_t; 83: struct RTL_EXTERN flx_dynlink_t; 84: struct RTL_EXTERN flx_libinit_t; 85: 86: /// Dynamic linkage failure. 87: 88: struct RTL_EXTERN flx_link_failure_t : flx_exception_t { 89: string filename; 90: string operation; 91: string what; 92: flx_link_failure_t(string f, string o, string w); 93: virtual ~flx_link_failure_t(); 94: }; 95: 96: RTL_EXTERN LIBHANDLE 97: flx_load_library(char const *fname); 98: 99: RTL_EXTERN LIBHANDLE 100: flx_load_module(char const *fname); 101: 102: /// frame creators. 103: 104: typedef thread_frame_t *(*thread_frame_creator_t) 105: ( 106: flx::gc::generic::collector_t* 107: ); 108: 109: /// library initialisation routine. 110: 111: typedef con_t *(*start_t) 112: ( 113: thread_frame_t*, 114: int, 115: char **, 116: FILE*, 117: FILE*, 118: FILE* 119: 120: ); 121: 122: typedef con_t *(*main_t)(thread_frame_t*); 123: 124: /// dynamic object loader. 125: 126: struct RTL_EXTERN flx_dynlink_t 127: { 128: // data 129: LIBHANDLE library; 130: string filename; 131: thread_frame_creator_t thread_frame_creator; 132: start_t start_sym; 133: main_t main_sym; 134: long refcnt; 135: 136: // routines 137: void link(char const *filename) throw(flx_link_failure_t); 138: void unlink(); 139: virtual ~flx_dynlink_t(); 140: flx_dynlink_t(); 141: 142: private: 143: // the user should override this procedure to 144: // link any extra symbols. 145: // on error, throw a flx_link_failure_t, 146: // otherwise your exception will be dishonoured 147: // and a generic link_failure_t thrown anyhow 148: 149: flx_dynlink_t(flx_dynlink_t const&); // uncopyable 150: void operator=(flx_dynlink_t const&); // uncopyable 151: virtual void usr_link(); 152: // called after mandatory symbols are linked 153: }; 154: 155: /// Thread Frame Initialisation. 156: 157: struct RTL_EXTERN flx_libinit_t 158: { 159: thread_frame_t *thread_frame; 160: con_t *start_proc; 161: con_t *main_proc; 162: flx_dynlink_t *lib; 163: flx::gc::generic::collector_t *collector; 164: void create 165: ( 166: flx_dynlink_t *lib_a, 167: flx::gc::generic::collector_t *collector_a, 168: main_t main_sym, 169: int argc, 170: char **argv, 171: FILE *stdin_, 172: FILE *stdout_, 173: FILE *stderr_ 174: ); 175: 176: void destroy (); 177: 178: con_t *bind_proc(void *fn, void *data); 179: virtual ~flx_libinit_t(); 180: flx_libinit_t(); 181: 182: private: 183: flx_libinit_t(flx_libinit_t const&); 184: void operator=(flx_libinit_t const&); 185: // the user can override these procedures 186: // to perform any additional initialisation 187: // and termination required. 188: 189: virtual void usr_create(); 190: // called after standard init completes 191: 192: virtual void usr_destroy(); 193: // called before standard destroy starts 194: }; 195: 196: #if FLX_MACOSX_NODLCOMPAT 197: void* getmachosym(LIBHANDLE, const char*); 198: #endif 199: 200: }} // namespaces 201: #endif
1: #line 1830 "./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: #if FLX_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 FLX_WIN32 || FLX_CYGWIN 55: #if FLX_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: #if FLX_MACOSX_NODLCOMPAT 63: NSObjectFileImage bndl_img; 64: NSObjectFileImageReturnCode res; 65: 66: string s_filename(filename); 67: struct stat st; 68: 69: if (stat(s_filename.c_str(), &st) != 0) { 70: // we can't find the file, so search DYLD_LIBRARY_PATH 71: string paths = getenv("DYLD_LIBRARY_PATH"); 72: 73: size_t i = 0; 74: bool found = false; 75: 76: while ((i = paths.find_first_of(':')) != paths.npos) { 77: string s = paths.substr(0, i) + '/' + filename; 78: paths = paths.substr(i + 1); 79: 80: if (stat(s.c_str(), &st) == 0) { 81: s_filename = s; 82: found = true; 83: break; 84: } 85: } 86: 87: if (!found) { 88: throw flx_link_failure_t(filename, "stat", 89: string("cannot find file: ") + filename); 90: } 91: } 92: 93: res = NSCreateObjectFileImageFromFile(s_filename.c_str(), &bndl_img); 94: 95: if(NSObjectFileImageSuccess != res) 96: throw flx_link_failure_t(filename, "NSCreateObjectFileImageFromFile", 97: "failure to open library"); 98: 99: // don't merge globals with loader's, load programmatically 100: // return on error allows us to continue without being terminated 101: 102: unsigned long link_flags; 103: link_flags = NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_RETURN_ON_ERROR; 104: library = NSLinkModule(bndl_img, filename, link_flags); 105: 106: // even if link failed, we do this 107: NSDestroyObjectFileImage(bndl_img); 108: 109: // more info can be gleaned about link errors from NSLinkEditError 110: if(FLX_CHECK_NOLIBRARY(library)) 111: throw flx_link_failure_t(filename, "NSLinkModule", "failed to link"); 112: 113: #else 114: library = dlopen(filename,RTLD_NOW); 115: if(FLX_CHECK_NOLIBRARY(library)) 116: throw flx_link_failure_t(filename,"dlopen",dlerror()); 117: #endif 118: #endif 119: #endif 120: return library; 121: } 122: 123: LIBHANDLE 124: flx_load_module(char const *fname) 125: { 126: int n = std::strlen(fname)+strlen(FLX_LIB_EXTENSION)+1; 127: char *f = (char*)std::malloc(n); 128: std::strcpy(f,fname); 129: std::strcat(f,FLX_LIB_EXTENSION); 130: LIBHANDLE lib = flx_load_library(f); 131: std::free(f); 132: return lib; 133: } 134: 135: void flx_dynlink_t::link(char const *fname) throw(flx_link_failure_t) 136: { 137: filename=fname; 138: library = flx_load_library(fname); 139: //fprintf(stderr,"File %s dlopened at %p ok\n",fname,library); 140: 141: thread_frame_creator = (thread_frame_creator_t) 142: DLSYM(library,create_thread_frame); 143: if(!thread_frame_creator) 144: throw flx_link_failure_t(filename,"dlsym","create_thread_frame"); 145: 146: //fprintf(stderr,"Thread frame creator found at %p\n",thread_frame_creator); 147: 148: start_sym = (start_t)DLSYM(library,flx_start); 149: if(!start_sym) 150: throw flx_link_failure_t(filename,"dlsym","flx_start"); 151: 152: main_sym = (main_t)DLSYM(library,flx_main); 153: 154: //fprintf(stderr,"Start symbol found at %p\n",start_sym); 155: //fprintf(stderr,"main symbol found at %p\n",main_sym); 156: 157: refcnt = 1L; 158: 159: //fprintf(stderr,"Set refcnt to 1\n"); 160: try { usr_link(); } 161: catch (flx_link_failure_t &) { throw; } 162: catch (...) { 163: throw flx_link_failure_t 164: ( 165: filename, 166: "usr_link()", 167: "Unknown user exception" 168: ); 169: } 170: } 171: 172: void flx_dynlink_t::unlink() 173: { 174: --refcnt; 175: if(refcnt == 0) { 176: //fprintf(stderr,"closing library\n"); 177: #ifndef FLX_STATIC_LINK 178: //#if FLX_WIN32 || FLX_CYGWIN 179: #if FLX_WIN32 180: FreeLibrary(library); 181: #else 182: #if FLX_MACOSX_NODLCOMPAT 183: NSUnLinkModule(library, NSUNLINKMODULE_OPTION_NONE); 184: #else 185: dlclose(library); 186: #endif 187: #endif 188: #endif 189: } 190: } 191: 192: void flx_dynlink_t::usr_link(){} 193: 194: flx_libinit_t::~flx_libinit_t(){} 195: flx_libinit_t::flx_libinit_t() : 196: thread_frame (NULL), 197: start_proc (NULL), 198: main_proc (NULL), 199: lib (NULL), 200: collector(NULL) 201: {} 202: 203: flx_libinit_t::flx_libinit_t(flx_libinit_t const&){} 204: void flx_libinit_t::operator=(flx_libinit_t const&){} 205: 206: void flx_libinit_t::create 207: ( 208: flx_dynlink_t *lib_a, 209: flx::gc::generic::collector_t *collector_a, 210: main_t main_sym, 211: int argc, 212: char **argv, 213: FILE *stdin_, 214: FILE *stdout_, 215: FILE *stderr_ 216: ) 217: { 218: lib = lib_a; 219: collector = collector_a; 220: thread_frame = lib->thread_frame_creator( 221: collector 222: ); 223: //fprintf(stderr,"Incrementing refcnt\n"); 224: ++lib->refcnt; 225: collector->add_root(thread_frame); 226: start_proc = lib->start_sym(thread_frame, argc, argv, stdin_,stdout_,stderr_); 227: main_proc = main_sym?main_sym(thread_frame):0; 228: usr_create(); 229: } 230: 231: void flx_libinit_t::usr_create(){} 232: 233: void flx_libinit_t::destroy () { 234: usr_destroy(); 235: collector->remove_root(thread_frame); 236: //fprintf(stderr,"Decrementing refcnt\n"); 237: //fprintf(stderr,"Ref cnt=%ld\n",lib->refcnt); 238: --lib->refcnt; 239: //fprintf(stderr,"Ref cnt=%ld\n",lib->refcnt); 240: } 241: 242: void flx_libinit_t::usr_destroy (){} 243: 244: con_t *flx_libinit_t::bind_proc(void *fn, void *data) { 245: typedef con_t *(*binder_t)(void *,void*); 246: return ((binder_t)fn)(thread_frame,data); 247: } 248: 249: }} // namespaces
1: #line 2081 "./lpsrc/flx_rtl.pak" 2: #ifndef __FLX_SYNC_H__ 3: #define __FLX_SYNC_H__ 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
1: #line 2140 "./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: }}