# HG changeset patch # User Sean Halle # Date 1362247678 28800 # Node ID a40859b8dc33a21599282a117601c137273935c4 # Parent dd1efbf29ff939342bd06f61d285135dd8084ca6 ML_dev -- compiles and runs, may still have shutdown issues diff -r dd1efbf29ff9 -r a40859b8dc33 VSs.c --- a/VSs.c Thu Feb 07 16:30:16 2013 -0800 +++ b/VSs.c Sat Mar 02 10:07:58 2013 -0800 @@ -125,26 +125,6 @@ ANY_CORE, creatingThd ); } -/* old version -- looks safe to delete -SlaveVP * -VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData, - SlaveVP *creatingSlv, int32 coreToAssignOnto ) - { VSsLangReq reqData; - - //the lang request data is on the stack and disappears when this - // call returns -- it's guaranteed to remain in the VP's stack for as - // long as the VP is suspended. - reqData.reqType = create_slave_w_aff; //not used, May 2012 - reqData.coreToAssignOnto = coreToAssignOnto; - reqData.fnPtr = fnPtr; - reqData.initData = initData; - reqData.callingSlv = creatingSlv; - - PR_WL__send_create_slaveVP_req( &reqData, creatingSlv, VSs_MAGIC_NUMBER ); - - return creatingSlv->dataRetFromReq; - } -*/ SlaveVP * @@ -160,7 +140,7 @@ reqData.fnPtr = fnPtr; reqData.initData = initData; - PR_WL__send_create_slaveVP_req( &reqData, thdID, (CreateHandler)&handleCreateThd, + PR_WL__send_create_slaveVP_req( &reqData, thdID, (CreateHandler)&VSs__handleCreateThd, creatingThd, VSs_MAGIC_NUMBER ); return (SlaveVP *)creatingThd->dataRetFromReq; } @@ -176,7 +156,7 @@ VSs__end_thread( SlaveVP *thdToEnd ) { //the lang request is null for VSs version of end slave - PR_WL__send_end_slave_req( NULL, (RequestHandler)&handleDissipate, thdToEnd, + PR_WL__send_end_slave_req( NULL, (RequestHandler)&VSs__handleDissipate, thdToEnd, VSs_MAGIC_NUMBER ); } @@ -202,7 +182,7 @@ // top-level-fn of task and the data for that fn, plus lang's req, // animating slave, and lang's magic number PR_WL__send_create_task_req( taskType->fn, args, &reqData, NO_ID, - &handleSubmitTask, animSlv, VSs_MAGIC_NUMBER ); + &VSs__handleSubmitTask, animSlv, VSs_MAGIC_NUMBER ); } void @@ -212,12 +192,12 @@ reqData.reqType = submit_task; - reqData.taskType = taskType; + reqData.taskType = taskType; //VSs info about args, dependencies, etc reqData.args = args; reqData.callingSlv = animSlv; PR_WL__send_create_task_req( taskType->fn, args, &reqData, taskID, - &handleSubmitTask, animSlv, VSs_MAGIC_NUMBER ); + &VSs__handleSubmitTask, animSlv, VSs_MAGIC_NUMBER ); } @@ -243,7 +223,7 @@ { VSsLangReq reqData; //VSs has nothing extra to communicate to end task handler, so lang req is NULL - PR_WL__send_end_task_request( NULL, &handleEndTask, animSlv, VSs_MAGIC_NUMBER ); + PR_WL__send_end_task_request( NULL, &VSs__handleEndTask, animSlv, VSs_MAGIC_NUMBER ); } @@ -258,11 +238,34 @@ reqData.reqType = taskwait; reqData.callingSlv = animSlv; - PR_WL__send_lang_request( &reqData, (RequestHandler)&handleTaskwait, animSlv, + PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleTaskwait, animSlv, VSs_MAGIC_NUMBER ); } +void +VSs__wait_for_all_VSs_created_work_to_end( SlaveVP *seedSlv ) + { + VSsLangReq reqData; + reqData.reqType = activity_cease_wait; + reqData.callingSlv = seedSlv; + + PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleWaitForVSsWorkToEnd, seedSlv, + VSs_MAGIC_NUMBER ); + } + + + +/*This is called by the application -- normally the seed slave. It causes a + * request to be sent that frees the VSs lang env and all its contents. + *The seed slave resumes from the built-in PRServ langlet's environment. It + * will be PRServ that causes return from this call. + */ +void +VSs__shutdown( SlaveVP *seedSlv ) + { + PR_WL__send_lang_shutdown_request( seedSlv, VSs_MAGIC_NUMBER ); + } //========================== send and receive ============================ // @@ -270,8 +273,9 @@ inline int32 * VSs__give_self_taskID( SlaveVP *animSlv ) - { - return PR__give_ID_from_slave( animSlv, VSs_MAGIC_NUMBER ); + { void *metaTask; + metaTask = PR_WL__give_lang_meta_task_from_slave( animSlv, VSs_MAGIC_NUMBER ); + return PR__give_ID_from_lang_meta_task( metaTask ); } //================================ send =================================== @@ -290,7 +294,7 @@ reqData.nextReqInHashEntry = NULL; - PR_WL__send_lang_request( &reqData, (RequestHandler)&handleSendTypeTo, + PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleSendTypeTo, senderSlv, VSs_MAGIC_NUMBER ); //When come back from suspend, no longer own data reachable from msg @@ -309,7 +313,7 @@ reqData.nextReqInHashEntry = NULL; - PR_WL__send_lang_request( &reqData, (RequestHandler)&handleSendFromTo, + PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleSendFromTo, senderSlv, VSs_MAGIC_NUMBER ); } @@ -335,7 +339,7 @@ reqData.nextReqInHashEntry = NULL; - PR_WL__send_lang_request( &reqData, (RequestHandler)&handleReceiveTypeTo, + PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleReceiveTypeTo, receiverSlv, VSs_MAGIC_NUMBER ); return receiverSlv->dataRetFromReq; @@ -361,7 +365,7 @@ reqData.nextReqInHashEntry = NULL; DEBUG__printf2(dbgRqstHdlr,"WL: receive from %d to: %d", reqData.senderID[1], reqData.receiverID[1]); - PR_WL__send_lang_request( &reqData, (RequestHandler)&handleReceiveFromTo, + PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleReceiveFromTo, receiverSlv, VSs_MAGIC_NUMBER ); return receiverSlv->dataRetFromReq; @@ -370,195 +374,4 @@ -//========================================================================== -// -/*A function singleton is a function whose body executes exactly once, on a - * single core, no matter how many times the fuction is called and no - * matter how many cores or the timing of cores calling it. - * - *A data singleton is a ticket attached to data. That ticket can be used - * to get the data through the function exactly once, no matter how many - * times the data is given to the function, and no matter the timing of - * trying to get the data through from different cores. - */ -/*asm function declarations*/ -void asm_save_ret_to_singleton(VSsSingleton *singletonPtrAddr); -void asm_write_ret_from_singleton(VSsSingleton *singletonPtrAddr); - -/*Fn singleton uses ID as index into array of singleton structs held in the - * language environment. - */ -void -VSs__start_fn_singleton( int32 singletonID, SlaveVP *animSlv ) - { - VSsLangReq reqData; - - // - reqData.reqType = singleton_fn_start; - reqData.singletonID = singletonID; - - PR_WL__send_lang_request( &reqData, (RequestHandler)&handleStartFnSingleton, - animSlv, VSs_MAGIC_NUMBER ); - if( animSlv->dataRetFromReq ) //will be 0 or addr of label in end singleton - { - VSsLangEnv *langEnv = - PR_int__give_lang_env_for_slave( animSlv, VSs_MAGIC_NUMBER ); - asm_write_ret_from_singleton(&(langEnv->fnSingletons[ singletonID])); - } - } - -/*Data singleton hands addr of loc holding a pointer to a singleton struct. - * The start_data_singleton makes the structure and puts its addr into the - * location. - */ -void -VSs__start_data_singleton( VSsSingleton **singletonAddr, SlaveVP *animSlv ) - { - VSsLangReq reqData; - - if( *singletonAddr && (*singletonAddr)->hasFinished ) - goto JmpToEndSingleton; - - reqData.reqType = singleton_data_start; - reqData.singletonPtrAddr = singletonAddr; - - PR_WL__send_lang_request( &reqData, (RequestHandler)&handleStartDataSingleton, - animSlv, VSs_MAGIC_NUMBER ); - if( animSlv->dataRetFromReq ) //either 0 or end singleton's return addr - { //Assembly code changes the return addr on the stack to the one - // saved into the singleton by the end-singleton-fn - //The return addr is at 0x4(%%ebp) - JmpToEndSingleton: - asm_write_ret_from_singleton(*singletonAddr); - } - //now, simply return - //will exit either from the start singleton call or the end-singleton call - } - -/*Uses ID as index into array of flags. If flag already set, resumes from - * end-label. Else, sets flag and resumes normally. - * - *Note, this call cannot be inlined because the instr addr at the label - * inside is shared by all invocations of a given singleton ID. - */ -void -VSs__end_fn_singleton( int32 singletonID, SlaveVP *animSlv ) - { - VSsLangReq reqData; - - //don't need this addr until after at least one singleton has reached - // this function - VSsLangEnv * - langEnv = PR_int__give_lang_env_for_slave( animSlv, VSs_MAGIC_NUMBER ); - - asm_write_ret_from_singleton(&(langEnv->fnSingletons[ singletonID])); - - reqData.reqType = singleton_fn_end; - reqData.singletonID = singletonID; - - PR_WL__send_lang_request( &reqData, (RequestHandler)&handleEndFnSingleton, - animSlv, VSs_MAGIC_NUMBER ); - -EndSingletonInstrAddr: - return; - } - -void -VSs__end_data_singleton( VSsSingleton **singletonPtrAddr, SlaveVP *animSlv ) - { - VSsLangReq reqData; - - //don't need this addr until after singleton struct has reached - // this function for first time - //do assembly that saves the return addr of this fn call into the - // data singleton -- that data-singleton can only be given to exactly - // one instance in the code of this function. However, can use this - // function in different places for different data-singletons. - asm_save_ret_to_singleton(*singletonPtrAddr); - - reqData.reqType = singleton_data_end; - reqData.singletonPtrAddr = singletonPtrAddr; - - PR_WL__send_lang_request( &reqData, (RequestHandler)&handleEndDataSingleton, - animSlv, VSs_MAGIC_NUMBER ); - } - -/*This executes the function in the masterVP, so it executes in isolation - * from any other copies -- only one copy of the function can ever execute - * at a time. - * - *It suspends to the master, and the request handler takes the function - * pointer out of the request and calls it, then resumes the VP. - *Only very short functions should be called this way -- for longer-running - * isolation, use transaction-start and transaction-end, which run the code - * between as work-code. - */ -void -VSs__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster, - void *data, SlaveVP *animSlv ) - { - VSsLangReq reqData; - - // - reqData.reqType = atomic; - reqData.fnToExecInMaster = ptrToFnToExecInMaster; - reqData.dataForFn = data; - - PR_WL__send_lang_request( &reqData, (RequestHandler)&handleAtomic, - animSlv, VSs_MAGIC_NUMBER ); - } - - -/*This suspends to the master. - *First, it looks at the VP's data, to see the highest transactionID that VP - * already has entered. If the current ID is not larger, it throws an - * exception stating a bug in the code. Otherwise it puts the current ID - * there, and adds the ID to a linked list of IDs entered -- the list is - * used to check that exits are properly ordered. - *Next it is uses transactionID as index into an array of transaction - * structures. - *If the "VP_currently_executing" field is non-null, then put requesting VP - * into queue in the struct. (At some point a holder will request - * end-transaction, which will take this VP from the queue and resume it.) - *If NULL, then write requesting into the field and resume. - */ -void -VSs__start_transaction( int32 transactionID, SlaveVP *animSlv ) - { - VSsLangReq reqData; - - // - reqData.callingSlv = animSlv; - reqData.reqType = trans_start; - reqData.transID = transactionID; - - PR_WL__send_lang_request( &reqData, (RequestHandler)&handleTransStart, - animSlv, VSs_MAGIC_NUMBER ); - } - -/*This suspends to the master, then uses transactionID as index into an - * array of transaction structures. - *It looks at VP_currently_executing to be sure it's same as requesting VP. - * If different, throws an exception, stating there's a bug in the code. - *Next it looks at the queue in the structure. - *If it's empty, it sets VP_currently_executing field to NULL and resumes. - *If something in, gets it, sets VP_currently_executing to that VP, then - * resumes both. - */ -void -VSs__end_transaction( int32 transactionID, SlaveVP *animSlv ) - { - VSsLangReq reqData; - - // - reqData.callingSlv = animSlv; - reqData.reqType = trans_end; - reqData.transID = transactionID; - - PR_WL__send_lang_request( &reqData, (RequestHandler)&handleTransEnd, - animSlv, VSs_MAGIC_NUMBER ); - } - -//======================== Internal ================================== - diff -r dd1efbf29ff9 -r a40859b8dc33 VSs.h --- a/VSs.h Thu Feb 07 16:30:16 2013 -0800 +++ b/VSs.h Sat Mar 02 10:07:58 2013 -0800 @@ -73,13 +73,12 @@ } VSsPointerEntry; -/*This is placed into langData, used for dependencies and wait construct*/ +/*This is VSs's "lang meta task" + *See the proto-runtime wiki entry to learn about "lang meta task" + *In essence, this holds all the meta information that VSs needs about a task + */ struct _VSsTaskStub { - //====== The first fields must match PRLangMetaTask fields ====== - int32 langMagicNumber; //magic num must be 1st field of langMetaTask - PRMetaTask *protoMetaTask; //back-link must always be 2nd field - //====== end PRLangMetaTask fields ========= void **args; //ctld args must be the first ones (as ptrs) VSsPointerEntry **ptrEntries; int32 numBlockingProp; @@ -140,15 +139,9 @@ receive_from_to, //=============================== taskwait, - malloc_req, - free_req, - singleton_fn_start, - singleton_fn_end, - singleton_data_start, - singleton_data_end, - atomic, - trans_start, - trans_end + activity_cease_wait, + wait_then_shutdown, + shutdown }; struct _VSsLangReq @@ -269,7 +262,13 @@ VSs__start( SlaveVP *seedSlv ); void -VSs__cleanup_after_shutdown(); +VSs__shutdown( SlaveVP *seedSlv ); + +void +VSs__wait_for_all_VSs_created_work_to_end( SlaveVP *seedSlv ); + +void +VSs__wait_until_activity_done_then_shutdown( SlaveVP *seedSlv ); //======================= @@ -291,8 +290,8 @@ void VSs__submit_task( VSsTaskType *taskType, void *args, SlaveVP *animSlv); -inline int32 * -VSs__create_taskID_of_size( int32 numInts, SlaveVP *animSlv ); +//inline int32 * +//VSs__create_taskID_of_size( int32 numInts, SlaveVP *animSlv ); void VSs__submit_task_with_ID( VSsTaskType *taskType, void *args, int32 *taskID, @@ -322,35 +321,10 @@ void * VSs__receive_from_to( int32 *senderID, int32 *receiverID, SlaveVP *receiverSlv ); -//======================= Concurrency Stuff ====================== -void -VSs__start_fn_singleton( int32 singletonID, SlaveVP *animSlv ); - -void -VSs__end_fn_singleton( int32 singletonID, SlaveVP *animSlv ); - -void -VSs__start_data_singleton( VSsSingleton **singeltonAddr, SlaveVP *animSlv ); - -void -VSs__end_data_singleton( VSsSingleton **singletonAddr, SlaveVP *animSlv ); - -void -VSs__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster, - void *data, SlaveVP *animSlv ); - -void -VSs__start_transaction( int32 transactionID, SlaveVP *animSlv ); - -void -VSs__end_transaction( int32 transactionID, SlaveVP *animSlv ); - //========================= Internal use only ============================= -void -VSs__Request_Handler( SlaveVP *requestingSlv, void *_langEnv ); -SlaveVP * +bool32 VSs__assign_work_to_slot( void *_langEnv, AnimSlot *slot ); SlaveVP* @@ -365,6 +339,9 @@ VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData, SlaveVP *creatingSlv, int32 coreToAssignOnto); +void +VSs__cleanup_after_shutdown(); + //===================== ===================== #include "VSs_Request_Handlers.h" diff -r dd1efbf29ff9 -r a40859b8dc33 VSs_PluginFns.c --- a/VSs_PluginFns.c Thu Feb 07 16:30:16 2013 -0800 +++ b/VSs_PluginFns.c Sat Mar 02 10:07:58 2013 -0800 @@ -12,17 +12,6 @@ #include "VSs_Request_Handlers.h" //=========================== Local Fn Prototypes =========================== -void -VSs__resume_slave( SlaveVP *slave, VSsLangEnv *langEnv ); - -inline void -handleLangReq( PRReqst *req, SlaveVP *requestingSlv, VSsLangEnv *langEnv ); - -inline void -handleDissipate( SlaveVP *requestingSlv, VSsLangEnv *langEnv ); - -inline void -handleCreate( PRReqst *req, SlaveVP *requestingSlv, VSsLangEnv *langEnv ); //============================== Assigner ================================== // @@ -68,8 +57,9 @@ if( returnSlv != NULL ) //Yes, have a slave, so return it. { returnSlv->coreAnimatedBy = coreNum; - fixme; //check that putting into slot and call chain are correct - PR_int__put_slave_into_slot( returnSlv, slot ); + PR_PI__put_slave_into_slot( returnSlv, slot ); + //Note: PR uses the return boolean to track how much ready work the + // lang env has in it.. goto Success; } @@ -77,8 +67,7 @@ newTaskStub = readPrivQ( langEnv->taskReadyQ ); if( newTaskStub != NULL ) { - fixme; //check that putting into slot and call chain are correct - PR_int__put_task_into_slot( newTaskStub, slot ); + PR_int__put_task_into_slot( newTaskStub, slot ); goto Success; } @@ -144,8 +133,9 @@ //=========================== Helper ============================== void -VSs__resume_slave( SlaveVP *slave, VSsLangEnv *langEnv ) - { +VSs__resume_slave( SlaveVP *slave, void *_langEnv ) + { VSsLangEnv *langEnv = (VSsLangEnv *)_langEnv; + //both suspended tasks and suspended explicit slaves resumed with this writePrivQ( slave, langEnv->slavesReadyToResumeQ ); //PR handles this.. PR_int__set_work_in_lang_env(langEnv); diff -r dd1efbf29ff9 -r a40859b8dc33 VSs_Request_Handlers.c --- a/VSs_Request_Handlers.c Thu Feb 07 16:30:16 2013 -0800 +++ b/VSs_Request_Handlers.c Sat Mar 02 10:07:58 2013 -0800 @@ -17,14 +17,6 @@ //=========================== Local Fn Prototypes =========================== -void -VSs__resume_slave( SlaveVP *slave, VSsLangEnv *langEnv ); - -void -VSs__lang_meta_task_freer( void *_langMetaTask ); - -void -VSs__langDataFreer( void *_langData ); //========================================================================== // Helpers @@ -198,7 +190,7 @@ */ //inline SlaveVP * -handleCreateThd( void *_langReq, SlaveVP *requestingSlv, void *_langEnv ) +VSs__handleCreateThd( void *_langReq, SlaveVP *requestingSlv, void *_langEnv ) { VSsLangReq *langReq; VSsTaskStub *taskStub, *parentTaskStub; SlaveVP *newSlv; @@ -272,7 +264,7 @@ */ //inline void -handleDissipate( void *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv ) +VSs__handleDissipate( void *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv ) { VSsTaskStub *parentTaskStub, *ownTaskStub; @@ -283,14 +275,32 @@ parentTaskStub = ownTaskStub->parentTaskStub; parentTaskStub->numLiveChildThreads -= 1; //parent wasn't freed, even if ended - //if all children ended, then free this task's stub - // else, keep stub around, and last child will free it (below) - if( ownTaskStub->numLiveChildTasks == 0 && - ownTaskStub->numLiveChildThreads == 0 ) - free_task_stub( ownTaskStub ); - else - ownTaskStub->isEnded = TRUE; //for children to see when they end - + //Thinking add a "don't free this!" flag to meta task and lang data, plus + // an "is ended" flag.. to their prologs.. VSs sets the flag at create + // clears it in here.. then PR does all the freeing, calling the freer + // pointed to inside the meta-task/lang-data + //Abort-end of lang or process can lose meta-tasks and lang-datas have the + // flag set.. memory leak.. so add linked list of meta-tasks/lang-datas + // owned by a lang/process.. plus a list of slaves.. free those first, + // then free the meta-tasks and lang-datas left over.. maybe leave as + // a bug for now, fix mem leak later.. + + //if children still live, keep stub around, and last child will free it (below) + if( ownTaskStub->numLiveChildTasks != 0 || + ownTaskStub->numLiveChildThreads != 0 ) + { + PR_PI__set_no_del_flag_in_lang_meta_task( ownTaskStub ); + ownTaskStub->isEnded = TRUE; //for children to see, when they end + } + + //check if this is last child of ended parent (note, not possible to + // have more than one level of ancestor waiting to be freed) + if( parentTaskStub->isEnded && + parentTaskStub->numLiveChildTasks == 0 && + parentTaskStub->numLiveChildThreads == 0 ) + { PR_PI__free_lang_meta_task( parentTaskStub ); //free whole meta-task + } + //Now, check on parents waiting on child threads to end if( parentTaskStub->isWaitingForChildThreadsToEnd && parentTaskStub->numLiveChildThreads == 0 ) @@ -301,66 +311,14 @@ PR_PI__make_slave_ready( PR_PI__give_slave_lang_meta_task_is_assigned_to(parentTaskStub), langEnv ); } - //check if this is last child of ended parent (note, not possible to - // have more than one level of ancestor waiting to be freed) - if( parentTaskStub->isEnded && - parentTaskStub->numLiveChildTasks == 0 && - parentTaskStub->numLiveChildThreads == 0 ) - { free_task_stub( parentTaskStub ); //just stub, langData already freed - } FreeSlaveStateAndReturn: - //PR frees the langData, task stub and requesting slave's base state + //PR frees slave's base state, and also the meta-tasks and lang data, + // except ones have "don't delete" flag set return; } -inline -void -handleShutdownDissipate( SlaveVP *requestingSlv, VSsLangEnv *langEnv ) - { - VSsTaskStub *ownTaskStub; - - ownTaskStub = PR_PI__give_lang_meta_task_from_slave( requestingSlv, VSs_MAGIC_NUMBER ); - free_task_stub( ownTaskStub ); - //PR frees the langData, task stub and requesting slave's base state - return; - } - -/*Register this with PR, during VSs start - * - *At some point, may change PR so that it recycles langData, in which case this - * only gets called when a process shuts down.. at that point, PR will call - * dissipate on all the slaves it has in the recycle Q. - */ -void -freeVSsLangData( void *_langData ) - { VSsLangData *langData; - TransListElem *transElem, *nextTransElem; - - langData = (VSsLangData *)_langData; - transElem = langData->lastTransEntered; - - //Each trans the slave has entered was saved in a linked list elem inside - // lang data -- delete those linked list elements - while( transElem != NULL) - { nextTransElem = transElem->nextTrans; - PR_int__free( transElem ); - transElem = nextTransElem; - } - PR_PI__free( _langData ); - } - -/*Will be used by a landData recycler, when (and if) such a thing added - to PR - */ -void -resetVSsLangData( void *_langData ) - { VSsLangData *langData = (VSsLangData *)_langData; - - langData->highestTransEntered = -1; - langData->lastTransEntered = NULL; - } //========================================================================== // @@ -445,9 +403,10 @@ * decide garbage collection of no-longer-used pointers later) * */ -//inline +//Here's the typedef this Fn's signature has to match: +//typedef void * (*CreateHandler)( void *, SlaveVP *, void * ); //req, slv, langEnv void * -handleSubmitTask( VSsLangReq *langReq, VSsLangEnv *langEnv ) +VSs__handleSubmitTask( VSsLangReq *langReq, SlaveVP *slave, VSsLangEnv *langEnv ) { uint32 key[3]; HashEntry *rawHashEntry; //has char *, but use with uint32 * VSsPointerEntry *ptrEntry; //contents of hash table entry for an arg pointer @@ -472,6 +431,7 @@ taskStub = create_task_stub( taskType, args );//copies arg ptrs taskStub->numBlockingProp = taskType->numCtldArgs; + //PR does this (metaTask contains taskID): taskStub->taskID = langReq->taskID; parentTaskStub = (VSsTaskStub *)PR_PI__give_lang_meta_task_from_slave(langReq->callingSlv, VSs_MAGIC_NUMBER); @@ -502,12 +462,15 @@ rawHashEntry = addValueIntoTable32( key, ptrEntry, argPtrHashTbl ); } else - { ptrEntry = (VSsPointerEntry *)rawHashEntry->content; + { //The hash table returns a "hashEntry" struct, which then holds + // a "pointer entry" struct -- get that struct for this hash value + ptrEntry = (VSsPointerEntry *)rawHashEntry->content; if( ptrEntry == NULL ) { ptrEntry = create_pointer_entry(); rawHashEntry = addValueIntoTable32(key, ptrEntry, argPtrHashTbl); } } + //save into task stub, the struct that holds meta-info about a pointer taskStub->ptrEntries[argNum] = ptrEntry; /*Have the hash entry. @@ -603,7 +566,7 @@ */ //inline void -handleEndTask( VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv ) +VSs__handleEndTask( VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv ) { VSsPointerEntry *ptrEntry; //contents of hash table entry for an arg pointer void **args; VSsTaskStub *endingTaskStub, *waitingTaskStub, *parentStub; @@ -631,8 +594,10 @@ } //Check if parent ended, and this was last descendent, then free it - if( parentStub->isEnded && parentStub->numLiveChildTasks == 0 ) - { free_task_stub( parentStub ); + if( parentStub->isEnded && + parentStub->numLiveChildTasks == 0 && + parentStub->numLiveChildThreads == 0 ) + { PR_PI__free_lang_meta_task( parentStub ); } @@ -730,17 +695,24 @@ //done ending the task, if still has live children, then keep stub around // else, free the stub and args copy - if( endingTaskStub->numLiveChildTasks == 0 && - endingTaskStub->numLiveChildThreads == 0 ) - { free_task_stub( endingTaskStub ); + if( endingTaskStub->numLiveChildTasks != 0 || + endingTaskStub->numLiveChildThreads != 0 ) + { PR_PI__set_no_del_flag_in_lang_meta_task( endingTaskStub ); } return; } + +/*This is called during shutdown, to delete a task that still has dependencies + * unfulfilled. + *VSs has a complex meta task, so this freer has to do a fair amount. + * The arguments were copied over into the meta task, and there are queues of + * other tasks waiting on completion of this one + */ //inline void -handleFreeTask( void *langMetaTask ) +VSs__free_waiting_task( void *langMetaTask ) { VSsPointerEntry *ptrEntry; //contents of hash table entry for an arg pointer void **args; VSsTaskStub *endingTaskStub, *waitingTaskStub; @@ -761,7 +733,7 @@ */ int32 argNum; for( argNum = 0; argNum < endingTaskType->numCtldArgs; argNum++ ) - { + { ptrEntry = ptrEntries[argNum]; while( TRUE ) { @@ -781,7 +753,7 @@ waitingTaskStub->numBlockingProp -= 1; if( waitingTaskStub->numBlockingProp == 0 ) { //last ptrEntry holding the task, so free it - free_task_stub( endingTaskStub ); + VSs__free_langlet_part_of_lang_meta_task( endingTaskStub ); } } }// @@ -789,13 +761,42 @@ } +/*Two use-cases for freeing a meta-task.. one is the langlet has control + * over the meta tasks's life-line it may differ from the task-work-unit's + * lifeline.. the other is PR controls, for example when a langlet or + * process gets pre-maturely shutdown due to outside influences, or exception, + * and so on.. + *In the first case, the langlet has two choices.. it can free all the langlet + * malloc'd data owned by the meta-task, then as PR to free the remaining + * proto meta-task.. or, it can just call PR's full-service "free meta-task" + * which in turn calls the langlet's "free just langlet-malloc'd data" Fn, which + * was given to the meta-task creator.. + * + *In the second case, PR calls the langlet's "free just langlet malloc'd data" + * Fn, which was given to the meta-task creator. The langlet has no other + * involvement. + * + *This is the VSs call that the langlet uses when it separately frees its own + * portion of the meta-task. + */ +void +VSs__free_full_lang_meta_task( VSsTaskStub *taskStub ) + { + + } + + +/*Frees only the langlet's portion of the meta task. + *This is given to PR when a meta task is created. It is also used by the + * end task handler, which may choose to keep the meta task info far past the + * end of the task's existence.. + */ //inline void -free_task_stub( VSsTaskStub *stubToFree ) +VSs__free_langlet_part_of_lang_meta_task( VSsTaskStub *stubToFree ) { if(stubToFree->ptrEntries != NULL ) //a thread stub has NULL entry { PR_PI__free( stubToFree->ptrEntries ); } - PR_PI__free( stubToFree ); } //========================== Task Comm handlers =========================== @@ -815,7 +816,7 @@ */ //inline void -handleSendTypeTo( VSsLangReq *langReq, SlaveVP *reqSlave, VSsLangEnv *langEnv ) +VSs__handleSendTypeTo( VSsLangReq *langReq, SlaveVP *reqSlave, VSsLangEnv *langEnv ) { SlaveVP *senderSlv, *receiverSlv; int32 *senderID, *receiverID; int32 *key, keySz, receiverIDNumInt; @@ -923,7 +924,7 @@ //TODO: combine both send handlers into single handler //inline void -handleSendFromTo( VSsLangReq *langReq, SlaveVP *dummySlave, VSsLangEnv *langEnv) +VSs__handleSendFromTo( VSsLangReq *langReq, SlaveVP *dummySlave, VSsLangEnv *langEnv) { SlaveVP *senderSlv, *receiverSlv; int32 *senderID, *receiverID; int32 *key, keySz, receiverIDNumInt, senderIDNumInt; @@ -1004,7 +1005,7 @@ //inline void -handleReceiveTypeTo( VSsLangReq *langReq, SlaveVP *dummySlv, VSsLangEnv *langEnv) +VSs__handleReceiveTypeTo( VSsLangReq *langReq, SlaveVP *dummySlv, VSsLangEnv *langEnv) { SlaveVP *senderSlv, *receiverSlv; int32 *receiverID; int32 *key, keySz, receiverIDNumInt; @@ -1090,7 +1091,7 @@ */ //inline void -handleReceiveFromTo( VSsLangReq *langReq, SlaveVP *dummySlv, VSsLangEnv *langEnv) +VSs__handleReceiveFromTo( VSsLangReq *langReq, SlaveVP *dummySlv, VSsLangEnv *langEnv) { SlaveVP *senderSlv, *receiverSlv; int32 *senderID, *receiverID; int32 *key, keySz, receiverIDNumInt, senderIDNumInt; @@ -1161,7 +1162,7 @@ */ //inline void -handleTaskwait( VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv) +VSs__handleTaskwait( VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv) { VSsTaskStub* taskStub; DEBUG__printf1(dbgRqstHdlr,"Taskwait request from processor %d", @@ -1179,256 +1180,16 @@ } } - -//========================================================================== -/* - */ void -handleMalloc( VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv ) - { void *ptr; - - DEBUG__printf1(dbgRqstHdlr,"Malloc request from processor %d",requestingSlv->slaveNum) - - ptr = PR_PI__malloc( langReq->sizeToMalloc ); - requestingSlv->dataRetFromReq = ptr; - PR_PI__make_slave_ready( requestingSlv, langEnv ); +VSs__handleWaitForVSsWorkToEnd( VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv) + { + PR_PI__handle_wait_for_langlets_work_to_end( requestingSlv, langEnv ); } -/* - */ void -handleFree( VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv ) +VSs__handleWaitThenShutdown( VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv) { - DEBUG__printf1(dbgRqstHdlr,"Free request from processor %d",requestingSlv->slaveNum) - PR_PI__free( langReq->ptrToFree ); - PR_PI__make_slave_ready( requestingSlv, langEnv ); - } - - -//=========================================================================== -// -/*Uses ID as index into array of flags. If flag already set, resumes from - * end-label. Else, sets flag and resumes normally. - */ -void -//inline -handleStartSingleton_helper( VSsSingleton *singleton, SlaveVP *reqstingSlv, - VSsLangEnv *langEnv ) - { - if( singleton->hasFinished ) - { //the code that sets the flag to true first sets the end instr addr - reqstingSlv->dataRetFromReq = singleton->endInstrAddr; - PR_PI__make_slave_ready( reqstingSlv, langEnv ); - return; - } - else if( singleton->hasBeenStarted ) - { //singleton is in-progress in a diff slave, so wait for it to finish - writePrivQ(reqstingSlv, singleton->waitQ ); - return; - } - else - { //hasn't been started, so this is the first attempt at the singleton - singleton->hasBeenStarted = TRUE; - reqstingSlv->dataRetFromReq = 0x0; - PR_PI__make_slave_ready( reqstingSlv, langEnv ); - return; - } - } -void -//inline -handleStartFnSingleton( VSsLangReq *langReq, SlaveVP *requestingSlv, - VSsLangEnv *langEnv ) - { VSsSingleton *singleton; - DEBUG__printf1(dbgRqstHdlr,"StartFnSingleton request from processor %d",requestingSlv->slaveNum) - - singleton = &(langEnv->fnSingletons[ langReq->singletonID ]); - handleStartSingleton_helper( singleton, requestingSlv, langEnv ); - } -void -//inline -handleStartDataSingleton( VSsLangReq *langReq, SlaveVP *requestingSlv, - VSsLangEnv *langEnv ) - { VSsSingleton *singleton; - - DEBUG__printf1(dbgRqstHdlr,"StartDataSingleton request from processor %d",requestingSlv->slaveNum) - if( *(langReq->singletonPtrAddr) == NULL ) - { singleton = PR_PI__malloc( sizeof(VSsSingleton) ); - singleton->waitQ = makePRQ(); - singleton->endInstrAddr = 0x0; - singleton->hasBeenStarted = FALSE; - singleton->hasFinished = FALSE; - *(langReq->singletonPtrAddr) = singleton; - } - else - singleton = *(langReq->singletonPtrAddr); - handleStartSingleton_helper( singleton, requestingSlv, langEnv ); - } - - -void -//inline -handleEndSingleton_helper( VSsSingleton *singleton, SlaveVP *requestingSlv, - VSsLangEnv *langEnv ) - { PrivQueueStruc *waitQ; - int32 numWaiting, i; - SlaveVP *resumingSlv; - - if( singleton->hasFinished ) - { //by definition, only one slave should ever be able to run end singleton - // so if this is true, is an error - ERROR1( "singleton code ran twice", requestingSlv ); - } - - singleton->hasFinished = TRUE; - waitQ = singleton->waitQ; - numWaiting = numInPrivQ( waitQ ); - for( i = 0; i < numWaiting; i++ ) - { //they will resume inside start singleton, then jmp to end singleton - resumingSlv = readPrivQ( waitQ ); - resumingSlv->dataRetFromReq = singleton->endInstrAddr; - PR_PI__make_slave_ready( resumingSlv, langEnv ); - } - - PR_PI__make_slave_ready( requestingSlv, langEnv ); - -} -void -handleEndFnSingleton( VSsLangReq *langReq, SlaveVP *requestingSlv, - VSsLangEnv *langEnv ) - { - VSsSingleton *singleton; - - DEBUG__printf1(dbgRqstHdlr,"EndFnSingleton request from processor %d",requestingSlv->slaveNum) - - singleton = &(langEnv->fnSingletons[ langReq->singletonID ]); - handleEndSingleton_helper( singleton, requestingSlv, langEnv ); - } -void -handleEndDataSingleton( VSsLangReq *langReq, SlaveVP *requestingSlv, - VSsLangEnv *langEnv ) - { - VSsSingleton *singleton; - - DEBUG__printf1(dbgRqstHdlr,"EndDataSingleton request from processor %d",requestingSlv->slaveNum) - - singleton = *(langReq->singletonPtrAddr); - handleEndSingleton_helper( singleton, requestingSlv, langEnv ); - } - - -/*This executes the function in the masterVP, take the function - * pointer out of the request and call it, then resume the VP. - */ -void -handleAtomic( VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv ) - { - DEBUG__printf1(dbgRqstHdlr,"Atomic request from processor %d",requestingSlv->slaveNum) - langReq->fnToExecInMaster( langReq->dataForFn ); - PR_PI__make_slave_ready( requestingSlv, langEnv ); - } - -/*First, it looks at the VP's semantic data, to see the highest transactionID - * that VP - * already has entered. If the current ID is not larger, it throws an - * exception stating a bug in the code. - *Otherwise it puts the current ID - * there, and adds the ID to a linked list of IDs entered -- the list is - * used to check that exits are properly ordered. - *Next it is uses transactionID as index into an array of transaction - * structures. - *If the "VP_currently_executing" field is non-null, then put requesting VP - * into queue in the struct. (At some point a holder will request - * end-transaction, which will take this VP from the queue and resume it.) - *If NULL, then write requesting into the field and resume. - */ -void -handleTransStart( VSsLangReq *langReq, SlaveVP *requestingSlv, - VSsLangEnv *langEnv ) - { VSsLangData *langData; - TransListElem *nextTransElem; - - DEBUG__printf1(dbgRqstHdlr,"TransStart request from processor %d",requestingSlv->slaveNum) - - //check ordering of entering transactions is correct - langData = PR_PI__give_lang_data(requestingSlv, VSs_MAGIC_NUMBER); - if( langData->highestTransEntered > langReq->transID ) - { //throw PR exception, which shuts down PR. - PR_PI__throw_exception( "transID smaller than prev", requestingSlv, NULL); - } - //add this trans ID to the list of transactions entered -- check when - // end a transaction - langData->highestTransEntered = langReq->transID; - nextTransElem = PR_PI__malloc( sizeof(TransListElem) ); - nextTransElem->transID = langReq->transID; - nextTransElem->nextTrans = langData->lastTransEntered; - langData->lastTransEntered = nextTransElem; - - //get the structure for this transaction ID - VSsTrans * - transStruc = &(langEnv->transactionStrucs[ langReq->transID ]); - - if( transStruc->VPCurrentlyExecuting == NULL ) - { - transStruc->VPCurrentlyExecuting = requestingSlv; - PR_PI__make_slave_ready( requestingSlv, langEnv ); - } - else - { //note, might make future things cleaner if save request with VP and - // add this trans ID to the linked list when gets out of queue. - // but don't need for now, and lazy.. - writePrivQ( requestingSlv, transStruc->waitingVPQ ); - } - } - - -/*Use the trans ID to get the transaction structure from the array. - *Look at VP_currently_executing to be sure it's same as requesting VP. - * If different, throw an exception, stating there's a bug in the code. - *Next, take the first element off the list of entered transactions. - * Check to be sure the ending transaction is the same ID as the next on - * the list. If not, incorrectly nested so throw an exception. - * - *Next, get from the queue in the structure. - *If it's empty, set VP_currently_executing field to NULL and resume - * requesting VP. - *If get somethine, set VP_currently_executing to the VP from the queue, then - * resume both. - */ -void -handleTransEnd(VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv) - { VSsLangData *langData; - SlaveVP *waitingSlv; - VSsTrans *transStruc; - TransListElem *lastTrans; - - DEBUG__printf1(dbgRqstHdlr,"TransEnd request from processor %d",requestingSlv->slaveNum) - - transStruc = &(langEnv->transactionStrucs[ langReq->transID ]); - - //make sure transaction ended in same VP as started it. - if( transStruc->VPCurrentlyExecuting != requestingSlv ) - { - PR_PI__throw_exception( "trans ended in diff VP", requestingSlv, NULL ); - } - - //make sure nesting is correct -- last ID entered should == this ID - langData = PR_PI__give_lang_data(requestingSlv, VSs_MAGIC_NUMBER); - lastTrans = langData->lastTransEntered; - if( lastTrans->transID != langReq->transID ) - { - PR_PI__throw_exception( "trans incorrectly nested", requestingSlv, NULL ); - } - - langData->lastTransEntered = langData->lastTransEntered->nextTrans; - - - waitingSlv = readPrivQ( transStruc->waitingVPQ ); - transStruc->VPCurrentlyExecuting = waitingSlv; - - if( waitingSlv != NULL ) - PR_PI__make_slave_ready( waitingSlv, langEnv ); - - PR_PI__make_slave_ready( requestingSlv, langEnv ); + implement_me(); } void diff -r dd1efbf29ff9 -r a40859b8dc33 VSs_Request_Handlers.h --- a/VSs_Request_Handlers.h Thu Feb 07 16:30:16 2013 -0800 +++ b/VSs_Request_Handlers.h Sat Mar 02 10:07:58 2013 -0800 @@ -15,31 +15,57 @@ */ SlaveVP * -handleCreateThd( void *_langReq, SlaveVP *requestingSlv, void *_langEnv ); +VSs__handleCreateThd( void *_langReq, SlaveVP *requestingSlv, void *_langEnv ); void -handleDissipate( void *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv ); +VSs__handleDissipate( void *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv ); void * -handleSubmitTask( VSsLangReq *langReq, VSsLangEnv *langEnv); +VSs__handleSubmitTask( VSsLangReq *langReq, SlaveVP *reqSlv, VSsLangEnv *langEnv); void -handleEndTask( VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv ); +VSs__handleEndTask( VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv ); void -handleSendTypeTo( VSsLangReq *langReq, SlaveVP *dummySlv, VSsLangEnv *langEnv); +VSs__handleSendTypeTo( VSsLangReq *langReq, SlaveVP *dummySlv, VSsLangEnv *langEnv); void -handleSendFromTo( VSsLangReq *langReq, SlaveVP* dummySlv, VSsLangEnv *langEnv); +VSs__handleSendFromTo( VSsLangReq *langReq, SlaveVP* dummySlv, VSsLangEnv *langEnv); void -handleReceiveTypeTo( VSsLangReq *langReq, SlaveVP *dummySlv, VSsLangEnv *langEnv); +VSs__handleReceiveTypeTo( VSsLangReq *langReq, SlaveVP *dummySlv, VSsLangEnv *langEnv); void -handleReceiveFromTo( VSsLangReq *langReq, SlaveVP *dummySlv, VSsLangEnv *langEnv); +VSs__handleReceiveFromTo( VSsLangReq *langReq, SlaveVP *dummySlv, VSsLangEnv *langEnv); void -handleTaskwait(VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv); +VSs__handleTaskwait(VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv); + +//==================================== +void +VSs__lang_meta_task_freer( void *_langMetaTask ); + inline void -free_task_stub( VSsTaskStub *stubToFree ); +VSs__free_langlet_part_of_lang_meta_task( VSsTaskStub *stubToFree ); + +void +VSs__langDataFreer( void *_langData ); VSsTaskStub * VSs__create_generic_slave_task_stub_in_slave( SlaveVP *slave ); +void +VSs__handle_shutdown( void *_langEnv ); +void * +VSs__create_lang_data_in_slave( SlaveVP *slave ); +void * +VSs__create_empty_lang_meta_task_in_slave( SlaveVP *slave ); + + +void +VSs__handleWaitForVSsWorkToEnd( VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv); +void +VSs__handleWaitThenShutdown( VSsLangReq *langReq, SlaveVP *requestingSlv, VSsLangEnv *langEnv); + +void +VSs__resume_slave( SlaveVP *slave, void *_langEnv ); +void +VSs__make_task_ready( void *taskStub, void *_langEnv ); + #endif /* _VSs_REQ_H */ diff -r dd1efbf29ff9 -r a40859b8dc33 VSs_SS.c --- a/VSs_SS.c Thu Feb 07 16:30:16 2013 -0800 +++ b/VSs_SS.c Sat Mar 02 10:07:58 2013 -0800 @@ -12,7 +12,7 @@ #include "Hash_impl/PrivateHash.h" #include "VSs.h" -#include "Measurement/VSs_Counter_Recording.h" +#include "PR_impl/Services_Offered_by_PR/Measurement_and_Stats/PR_MEAS__Counter_Recording.h" //========================================================================== @@ -26,11 +26,11 @@ VSs__start( SlaveVP *seedSlv ) { VSsLangEnv *langEnv; int32 i; - VSsLangData *langData; + VSsLangData *langData; VSsTaskStub *threadTaskStub, *parentTaskStub; langEnv = - PR_SS__create_lang_env( sizeof(VSsLangEnv), seedSlv, VSs_MAGIC_NUMBER); + (VSsLangEnv *)PR_SS__create_lang_env( sizeof(VSsLangEnv), seedSlv, VSs_MAGIC_NUMBER); //seed slave is a thread slave, so make a thread's task stub for it // and then make another to stand for the seed's parent task. Make @@ -44,7 +44,7 @@ threadTaskStub->isWaitingForChildTasksToEnd = FALSE; parentTaskStub = - PR_int__create_lang_meta_task(sizeof(VSsTaskStub), &VSs__lang_meta_task_freer, seedSlv, VSs_MAGIC_NUMBER); + PR_int__create_lang_meta_task(sizeof(VSsTaskStub), &VSs__lang_meta_task_freer, VSs_MAGIC_NUMBER); parentTaskStub->isEnded = TRUE; parentTaskStub->numLiveChildThreads = 1; //so dissipate works for seed @@ -53,20 +53,11 @@ //register the langlet's handlers with PR PR_SS__register_assigner( &VSs__assign_work_to_slot, seedSlv, VSs_MAGIC_NUMBER ); - PR_SS__register_shutdown_handler( &VSs__handle_shutdown, seedSlv, VSs_MAGIC_NUMBER ); + PR_SS__register_lang_shutdown_handler( &VSs__handle_shutdown, seedSlv, VSs_MAGIC_NUMBER ); PR_SS__register_lang_data_creator( &VSs__create_lang_data_in_slave, seedSlv, VSs_MAGIC_NUMBER ); PR_SS__register_lang_meta_task_creator( &VSs__create_empty_lang_meta_task_in_slave, seedSlv, VSs_MAGIC_NUMBER ); - PR_SS__register_make_slave_ready_fn( &VSs__resume_slave ); - PR_SS__register_make_task_ready_fn( &VSs__make_task_ready ); -/* - PR_SS__register_create_task_handler( &createTaskHandler, seedVP, VSs_MAGIC_NUMBER ); - PR_SS__register_end_task_handler( &endTaskHandler, seedVP, VSs_MAGIC_NUMBER ); - PR_SS__register_create_slave_handler( &createThreadHandler, seedVP, VSs_MAGIC_NUMBER ); - PR_SS__register_dissipate_slave_handler( &endThreadHandler, seedVP, VSs_MAGIC_NUMBER ); - RequestHandler createInitialLangDataFn; - RequestHandler resetLangDataFn; - PR_SS__register_request_handler( &VSs__Request_Handler, seedSlv, VSs_MAGIC_NUMBER ); - */ + PR_SS__register_make_slave_ready_fn( &VSs__resume_slave, seedSlv, VSs_MAGIC_NUMBER ); + PR_SS__register_make_task_ready_fn( &VSs__make_task_ready, seedSlv, VSs_MAGIC_NUMBER ); #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS _PRTopEnv->counterHandler = &PR_MEAS__counter_handler; @@ -95,13 +86,17 @@ memset(langEnv->last_in_slot,0,sizeof(NUM_CORES * NUM_ANIM_SLOTS * sizeof(Unit))); #endif - MEAS__Make_Meas_Hists_for_VSs + MEAS__Make_Meas_Hists_for_VSs(seedSlv, VSs_MAGIC_NUMBER); } -/*This shuts down the langlet + +/*This runs inside the MasterVP. + *It shuts down the langlet * Frees any memory allocated by VSs__init() and deletes any slaves or tasks * still in ready Qs. + * + *Note: it needs the special lang-shutdown-request-handler prototype */ void VSs__handle_shutdown( void *_langEnv ) @@ -229,36 +224,28 @@ SlaveVP *slave; VSsTaskStub *task; - //dissipate any slaves still in the readyQ + //Not clear what to do with ready slaves still in readyQ.. reasonable to + // end them.. also reasonable to send them over to PRServ. + //Decided to send ready slaves over to PRServ queue = langEnv->slavesReadyToResumeQ; slave = readPrivQ( queue ); while( slave != NULL ) - { handleShutdownDissipate( slave ); - PR_int__recycle_slave( slave ); //recycler is for all of PR + { PR_PI__resume_slave_in_PRServ( slave ); //recycler is for all of PR slave = readPrivQ( queue ); } freePrivQ( queue ); - //end any tasks still in the readyQ + //delete any tasks in the readyQ queue = langEnv->taskReadyQ; task = readPrivQ( queue ); while( task != NULL ) - { handleFreeTask( task ); + { VSs__free_waiting_task( task ); task = readPrivQ( queue ); } freePrivQ( queue ); freeHashTable( langEnv->commHashTbl ); freeHashTable( langEnv->argPtrHashTbl ); - - int32 i; - for( i = 0; i < NUM_STRUCS_IN_LANG_ENV; i++ ) - { - freePrivQ( langEnv->fnSingletons[i].waitQ ); - freePrivQ( langEnv->transactionStrucs[i].waitingVPQ ); - } - - PR_int__free_lang_env( langEnv ); }