# HG changeset patch # User Me # Date 1278533754 25200 # Node ID 2b161e1a50ee9f97cca1f4637f14f89e80da14c9 # Parent aa634ef7cc35b63b2d6d00492412b27356ce4722 1st working version -- as far as can tell due to SEH bugs diff -r aa634ef7cc35 -r 2b161e1a50ee CoreLoop.c --- a/CoreLoop.c Wed Jun 30 13:11:06 2010 -0700 +++ b/CoreLoop.c Wed Jul 07 13:15:54 2010 -0700 @@ -33,21 +33,12 @@ //Designate a core by a 1 in bit-position corresponding to the core SetThreadAffinityMask(GetCurrentThread(),1 << coreLoopThdParams->coreNum); - //Save the stack pointer and frame pointer of this coreLoop's thread -// asm volatile("movl %%ebp, %0; \ - movl %%esp, %1; "\ - /* outputs */ : "=m" (coreLoopThdParams->framePtr), \ - "=m" (coreLoopThdParams->stackPtr) \ - /* inputs */ : \ - ); //Save addr of "end core loop" label - jump to it to shut down coreloop //To get label addr in non-gcc compiler, can trick it by making a call // to a fn that does asm that pulls the "return" // addr off the stack and stores it in a pointed-to location. - coreLoopThdParams->endThdPt = &&EndCoreLoop; - _VMSMasterEnv->coreLoopShutDownPt = &&EndCoreLoop; //haven't decided yet - //which way will do shutdown of core loops + _VMSMasterEnv->coreLoopShutDownPt = &&EndCoreLoop; //Core loop has no values live upon CoreLoopStartPt except workQ // every value in the code is defined by a statement in core loop, @@ -65,7 +56,9 @@ workQ = _VMSWorkQ; currPr = (VirtProcr *) readCASQ( workQ ); - currPr->coreLoopStartPt = &&CoreLoopStartPt; //just to be sure.(GCC spec) +// printf("core %d loop procr addr: %d\n", coreLoopThdParams->coreNum, \ + (int)currPr ); fflush(stdin); + currPr->coreLoopStartPt = &&CoreLoopStartPt; //to be sure.(GCC specific) currPr->coreAnimatedBy = coreLoopThdParams->coreNum; @@ -88,7 +81,6 @@ //Explicitly loading into eax before changing frame-ptr fixed it //Also, it turns "(currPr->coreLoopFramePtr)" into a temporary on the // stack, so "movl %%ebp, %0" saves to the temp, NOT the data-struc! -//coreLoop asm volatile("movl %0, %%eax; \ movl %%esp, (%%eax); \ movl %1, %%eax; \ diff -r aa634ef7cc35 -r 2b161e1a50ee VMS.c --- a/VMS.c Wed Jun 30 13:11:06 2010 -0700 +++ b/VMS.c Wed Jul 07 13:15:54 2010 -0700 @@ -71,12 +71,34 @@ masterEnv->schedSlots[0]->workIsDone = FALSE; //says don't touch masterEnv->schedSlots[0]->procrAssignedToSlot = masterEnv->masterVirtPr; masterEnv->masterVirtPr->schedSlot = masterEnv->schedSlots[0]; + masterEnv->stillRunning = FALSE; //First core loop to start up gets this, which will schedule seed Pr //TODO: debug: check address of masterVirtPr writeCASQ( masterEnv->masterVirtPr, workQ ); numProcrsCreated = 1; + + //======================================================================== + // Create the Threads + int coreIdx; + + //Make params given to the win threads that animate the core loops + for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) + { coreLoopThdParams[coreIdx] = malloc( sizeof(ThdParams) ); + coreLoopThdParams[coreIdx]->coreNum = coreIdx; + + //make the core loop threads, born in suspended state + coreLoopThdHandles[ coreIdx ] = + CreateThread ( NULL, // Security attributes + 0, // Stack size + coreLoop, + coreLoopThdParams[coreIdx], + CREATE_SUSPENDED, + &(coreLoopThdIds[coreIdx]) + ); + } + } @@ -103,30 +125,44 @@ /*Semantic layer calls this when it want the system to start running.. * - *This creates the core loops, pins them to physical cores, gives them the - * pointer to the workQ, and starts them running. + *This starts the core loops running then waits for them to exit. */ void -VMS__start() +VMS__start_the_work_then_wait_until_done() { int coreIdx; + //Start the core loops running +//=========================================================================== + LARGE_INTEGER stPerfCount, endPerfCount, countFreq; + unsigned long long count = 0, freq = 0; + double runTime; - //TODO: Save "orig" stack pointer and frame ptr -- restore in VMS__end() - //Create the win threads that animate the core loops + QueryPerformanceCounter( &stPerfCount ); + + //start them running + for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) + { //Create the threads + ResumeThread( coreLoopThdHandles[coreIdx] ); //starts thread + } + + //wait for all to complete for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) { - coreLoopThdParams[coreIdx] = (ThdParams *)malloc( sizeof(ThdParams) ); - coreLoopThdParams[coreIdx]->coreNum = coreIdx; + WaitForSingleObject(coreLoopThdHandles[coreIdx], INFINITE); + } - coreLoopThdHandles[coreIdx] = - CreateThread ( NULL, // Security attributes - 0, // Stack size - coreLoop, - coreLoopThdParams[coreIdx], - CREATE_SUSPENDED, - &(coreLoopThdIds[coreIdx]) - ); - ResumeThread( coreLoopThdHandles[coreIdx] ); //starts thread - } + //NOTE: do not clean up VMS env here -- semantic layer has to have + // a chance to clean up its environment first, then do a call to free + // the Master env and rest of VMS locations + + QueryPerformanceCounter( &endPerfCount ); + count = endPerfCount.QuadPart - stPerfCount.QuadPart; + + QueryPerformanceFrequency( &countFreq ); + freq = countFreq.QuadPart; + runTime = (double)count / (double)freq; + + printf("\n Time startup to shutdown: %f\n", runTime); + fflush( stdin ); } @@ -283,7 +319,7 @@ /*This inserts the semantic-layer's request data into standard VMS carrier */ inline void -VMS__send_sem_request( void *semReqData, VirtProcr *callingPr ) +VMS__add_sem_request( void *semReqData, VirtProcr *callingPr ) { VMSReqst *req; req = malloc( sizeof(VMSReqst) ); @@ -295,20 +331,6 @@ } -/*This creates a request of type "dissipate" -- which will cause the virt - * processor's state and owned locations to be freed - */ -inline void -VMS__send_dissipate_request( VirtProcr *procrToDissipate ) - { VMSReqst *req; - - req = malloc( sizeof(VMSReqst) ); -// req->virtProcrFrom = callingPr; - req->reqType = dissipate; - req->nextReqst = procrToDissipate->requests; - procrToDissipate->requests = req; - } - //TODO: add a semantic-layer supplied "freer" for the semantic-data portion // of a request -- IE call with both a virt procr and a fn-ptr to request @@ -322,36 +344,63 @@ free( req ); } -/*This must be called by the request handler plugin -- it cannot be called - * from the semantic library "dissipate processor" function -- instead, the - * semantic layer has to generate a request for the plug-in to call this - * function. - *The reason is that this frees the virtual processor's stack -- which is - * still in use inside semantic library calls! - * - *This frees or recycles all the state owned by and comprising the animating - * virtual procr. It frees any state that was malloc'd by the VMS system - * itself, and asks the VMS system to dis-own any VMS__malloc'd locations. - *If the dissipated processor is the sole (remaining) owner of VMS__malloc'd - * state, then that state gets freed (or sent to recycling) as a side-effect - * of dis-owning it. - */ + +//TODO: add a semantic-layer supplied "freer" for the semantic-data portion +// of a request -- IE call with both a virt procr and a fn-ptr to request +// freer (also maybe put sem request freer as a field in virt procr?) void -VMS__free_procr_locs( VirtProcr *animatingPr ) +VMS__free_request( VMSReqst *req ) + { + free( req ); + } + +VMSReqst * +VMS__take_top_request_from( VirtProcr *procrWithReq ) + { VMSReqst *req; + + req = procrWithReq->requests; + if( req == NULL ) return req; + + procrWithReq->requests = procrWithReq->requests->nextReqst; + return req; + } + +inline int +VMS__isSemanticReqst( VMSReqst *req ) { - //dis-own all locations owned by this processor, causing to be freed - // any locations that it is (was) sole owner of - //TODO: implement VMS__malloc system, including "give up ownership" + return ( req->reqType == semantic ); + } - VMS__remove_and_free_top_request( animatingPr ); - free( animatingPr->startOfStack ); - - //NOTE: animatingPr->semanticData should either have been allocated - // with VMS__malloc, or else freed in the request handler plug-in. - //NOTE: initialData was given to the processor, so should either have - // been alloc'd with VMS__malloc, or freed by the level above animPr. - //So, all that's left to free here is the VirtProcr struc itself - free( animatingPr ); + +inline void * +VMS__take_sem_reqst_from( VMSReqst *req ) + { + return req->semReqData; + } + +inline int +VMS__isDissipateReqst( VMSReqst *req ) + { + return ( req->reqType == dissipate ); + } + +inline int +VMS__isCreateReqst( VMSReqst *req ) + { + return ( req->reqType == regCreated ); + } + +void +VMS__send_register_new_procr_request(VirtProcr *newPr, VirtProcr *reqstingPr) + { VMSReqst *req; + + req = malloc( sizeof(VMSReqst) ); + req->reqType = regCreated; + req->semReqData = newPr; + req->nextReqst = reqstingPr->requests; + reqstingPr->requests = req; + + VMS__suspend_procr( reqstingPr ); } @@ -384,6 +433,44 @@ } +/*This must be called by the request handler plugin -- it cannot be called + * from the semantic library "dissipate processor" function -- instead, the + * semantic layer has to generate a request for the plug-in to call this + * function. + *The reason is that this frees the virtual processor's stack -- which is + * still in use inside semantic library calls! + * + *This frees or recycles all the state owned by and comprising the VMS + * portion of the animating virtual procr. The request handler must first + * free any semantic data created for the processor that didn't use the + * VMS_malloc mechanism. Then it calls this, which first asks the malloc + * system to disown any state that did use VMS_malloc, and then frees the + * statck and the processor-struct itself. + *If the dissipated processor is the sole (remaining) owner of VMS__malloc'd + * state, then that state gets freed (or sent to recycling) as a side-effect + * of dis-owning it. + */ +void +VMS__free_procr_locs( VirtProcr *animatingPr ) + { + //dis-own all locations owned by this processor, causing to be freed + // any locations that it is (was) sole owner of + //TODO: implement VMS__malloc system, including "give up ownership" + + //The dissipate request might still be attached, so remove and free it + VMS__remove_and_free_top_request( animatingPr ); + free( animatingPr->startOfStack ); + + //NOTE: initialData was given to the processor, so should either have + // been alloc'd with VMS__malloc, or freed by the level above animPr. + //So, all that's left to free here is the stack and the VirtProcr struc + // itself + free( animatingPr->startOfStack ); + free( animatingPr ); + } + + + /*This is the function run by the special "shut-down" processor * *The _VMSMasterEnv is needed by this shut down function, so the "wait" @@ -422,11 +509,32 @@ // get its request handled before all the cores have shutdown. //TODO: after all the threads stop, clean out the MasterEnv, the // SemanticEnv, and the workQ before returning. - VMS__send_dissipate_request( animatingPr ); - VMS__suspend_procr( animatingPr ); //will never come back from this + VMS__dissipate_procr( animatingPr ); //will never come back from this } +/*This has to free anything allocated during VMS_init, and any other alloc'd + * locations that might be left over. + */ +void +VMS__shutdown() + { int i; + + free( _VMSWorkQ ); + free( _VMSMasterEnv->filledSlots ); + for( i = 0; i < NUM_SCHED_SLOTS; i++ ) + { + free( _VMSMasterEnv->schedSlots[i] ); + } + + free( _VMSMasterEnv->schedSlots); + VMS__free_procr_locs( _VMSMasterEnv->masterVirtPr ); + + free( _VMSMasterEnv ); + } + + +//=========================================================================== inline TSCount getTSCount() { unsigned int low, high; diff -r aa634ef7cc35 -r 2b161e1a50ee VMS.h --- a/VMS.h Wed Jun 30 13:11:06 2010 -0700 +++ b/VMS.h Wed Jul 07 13:15:54 2010 -0700 @@ -29,7 +29,7 @@ //#define thdAttrs NULL //For PThreads typedef struct _SchedSlot SchedSlot; -typedef struct _SlaveReqst VMSReqst; +typedef struct _VMSReqst VMSReqst; typedef struct _VirtProcr VirtProcr; typedef VirtProcr * (*SlaveScheduler) ( void * ); //semEnv @@ -59,18 +59,19 @@ { semantic = 1, dissipate, + regCreated, IO }; -struct _SlaveReqst +struct _VMSReqst { // VirtProcr *virtProcrFrom; - enum ReqstType reqType; //used for dissipate and in future for IO requests + enum ReqstType reqType;//used for dissipate and in future for IO requests void *semReqData; VMSReqst *nextReqst; }; -//SlaveReqst +//VMSReqst struct _VirtProcr { int procrID; //for debugging -- count up each time create @@ -142,7 +143,7 @@ VMS__init(); void -VMS__start(); +VMS__start_the_work_then_wait_until_done(); VirtProcr * VMS__create_procr( VirtProcrFnPtr fnPtr, void *initialData ); @@ -150,15 +151,37 @@ VirtProcr * VMS__create_the_shutdown_procr(); +//========================== inline void -VMS__send_sem_request( void *semReqData, VirtProcr *callingPr ); +VMS__add_sem_request( void *semReqData, VirtProcr *callingPr ); void -VMS__send_dissipate_request( VirtProcr *procrToDissipate ); +VMS__send_register_new_procr_request( VirtProcr *newPrToRegister, + VirtProcr *reqstingPr ); + +void +VMS__free_request( VMSReqst *req ); void VMS__remove_and_free_top_request( VirtProcr *reqstingPr ); +VMSReqst * +VMS__take_top_request_from( VirtProcr *reqstingPr ); + +inline void * +VMS__take_sem_reqst_from( VMSReqst *req ); + +inline int +VMS__isSemanticReqst( VMSReqst *req ); + +inline int +VMS__isDissipateReqst( VMSReqst *req ); + +inline int +VMS__isCreateReqst( VMSReqst *req ); + +//========================== + void VMS__suspend_procr( VirtProcr *callingPr );