//***** ThreadSafe! ***** void bbDelay( int millis ){ int i,e; if( millis<0 ) return; e=bbMilliSecs()+millis; for( i=0;;++i ){ int t=e-bbMilliSecs(); if( t<=0 ){ if( !i ) usleep( 0 ); //always sleep at least once. break; } usleep( t*1000 ); } }
static void startup(){ struct sysinfo info; _mainThread=pthread_self(); sysinfo( &info ); base_time=bbMilliSecs()-info.uptime*1000; }
static void startup(){ struct sysinfo info; //_mainThread=pthread_self(); // TODO : appears as "undefined" when linking... need this for millisecs support. //sysinfo( &info ); base_time=bbMilliSecs()-info.uptime*1000; }
static void *timerProc( void *data ){ BBTimer *timer=(BBTimer*)data; int time=timer->start; while( timer->status==1 ){ time+=timer->period; bbDelay( time-bbMilliSecs() ); ++timer->puts; bbSystemPostSyncOp( timerSyncOp,&bbNullObject,(int)timer ); } bbSystemPostSyncOp( timerSyncOp,&bbNullObject,(int)timer ); }
BBTimer *bbTimerStart( float hertz,BBObject *bbTimer ){ BBTimer *timer; int start=bbMilliSecs(); timer=(BBTimer*)malloc( sizeof( BBTimer ) ); timer->status=1; timer->puts=1; timer->gets=0; timer->start=start; timer->period=1000.0f/hertz; timer->bbTimer=bbTimer; if( pthread_create( &timer->thread,0,(void*(*)(void*))timerProc,timer )<0 ){ free( timer ); return 0; } BBRETAIN( timer->bbTimer ); return timer; }
void collectMem( int dummy ){ int i; void **r; static int recurs; if( recurs ){ // printf( "RECURSIVE GC!\n" );fflush( stdout ); return; } recurs=1; #ifdef DEBUG_GC int ms=bbMilliSecs(); #endif BBThread *thread; BBThread *curThread=bbThreadGetCurrent(); BBThread *lockedThreads=_bbThreadLockThreads(); for( thread=lockedThreads;thread;thread=thread->succ ){ for( i=0;i<32;++i ){ mark( thread->data[i] ); } if( thread==curThread ){ void *regs[BBGC_NUM_ROOTREGS]; void **sp=bbGCRootRegs( regs ); for( i=0;i<BBGC_NUM_ROOTREGS;++i ){ mark( regs[i] ); } for( r=sp;r!=thread->stackTop;++r ){ mark( *r ); } }else{ for( i=0;i<BB_THREADREGS;++i ){ mark( (void*)thread->locked_regs[i] ); } for( r=(void**)thread->locked_sp;r!=thread->stackTop;++r ){ mark( *r ); } } } for( i=0;i<n_global_vars;++i ){ mark( *global_vars[i] ); } #ifdef DEBUG_GC int mark_ms=bbMilliSecs(); #endif GCBlock *t; //mark locked blocks for( t=usedBlocks;t;t=t->succ ){ if( t->flags & BBGC_LOCKED ) mark( t->data ); } //resurrect or free finalized blocks while( t=finalizedBlocks ){ finalizedBlocks=t->succ; if( t->flags & BBGC_MARKED ){ //resurrect me! t->succ=usedBlocks; usedBlocks=t; if( t->flags & BBGC_FINALIZE ){ t->flags&=~BBGC_FINALIZE; #ifdef DEBUG_GC BBObject *q=(BBObject*)t->data; printf( "GC resurrected:%s @%p\n",typeName( q ),q );fflush( stdout ); #endif } }else{ freeBlock( t ); } } GCBlock **p=&usedBlocks; int n_finalized=0; while( t=*p ){ if( t->flags & BBGC_MARKED ){ p=&t->succ; t->flags&=~BBGC_MARKED; }else{ *p=t->succ; if( t->flags & BBGC_FINALIZE ){ ++n_finalized; BBObject *q=(BBObject*)t->data; // printf( "GC finalizing:%s\n",typeName( q ) );fflush( stdout ); BBClass *c=q->clas; c->free( q ); q->clas=c; } t->succ=finalizedBlocks; finalizedBlocks=t; } } if( !n_finalized ){ // //No finalizers were run, so it's OK to free blocks NOW. // while( t=finalizedBlocks ){ finalizedBlocks=t->succ; freeBlock( t ); } } _bbThreadUnlockThreads(); #ifdef DEBUG_GC int end_ms=bbMilliSecs(); printf( "gc ms=%i, marked=%i, marked_ms=%i, freed=%i, freed_ms=%i\n",end_ms-ms,n_marked,mark_ms-ms,n_freed,end_ms-mark_ms );fflush( stdout ); #endif recurs=0; }