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