For statically linked programs, command line arguments are passed directly, the debugging switch isn't supported.
For dynamically loaded programs, the name of the driver and optional --debug switch given before the shared library name are not passed.
1: #line 2604 "./lpsrc/flx_rtl.pak" 2: #ifndef __FLX_ASYNC__ 3: #define __FLX_ASYNC__ 4: #include "flx_rtl_config.hpp" 5: #include "flx_rtl.hpp" 6: 7: #ifdef BUILD_ASYNC 8: #define ASYNC_EXTERN FLX_EXPORT 9: #else 10: #define ASYNC_EXTERN FLX_IMPORT 11: #endif 12: 13: // GLOBAL NAMESPACE! 14: 15: class ASYNC_EXTERN async_hooker { 16: public: 17: virtual flx::rtl::fthread_t *dequeue()=0; 18: virtual bool handle_request(void *data, flx::rtl::fthread_t *ss)=0; 19: virtual ~async_hooker(); 20: }; 21: 22: typedef 23: async_hooker * 24: create_async_hooker_t 25: ( 26: int n0, // bound on resumable thread queue 27: int n1, // bound on general input job queue 28: int m1, // number of threads in job pool 29: int n2, // bound on async fileio job queue 30: int m2 // number of threads doing async fileio 31: ); 32: 33: extern "C" { 34: ASYNC_EXTERN async_hooker * 35: create_async_hooker 36: ( 37: int n0, // bound on resumable thread queue 38: int n1, // bound on general input job queue 39: int m1, // number of threads in job pool 40: int n2, // bound on async fileio job queue 41: int m2 // number of threads doing async fileio 42: ); 43: } 44: 45: #endif 46:
1: #line 2651 "./lpsrc/flx_rtl.pak" 2: #include "flx_async.hpp" 3: #include "pthread_sleep_queue.hpp" 4: #include "flx_rtl.hpp" 5: #include "demux_demuxer.hpp" 6: #include "faio_drv.hpp" 7: 8: using namespace flx::rtl; 9: using namespace flx::demux; 10: using namespace flx::faio; 11: using namespace flx::pthread; 12: 13: 14: class async_hooker_impl : public async_hooker { 15: virtual flx::faio::flx_drv *get_driver()=0; 16: virtual flx::demux::demuxer *get_demuxer()=0; 17: public: 18: bool handle_request(void *data,fthread_t *ss); 19: ~async_hooker_impl(); 20: }; 21: 22: 23: #ifdef _WIN32 24: #include "demux_iocp_demuxer.hpp" 25: #include "faio_wdrv.hpp" 26: typedef flx::demux::iocp_demuxer flx_demuxer; 27: #elif defined(HAVE_KQUEUE_DEMUXER) 28: #include "demux_kqueue_demuxer.hpp" 29: #include "faio_pdrv.hpp" 30: typedef flx::demux::kqueue_demuxer flx_demuxer; 31: #elif defined(HAVE_EVTPORTS) 32: #include "demux_evtport_demuxer.hpp" 33: #include "faio_pdrv.hpp" 34: typedef flx::demux::evtport_demuxer flx_demuxer; 35: #elif defined(HAVE_EPOLL) 36: #include "demux_epoll_demuxer.hpp" 37: #include "faio_pdrv.hpp" 38: typedef flx::demux::epoll_demuxer flx_demuxer; 39: #elif defined(HAVE_POLL) 40: // NB!: on osx 10.3 poll exists, but is a poor cousin emulation layer on 41: // top of select. however, 10.3 has kqueues (above), so should be ok... 42: #include "demux_ts_poll_demuxer.hpp" 43: #include "faio_pdrv.hpp" 44: typedef flx::demux::ts_poll_demuxer flx_demuxer; 45: #else 46: #include "demux_ts_select_demuxer.hpp" 47: #include "faio_pdrv.hpp" 48: typedef flx::demux::ts_select_demuxer flx_demuxer; // thread safe! 49: #endif 50: 51: #include "faio_asyncio.hpp" 52: 53: async_hooker::~async_hooker(){ 54: //fprintf(stderr,"Deleted async_hooker\n"); 55: } 56: 57: async_hooker_impl::~async_hooker_impl(){ 58: //fprintf(stderr,"Deleted async_hooker_impl\n"); 59: } 60: 61: bool async_hooker_impl::handle_request(void *data,fthread_t *ft) 62: { 63: flx::faio::flx_driver_request_base* dreq = 64: (flx::faio::flx_driver_request_base*)data 65: ; 66: 67: //fprintf(stderr,"Request object at %p\n",dreq); 68: // RF hates the flag this function returns .. might 69: // mask a race condition, get rid of it 70: 71: bool result =dreq->start_async_op( 72: *get_demuxer(), 73: get_driver(), 74: ft) 75: ; 76: return result; 77: } 78: 79: class proto_async : public async_hooker_impl 80: { 81: flx_demuxer demux; 82: 83: sleep_queue_t async_active; 84: flx_thread_t ethread; 85: 86: #ifdef _WIN32 87: wflx_drv driver; 88: static DWORD pthread_thread(LPVOID udat); 89: #else 90: pflx_drv driver; 91: static void* pthread_thread(void* udat); 92: #endif 93: 94: public: 95: proto_async(int n0, int n1, int m1, int n2, int m2) : 96: async_active(n0), driver(async_active,n1,m1,n2,m2) 97: { 98: // start waiting thread. note that we only have ONE event waiting thread. 99: // that's currently important for clean takedowns 100: #if _WIN32 101: // cast callback to itself. go figure. 102: if(ethread.init((LPTHREAD_START_ROUTINE)pthread_thread, &demux) == -1) throw -1; 103: #else 104: if(ethread.init(pthread_thread, &demux) == -1) throw -1; 105: #endif 106: } 107: 108: ~proto_async(){ 109: //fprintf(stderr,"Deleting proto async\n"); 110: } 111: flx_drv *get_driver() { return &driver; } 112: demuxer *get_demuxer(){ return &demux; } 113: fthread_t* dequeue() 114: { 115: return (fthread_t*)async_active.dequeue(); 116: } 117: }; 118: 119: #ifdef _WIN32 120: DWORD 121: proto_async::pthread_thread(LPVOID udat) 122: #else 123: void* 124: proto_async::pthread_thread(void* udat) 125: #endif 126: { 127: demuxer* d = (demuxer*)udat; 128: 129: while(1) 130: { 131: //fprintf(stderr, "ETHREAD ABOUT TO WAIT\n"); 132: d->wait(); // this does it 133: //fprintf(stderr, "ETHREAD CHECKING QUIT FLAG\n"); 134: demux_quit_flag* f = d->get_quit_flag(); 135: if(f) 136: { 137: // got a quit flag - this is the very last thing we do before 138: // exiting. don't use the demuxer after this as it's probably been 139: // destructed. 140: //fprintf(stderr, "ETHREAD GOT QUIT FLAG, SIGNALLING AND EXITING\n"); 141: f->signal_true(); 142: // in the case of a system takedown there's no guarantee that 143: // anything after the signal_finish will be run at all, so this 144: // is not a good place to put anything important. 145: break; // outta here 146: } 147: } 148: //fprintf(stderr, "ETHREAD EXITING\n"); 149: // fprintf(stderr, "proto_async was asked to quit...\n"); 150: return 0; 151: } 152: 153: async_hooker *create_async_hooker(int n0,int n1,int m1,int n2,int m2) { 154: return new proto_async(n0,n1,m1,n2,m2); 155: } 156:
1: #line 2808 "./lpsrc/flx_rtl.pak" 2: #ifndef __FLX_EH__ 3: #define __FLX_EH__ 4: #include "flx_rtl_config.hpp" 5: #include "flx_rtl.hpp" 6: 7: namespace flx { namespace rtl { 8: void RTL_EXTERN print_loc(FILE *ef,flx::rtl::flx_range_srcref_t x,char *cf, int cl); 9: int RTL_EXTERN std_exception_handler (std::exception *e); 10: int RTL_EXTERN flx_exception_handler (flx::rtl::flx_exception_t *e); 11: }} 12: 13: #endif 14:
1: #line 2823 "./lpsrc/flx_rtl.pak" 2: #include <stdio.h> 3: #include "flx_rtl.hpp" 4: #include "flx_dynlink.hpp" 5: #include "flx_eh.hpp" 6: using namespace flx::rtl; 7: 8: void flx::rtl::print_loc(FILE *ef,flx_range_srcref_t x,char *cf, int cl) 9: { 10: fprintf(ef,"Felix location: %s %d[%d]-%d[%d]\n", 11: x.filename, 12: x.startline, 13: x.startcol, 14: x.endline, 15: x.endcol 16: ); 17: fprintf(ef,"C++ location : %s %d\n", cf, cl); 18: } 19: 20: 21: int flx::rtl::std_exception_handler (std::exception *e) 22: { 23: fprintf(stderr,"C++ STANDARD EXCEPTION %s\n",e->what()); 24: return 4; 25: } 26: 27: int flx::rtl::flx_exception_handler (flx_exception_t *e) 28: { 29: if (flx_link_failure_t *x = dynamic_cast<flx_link_failure_t*>(e)) 30: { 31: fprintf(stderr,"Dynamic linkage error\n"); 32: fprintf(stderr,"filename: %s\n",x->filename.data()); 33: fprintf(stderr,"operation: %s\n",x->operation.data()); 34: fprintf(stderr,"what: %s\n",x->what.data()); 35: return 2; 36: } 37: else 38: if (flx_exec_failure_t *x = dynamic_cast<flx_exec_failure_t*>(e)) 39: { 40: fprintf(stderr,"Execution error\n"); 41: fprintf(stderr,"filename: %s\n",x->filename.data()); 42: fprintf(stderr,"operation: %s\n",x->operation.data()); 43: fprintf(stderr,"what: %s\n",x->what.data()); 44: return 3; 45: } 46: else 47: if (flx_assert_failure_t *x = dynamic_cast<flx_assert_failure_t*>(e)) 48: { 49: fprintf(stderr,"Assertion Failure\n"); 50: print_loc(stderr,x->flx_loc,x->cxx_srcfile, x->cxx_srcline); 51: return 3; 52: } 53: else 54: if (flx_assert2_failure_t *x = dynamic_cast<flx_assert2_failure_t*>(e)) 55: { 56: fprintf(stderr,"Assertion2 Failure\n"); 57: print_loc(stderr,x->flx_loc,x->cxx_srcfile, x->cxx_srcline); 58: print_loc(stderr,x->flx_loc2,x->cxx_srcfile, x->cxx_srcline); 59: return 3; 60: } 61: else 62: if (flx_match_failure_t *x = dynamic_cast<flx_match_failure_t*>(e)) 63: { 64: fprintf(stderr,"Match Failure\n"); 65: print_loc(stderr,x->flx_loc,x->cxx_srcfile, x->cxx_srcline); 66: return 3; 67: } 68: if (flx_range_failure_t *x = dynamic_cast<flx_range_failure_t*>(e)) 69: { 70: fprintf(stderr,"Range Check Failure\n"); 71: print_loc(stderr,x->flx_loc,x->cxx_srcfile, x->cxx_srcline); 72: return 3; 73: } 74: else 75: { 76: fprintf(stderr,"Unknown EXCEPTION!\n"); 77: return 5; 78: } 79: } 80:
1: #line 2904 "./lpsrc/flx_rtl.pak" 2: #include <cstdlib> 3: #include <stdio.h> 4: #include <vector> 5: #include <list> 6: #include <map> 7: #include <cstring> 8: #include <cassert> 9: 10: #include <string> 11: //#include <unistd.h> 12: #include "flx_rtl.hpp" 13: 14: #include "flx_async.hpp" 15: 16: #include "flx_ts_collector.hpp" 17: #include "flx_dynlink.hpp" 18: #include "flx_sync.hpp" 19: #include "pthread_thread.hpp" 20: #include "pthread_counter.hpp" 21: #include "flx_eh.hpp" 22: 23: using namespace std; 24: using namespace flx::rtl; 25: using namespace flx::pthread; 26: using namespace flx::run; 27: 28: #ifdef HAVE_GNU_X86 29: register void *sp __asm__("esp"); 30: #else 31: #ifdef HAVE_GNU_X86_64 32: register void *sp __asm__("rsp"); 33: #else 34: static void *sp = 0; 35: #endif 36: #endif 37: 38: // non async drivers aren't don't depend on faio<-demux<-winsock 39: // and so aren't linked with mswsock and ws2_32 40: #if defined(_WIN32) && defined(FLX_SUPPORT_ASYNC) 41: #include "demux_iocp_demuxer.hpp" 42: // needed to perform win socket io (calls WSAInit). Must happen 43: // before iocp_demuxer is instantiated and (I assume) happen 44: // only once. 45: // JS: No, it can be called any number of times, provided 46: // the destructor WSACleanup is called same number of times 47: // Use of this RAII object ensures WSAinit/Cleanup calls balance. 48: // RF: Still has to happen before any socket calls. Putting it in 49: // the async object which is created on command is already too late. 50: // If that's a problem then any socket creation calls would have to 51: // gratuitously make async calls. 52: flx::demux::winsock_initer wsinit; 53: #endif 54: 55: 56: int do_final_cleanup( 57: bool debug_driver, 58: gc_profile_t *gcp, 59: flx_dynlink_t *library, 60: flx_libinit_t *instance 61: ); 62: 63: class thread_control_t 64: { 65: unsigned int thread_counter; 66: bool do_world_stop; 67: flx_condv_t stop_guard; 68: flx_mutex_t stop_mutex; 69: public: 70: thread_control_t () : do_world_stop(false), thread_counter(0) 71: { 72: //fprintf(stderr,"INITIALISING THREAD CONTROL OBJECT\n"); 73: } 74: 75: int thread_count() { 76: flx_mutex_locker_t m(stop_mutex); 77: return thread_counter; 78: } 79: 80: void add_thread() { 81: flx_mutex_locker_t m(stop_mutex); 82: //fprintf(stderr, "Adding thread\n"); 83: ++thread_counter; 84: stop_guard.broadcast(); 85: } 86: void remove_thread() { 87: flx_mutex_locker_t m(stop_mutex); 88: //fprintf(stderr, "Removing thread\n"); 89: --thread_counter; 90: stop_guard.broadcast(); 91: } 92: 93: // stop the world! 94: bool world_stop() { 95: flx_mutex_locker_t m(stop_mutex); 96: //fprintf(stderr,"Stopping world\n"); 97: if (do_world_stop) return false; // race! Someone else beat us 98: do_world_stop = true; 99: --thread_counter; 100: while(thread_counter>0) stop_guard.wait(&stop_mutex); 101: //fprintf(stderr,"World STOPPED\n"); 102: return true; // we stopped the world 103: } 104: 105: // used by mainline to wait for other threads to die 106: void join_all() 107: { 108: flx_mutex_locker_t m(stop_mutex); 109: while(do_world_stop || thread_counter>0) stop_guard.wait(&stop_mutex); 110: //fprintf(stderr,"World restarted: do_world_stop=%d, Yield thread count now %d\n",do_world_stop,thread_counter); 111: } 112: 113: // restart the world 114: void world_start() { 115: flx_mutex_locker_t m(stop_mutex); 116: //fprintf(stderr,"Restarting world\n"); 117: ++thread_counter; 118: do_world_stop = false; 119: stop_guard.broadcast(); 120: } 121: 122: void yield() { 123: flx_mutex_locker_t m(stop_mutex); 124: if (do_world_stop) 125: { 126: //fprintf(stderr,"Yield found world stop!\n"); 127: --thread_counter; 128: //fprintf(stderr,"Yield thread count now %d\n",thread_counter); 129: stop_guard.broadcast(); 130: while(do_world_stop) stop_guard.wait(&stop_mutex); 131: ++thread_counter; 132: //fprintf(stderr,"World restarted: do_world_stop=%d, Yield thread count now %d\n",do_world_stop,thread_counter); 133: } 134: } 135: }; 136: 137: 138: struct doflx_data 139: { 140: bool debug_driver; 141: gc_profile_t *gcp; 142: std::list<fthread_t*> *active; 143: thread_control_t *thread_control; 144: doflx_data(bool d, gc_profile_t *g, std::list<fthread_t*> *a, thread_control_t *tc) 145: : debug_driver(d), gcp(g), active(a), thread_control(tc) {} 146: }; 147: 148: static 149: create_async_hooker_t *ptr_create_async_hooker = NULL; 150: 151: #ifdef _WIN32 152: DWORD 153: #else 154: void* 155: #endif 156: doflx (void *data) { 157: doflx_data *d = (doflx_data*)data; 158: bool debug_driver = d->debug_driver; 159: gc_profile_t *gcp = d-> gcp; 160: std::list<fthread_t*> *active = d->active; 161: thread_control_t *thread_control=d->thread_control; 162: delete d; 163: 164: unsigned long async_count = 0; 165: async_hooker* async = NULL; 166: 167: try 168: { 169: sync_state_t ss(debug_driver, gcp, active); 170: 171: process_active: 172: if(debug_driver)fprintf(stderr,"Process active .."); 173: 174: if(debug_driver) 175: fprintf(stderr,"Before running: Sync state is %s/%s\n", 176: get_fstate_desc(ss.fs),get_fpc_desc(ss.pc)); 177: 178: ss.frun(); 179: 180: if(debug_driver) 181: fprintf(stderr,"After running: Sync state is %s/%s\n", 182: get_fstate_desc(ss.fs),get_fpc_desc(ss.pc)); 183: 184: if (ss.fs == terminated) goto cleanup; 185: 186: //fprintf(stderr, "Thread yielding .."); 187: thread_control->yield(); 188: //fprintf(stderr, "..Thread resuming!\n"); 189: 190: if (ss.fs == blocked) goto do_async; 191: 192: if (ss.fs == delegated) 193: switch (ss.request->variant) 194: { 195: case svc_compact: 196: { 197: // requires fthreads to be immobile 198: if(debug_driver)fprintf(stderr,"svc compact\n"); 199: gcp->collector->compact(false); 200: } 201: goto process_active; 202: 203: case svc_collect: 204: { 205: // requires fthreads to be immobile 206: if(debug_driver)fprintf(stderr,"svc collect\n"); 207: if (thread_control->world_stop()) 208: { 209: if(debug_driver)fprintf(stderr,"ACTUALLY COLLECTING\n"); 210: gcp->collector->collect(); 211: thread_control->world_start(); 212: } 213: else { 214: if(debug_driver)fprintf(stderr,"RACE: someone else is collecting, just yield\n"); 215: thread_control->yield(); 216: } 217: } 218: goto process_active; 219: 220: case svc_collect_and_compact: 221: { 222: // requires fthreads to be immobile 223: if(debug_driver)fprintf(stderr,"svc collect and compact\n"); 224: if (thread_control->world_stop()) 225: { 226: gcp->collector->collect(); 227: gcp->collector->compact(true); 228: thread_control->world_start(); 229: } 230: else thread_control->yield(); 231: } 232: goto process_active; 233: 234: case svc_spawn_pthread: 235: { 236: fthread_t *ftx = *(fthread_t**)ss.request->data; 237: if(debug_driver)fprintf(stderr,"Spawn pthread %p\n",ftx); 238: gcp->collector->add_root(ftx); 239: std::list<fthread_t*> *pactive =new std::list<fthread_t*>; 240: pactive->push_front(ftx); 241: void *data = new doflx_data(debug_driver, gcp, pactive, thread_control); 242: flx_detached_thread_t dummy; 243: if(debug_driver)fprintf(stderr,"Starting new pthread, thread counter= %ld\n",thread_control->thread_count()); 244: thread_control->add_thread(); 245: dummy.init( 246: #ifdef _WIN32 247: (LPTHREAD_START_ROUTINE) 248: #endif 249: doflx,data); 250: } 251: goto process_active; 252: 253: case svc_general: 254: { 255: if(debug_driver) 256: fprintf(stderr,"svc_general from fthread=%p\n",ss.ft); 257: if( !async ) 258: { 259: if (ptr_create_async_hooker == NULL) 260: { 261: #ifndef FLX_SUPPORT_ASYNC 262: ptr_create_async_hooker = 0; 263: #else 264: ptr_create_async_hooker = create_async_hooker; 265: #ifndef FLX_STATIC_LINK 266: LIBHANDLE async_lib = flx_load_module("libflx_async_dynamic"); 267: if (async_lib == NULL) 268: { 269: fprintf(stderr,"Unable to find module 'libflx_async_dynamic'\n"); 270: exit(1); 271: } 272: // debug only .. 273: else { 274: if(debug_driver) 275: fprintf(stderr, "module 'libflx_async_dynamic' loaded!\n"); 276: } 277: ptr_create_async_hooker = (create_async_hooker_t*) 278: DLSYM(async_lib,create_async_hooker) 279: ; 280: if (ptr_create_async_hooker == NULL) 281: { 282: fprintf(stderr,"Unable to find symbol 'create_async_hooker' in module 'libflx_async_dynamic'\n"); 283: exit(1); 284: } 285: // debug only 286: else { 287: if(debug_driver) 288: fprintf(stderr, "found 'create_async_hooker'!\n"); 289: } 290: #endif 291: #endif 292: } 293: if (ptr_create_async_hooker == NULL) 294: { 295: fprintf(stderr,"Unable to initialise async I/O system: terminating\n"); 296: exit(1); 297: } 298: async = (*ptr_create_async_hooker)( 299: 20000, // bound on resumable thread queue 300: 50, // bound on general input job queue 301: 2, // number of threads in job pool 302: 50, // bound on async fileio job queue 303: 1 // number of threads doing async fileio 304: ); 305: } 306: ++async_count; 307: void *dreq = (((_ref_*)(ss.request->data))->get_data()); 308: 309: //fprintf(stderr,"Request object at %p\n",dreq); 310: // RF hates the flag this function returns .. might 311: // mask a race condition, get rid of it 312: if(!async->handle_request(dreq, ss.ft)) 313: { 314: ss.pc = next_fthread_pos; 315: } 316: else { 317: --async_count; 318: ss.pc = next_request_pos; 319: } 320: } 321: goto process_active; 322: 323: default: 324: fprintf(stderr,"Unknown service request code 0x%4x\n",ss.request->variant); 325: abort(); 326: } 327: fprintf(stderr,"Unknown frun return status 0x%4x\n",ss.fs); 328: abort(); 329: 330: do_async: 331: // ran out of active threads - are there any in the async queue? 332: if(debug_driver){ 333: fprintf(stderr, "out of active synchronous threads, trying async, count=%ld\n",async_count); 334: } 335: 336: if(async && async_count > 0){ 337: // STILL A ROOT 338: fthread_t* ftp = async->dequeue(); 339: if(debug_driver) 340: fprintf(stderr,"Async Retrieving fthread %p\n",ftp); 341: active->push_front(ftp); 342: --async_count; 343: ss.pc = next_fthread_pos; 344: goto process_active; 345: } 346: 347: if(debug_driver)fprintf(stderr,"Out of jobs\n"); 348: cleanup:; 349: } 350: catch (flx_exception_t &x) { flx_exception_handler (&x); } 351: catch (std::exception &x) { std_exception_handler (&x); } 352: catch (...) { fprintf(stderr,"Unknown exception in thread!\n"); } 353: 354: try 355: { 356: if(debug_driver)fprintf(stderr,"Terminating Felix subsystem\n"); 357: delete async; 358: delete active; 359: } 360: catch (...) { fprintf(stderr,"Unknown exception deleting async!\n"); } 361: 362: // if this fails the whole system is corrupted 363: thread_control->remove_thread(); 364: return 0; 365: } 366: 367: // RUN A FELIX INSTANCE IN THE CURRENT PTHREAD 368: // 369: // CURRENTLY ONLY CALLED ONCE IN MAIN THREAD 370: 371: int run_felix_pthread( 372: bool debug_driver, 373: gc_profile_t *gcp, 374: flx_dynlink_t *library, 375: flx_libinit_t *instance 376: ) 377: { 378: flx::gc::generic::collector_t *collector = gcp->collector; 379: std::list<fthread_t*> *active =new std::list<fthread_t*>; 380: 381: fthread_t *flx_main = NULL; 382: { 383: con_t *top = instance->main_proc; 384: if(top) 385: { 386: flx_main = new (*collector,_fthread_ptr_map) fthread_t(top); 387: collector->add_root(flx_main); 388: active->push_front(flx_main); 389: } 390: } 391: 392: { 393: con_t *top = instance->start_proc; 394: fthread_t *ft = new (*collector,_fthread_ptr_map) fthread_t(top); 395: collector->add_root(ft); 396: active->push_front(ft); 397: } 398: 399: { 400: thread_control_t thread_control; 401: thread_control.add_thread(); 402: 403: doflx(new doflx_data(debug_driver, gcp, active, &thread_control)); // deletes active for us! 404: 405: if(debug_driver)fprintf(stderr,"MAIN THREAD FINISHED: waiting for other threads\n"); 406: thread_control.join_all(); 407: if(debug_driver)fprintf(stderr,"ALL THREADS DEAD: mainline cleanup!\n"); 408: 409: if(debug_driver){ 410: unsigned long uncollected = collector->get_allocation_count(); 411: unsigned long roots = collector->get_root_count(); 412: fprintf(stderr, 413: "program finished, %ld collections, %ld uncollected objects, roots %ld\n", 414: gcp->collections,uncollected,roots); 415: } 416: } 417: 418: if(gcp->finalise) 419: do_final_cleanup(debug_driver, gcp, library, instance); 420: return 0; 421: } 422: 423: // terminates process! 424: // Not called by default (let the OS clean up) 425: // 426: // NEEDS TO BE SPLIT UP so that destroying 427: // a program instance is separated from unloading 428: // the library 429: 430: int do_final_cleanup( 431: bool debug_driver, 432: gc_profile_t *gcp, 433: flx_dynlink_t *library, 434: flx_libinit_t *instance 435: ) 436: { 437: flx::gc::generic::collector_t *collector = gcp->collector; 438: 439: // garbage collect application objects 440: { 441: if(debug_driver || gcp->debug_collections) 442: fprintf(stderr,"Finalisation: pass 1 Data collection starts ..\n"); 443: unsigned long n = collector->collect(); 444: unsigned long a = collector->get_allocation_count(); 445: if(debug_driver || gcp->debug_collections) 446: fprintf(stderr,"flx_run collected %ld objects, %ld left\n",n,a); 447: } 448: 449: // Destroy program instance/ thread frame object 450: 451: if(debug_driver) 452: fprintf(stderr,"Destroying program instance\n"); 453: instance->destroy(); 454: 455: // garbage collect system objects 456: 457: { 458: if(debug_driver || gcp->debug_collections) 459: fprintf(stderr,"Finalisation: pass 2 Final collection starts ..\n"); 460: unsigned long n = collector->collect(); 461: unsigned long a = collector->get_allocation_count(); 462: if(debug_driver || gcp->debug_collections) 463: fprintf(stderr,"Collected %ld objects, %ld left (should be 0)\n",n,a); 464: if(a!=0){ 465: fprintf(stderr,"flx_run %ld uncollected objects, should be zero!!\n",a); 466: return 5; 467: } 468: } 469: 470: // dump the DLL 471: 472: if(debug_driver) 473: fprintf(stderr,"Libref cnt = %ld\n",library->refcnt); 474: if(library->refcnt >0) 475: { 476: if(debug_driver) 477: fprintf(stderr,"flx_run %p library still referenced %ld times\n", 478: library->library,library->refcnt 479: ); 480: } 481: if(debug_driver) 482: fprintf(stderr,"Unlinking library ..\n"); 483: library->unlink(); 484: return 0; 485: } 486: 487: // MAINLINE, ONLY DONE ONCE 488: int run_felix( 489: bool debug_driver, 490: gc_profile_t *gcp, 491: char *filename, 492: int flx_argc, 493: char **flx_argv 494: ) 495: { 496: try 497: { 498: if(debug_driver) 499: fprintf(stderr,"flx_run driver begins %s\n",flx_argv[0]); 500: flx_dynlink_t library; 501: flx_libinit_t instance; 502: library.link(filename); 503: 504: flx::gc::generic::collector_t *collector = gcp->collector; 505: 506: instance.create(&library, collector,library.main_sym,flx_argc,flx_argv,stdin,stdout,stderr); 507: 508: if(debug_driver){ 509: fprintf(stderr,"loaded library %s at %p\n",filename,library.library); 510: fprintf(stderr,"thread frame at %p\n",instance.thread_frame); 511: fprintf(stderr,"initial continuation at %p\n",instance.start_proc); 512: fprintf(stderr,"main continuation at %p\n",instance.main_proc); 513: } 514: run_felix_pthread(debug_driver,gcp,&library,&instance); 515: 516: if(gcp->finalise) 517: { 518: if(library.refcnt >0) 519: { 520: fprintf(stderr,"flx_run %p library still referenced %ld times?!\n",library.library,library.refcnt); 521: return 6; 522: } 523: if(debug_driver) 524: fprintf(stderr,"flx_run driver ends with finalisation complete\n"); 525: } 526: else 527: { 528: if(debug_driver || gcp->debug_collections) 529: { 530: unsigned long a = collector->get_allocation_count(); 531: fprintf(stderr,"flx_run driver ends with finalisation skipped, %ld uncollected objects\n",a); 532: } 533: } 534: } 535: catch (flx_exception_t &x) 536: { 537: return flx_exception_handler(&x); 538: } 539: catch (...) 540: { 541: fprintf(stderr,"flx_run driver ends with unknown EXCEPTION\n"); 542: return 4; 543: } 544: return 0; 545: } 546: 547: int main(int argc, char** argv) 548: { 549: #ifndef FLX_STATIC_LINK 550: bool static_link = false; 551: if (argc<2) 552: { 553: printf("usage: flx_run [--debug] dll_filename options ..\n"); 554: printf(" environment variables:\n"); 555: printf(" FLX_DEBUG # enable debugging traces (default off)\n"); 556: printf(" FLX_DEBUG_ALLOCATIONS # enable debugging allocator (default FLX_DEBUG)\n"); 557: printf(" FLX_DEBUG_COLLECTIONS # enable debugging collector (default FLX_DEBUG)\n"); 558: printf(" FLX_DEBUG_DRIVER # enable debugging driver (default FLX_DEBUG)\n"); 559: printf(" FLX_FINALISE # whether to cleanup on termination (default NO)\n"); 560: printf(" FLX_COMPACT=n # size of compaction arena, 0 to disable (default)\n"); 561: printf(" FLX_GC_FREQ=n # how often to call garbage collector (default 1000)\n"); 562: return 1; 563: } 564: char *filename = argv[1]; 565: char **flx_argv = argv+1; 566: int flx_argc = argc-1; 567: bool debug = (argc > 1) && (strcmp(argv[1],"--debug")==0); 568: if(debug) 569: { 570: if(argc<3) 571: { 572: printf("usage: flx_run [--debug] dll_filename options ..\n"); 573: return 1; 574: } 575: filename = argv[2]; 576: --flx_argc; 577: ++flx_argv; 578: } 579: #else 580: bool static_link = true; 581: char *filename = argv[0]; 582: char **flx_argv = argv; 583: int flx_argc = argc; 584: bool debug = false; 585: 586: // printf("Statically linked Felix program running\n"); 587: #endif 588: char *debug_env = std::getenv("FLX_DEBUG"); 589: debug = debug || debug_env != 0; 590: if(debug) 591: { 592: fprintf(stderr,"[FLX_DEBUG] Debug enabled for %s link program\n",static_link?"static":"dynamic"); 593: } 594: 595: bool debug_allocations = debug || std::getenv("FLX_DEBUG_ALLOCATIONS") !=0; 596: if(debug_allocations) 597: { 598: fprintf(stderr,"[FLX_DEBUG_ALLOCATIONS] Allocation debug enabled\n"); 599: } 600: 601: bool debug_collections = debug || std::getenv("FLX_DEBUG_COLLECTIONS") !=0; 602: if(debug_collections) 603: { 604: fprintf(stderr,"[FLX_DEBUG_COLLECTIONS] Collection debug enabled\n"); 605: } 606: 607: 608: bool debug_driver = debug || std::getenv("FLX_DEBUG_DRIVER") !=0; 609: if(debug_driver) 610: { 611: fprintf(stderr,"[FLX_DEBUG_DRIVER] Driver debug enabled\n"); 612: } 613: 614: 615: char *finalise_env= std::getenv("FLX_FINALISE"); 616: bool finalise = finalise_env != 0; 617: 618: if(debug) 619: fprintf(stderr,"[FLX_FINALISE] Finalisation %s\n",finalise? "Enabled" : "Disabled"); 620: 621: char *compact_env= std::getenv("FLX_COMPACT"); 622: unsigned long compact = compact_env?atol(compact_env):0; 623: if(debug) 624: { 625: if(compact) 626: fprintf(stderr,"[FLX_COMPACT] Compacting with arena minimum size = %ldK\n",compact); 627: else 628: fprintf(stderr,"[FLX_COMPACT] Compaction initially OFF\n"); 629: } 630: compact = compact * 1024; 631: 632: char *gc_freq_env= std::getenv("FLX_GC_FREQ"); 633: unsigned long gc_freq = gc_freq_env?atol(gc_freq_env):1000; 634: if (gc_freq < 1) gc_freq = 1; 635: if(debug) 636: fprintf(stderr,"[FLX_GC_FREQ] call gc every %lu iterations\n",gc_freq); 637: 638: #ifdef HAVE_GNU 639: if(debug)fprintf(stderr, "Compiled by g++\n"); 640: static void *init_sp = sp; 641: static void *init_fframe FLX_UNUSED = __builtin_frame_address(0); 642: static void *init_ret = __builtin_return_address(0); 643: if(debug)fprintf(stderr, "Stack pointer = %p, frame=%p, return=%p\n",sp,init_fframe,init_ret); 644: #endif 645: if(debug) 646: for(int i=0; i<flx_argc; ++i) 647: fprintf(stderr,"flx_argv[%d]->%s\n",i,flx_argv[i]); 648: 649: flx::gc::generic::allocator_t *allocator = 650: new flx::gc::collector::malloc_free() 651: ; 652: allocator->set_debug(debug_allocations); 653: 654: flx::gc::collector::flx_collector_t *collector = 655: new flx::gc::collector::flx_ts_collector_t(allocator) 656: ; 657: collector->set_debug(debug_collections); 658: if(compact) 659: { 660: collector->set_min_arena_size(compact); 661: collector->compact(false); 662: } 663: 664: 665: gc_profile_t *gcp = new gc_profile_t( 666: debug_allocations, 667: debug_collections, 668: compact, 669: gc_freq, 670: finalise, 671: collector 672: ); 673: run_felix( 674: debug_driver, 675: gcp, 676: filename,flx_argc,flx_argv 677: ); 678: 679: delete gcp; 680: delete collector; 681: delete allocator; 682: 683: #ifdef HAVE_GNU 684: // check the frame pointer isn't corrupted 685: static void *fin_sp = sp; 686: static void *fin_fframe FLX_UNUSED = __builtin_frame_address(0); 687: static void *fin_ret = __builtin_return_address(0); 688: if (init_sp != fin_sp ) { 689: fprintf(stderr,"g++: STACK POINTER ERROR %p != %p\n",init_sp,fin_sp); 690: } 691: // I have to comment this out, because it only applies if the 692: // gcc compiler is using the frame pointer.. it doesn't if you 693: // say -fomit-frame-pointer, for example .. I don't know if there 694: // is a way to tell inside the code .. 695: #if 0 696: if (init_fframe != fin_fframe) { 697: fprintf(stderr,"g++: FRAME POINTER ERROR %p != %p\n",init_fframe,fin_fframe); 698: } 699: #endif 700: else if (init_ret != fin_ret) { 701: fprintf(stderr,"g++: RETURN ADDRESS ERROR %p != %p\n",init_ret,fin_ret); 702: } 703: #endif 704: if(debug)fprintf(stderr,"flx_run driver ends OK\n"); 705: return 0; 706: } 707:
1: #line 3621 "./lpsrc/flx_rtl.pak" 2: #include "flx_rtl_config.hpp" 3: #include "flx_rtl.hpp" 4: // THIS IS A DO NOTHING MAINLINE FOR USE WHEN STATICALLY LINKING 5: extern "C" flx::rtl::con_t *flx_main( void *p){ return 0; } 6: 7:
1: #line 3629 "./lpsrc/flx_rtl.pak" 2: #include <stdio.h> 3: #include "flx_rtl.hpp" 4: #include "flx_collector.hpp" 5: #include "flx_dynlink.hpp" 6: 7: using namespace std; 8: using namespace flx; 9: 10: int main(int argc, char** argv) 11: { 12: rtl::flx_dynlink_t library; 13: rtl::flx_libinit_t instance; 14: library.link(argc>1?argv[1]:"<static>"); 15: gc::collector::malloc_free allocator; 16: gc::collector::flx_collector_t collector(&allocator); 17: instance.create(&library, &collector,library.main_sym,argc,argv,stdin,stdout,stderr); 18: rtl::con_t *top = instance.start_proc; 19: while( top ) top = top->resume(); 20: return 0; 21: } 22: 23:
1: #line 3652 "./lpsrc/flx_rtl.pak" 2: #ifndef FLX_I18N 3: #define FLX_I18N 4: #include <string> 5: #include "flx_rtl_config.hpp" 6: 7: namespace flx { namespace rtl { namespace i18n { 8: RTL_EXTERN std::string utf8(unsigned long); 9: }}} 10: #endif 11:
1: #line 3663 "./lpsrc/flx_rtl.pak" 2: #include "flx_i18n.hpp" 3: namespace flx { namespace rtl { namespace i18n { 4: std::string utf8(unsigned long i) 5: { 6: char s[6]; 7: if (i < 0x80UL ) 8: { 9: s[0]= i; 10: s[1]= 0; 11: } 12: else if (i < 0x800UL ) 13: { 14: s[0]=0xC0u | (i >> 6ul) & 0x1Fu; 15: s[1]=0x80u | i & 0x3Fu; 16: s[2]=0; 17: } 18: else if (i < 0x10000UL ) 19: { 20: s[0]=0xE0u | (i >> 12ul) & 0xFu; 21: s[1]=0x80u | (i >> 6ul) & 0x3Fu; 22: s[2]=0x80u | i & 0x3F; 23: s[3]=0; 24: } 25: else if (i < 0x200000UL ) 26: { 27: s[0]=0xF0u | (i >> 18ul) & 0x7u; 28: s[1]=0x80u | (i >> 12ul) & 0x3Fu; 29: s[2]=0x80u | (i >> 6ul) & 0x3Fu; 30: s[3]=0x80u | i & 0x3F; 31: s[4]=0; 32: } 33: else if (i < 0x4000000UL ) 34: { 35: s[0]=0xF8u | (i >> 24ul) & 0x3u; 36: s[1]=0x80u | (i >> 18ul) & 0x3Fu; 37: s[2]=0x80u | (i >> 12ul) & 0x3Fu; 38: s[3]=0x80u | (i >> 6ul) & 0x3Fu; 39: s[4]=0x80u | i & 0x3Fu; 40: s[5]=0; 41: } 42: else 43: { 44: s[0]=0xFCu | (i >> 30ul) & 0x1u; 45: s[1]=0x80u | (i >> 24ul) & 0x3Fu; 46: s[2]=0x80u | (i >> 18ul) & 0x3Fu; 47: s[3]=0x80u | (i >> 12ul) & 0x3Fu; 48: s[4]=0x80u | (i >> 6ul) & 0x3Fu; 49: s[5]=0x80u | i & 0x3Fu; 50: s[6]=0; 51: } 52: return s; 53: } 54: }}} 55: