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