1.2. Unix Dynamic linker

This is a Unix specific module, which uses dlopen and friends to dynamically attach a shared file representing a felix top level module to an application, and extract the standard symbols from it.

The link routine links the following symbols, which must be present in all felix libraries.

  create_thread_frame
  start
The 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.

Start cpp section to rtl/flx_dynlink.hpp[1 /1 ]
     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
End cpp section to rtl/flx_dynlink.hpp[1]
Start cpp section to rtl/flx_dynlink.cpp[1 /1 ]
     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
End cpp section to rtl/flx_dynlink.cpp[1]
Start cpp section to rtl/flx_sync.hpp[1 /1 ]
     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
End cpp section to rtl/flx_sync.hpp[1]
Start cpp section to rtl/flx_sync.cpp[1 /1 ]
     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: }}
End cpp section to rtl/flx_sync.cpp[1]