# HG changeset patch # User Sean Halle # Date 1352083168 28800 # Node ID 608833ae2c5db11e31aa853f987e62c812835a18 # Parent a5fa1e087c7e5ce5d44fa23e55067711636dd48d Checkpoint -- about to clean up AnimationMaster, deleting a bunch of stuff diff -r a5fa1e087c7e -r 608833ae2c5d AnimationMaster.c --- a/AnimationMaster.c Thu Oct 25 23:35:36 2012 -0700 +++ b/AnimationMaster.c Sun Nov 04 18:39:28 2012 -0800 @@ -13,7 +13,7 @@ #include "VSs_impl/VSs.h" inline void -replaceWithNewSlotSlv( SlaveVP *requestingSlv, PRProcessEnv *processEnv ); +replaceWithNewSlotSlv( SlaveVP *slave ); /*The animationMaster embodies most of the animator of the language. The @@ -189,13 +189,13 @@ if( currSlot->workIsDone ) { currSlot->workIsDone = FALSE; - currSlot->needsSlaveAssigned = TRUE; + currSlot->needsWorkAssigned = TRUE; HOLISTIC__Record_AppResponder_start; MEAS__startReqHdlr; currSlot->workIsDone = FALSE; - currSlot->needsSlaveAssigned = TRUE; + currSlot->needsWorkAssigned = TRUE; SlaveVP *currSlave = currSlot->slaveAssignedToSlot; justAddedReqHdlrChg(); @@ -223,7 +223,7 @@ MEAS__endReqHdlr; } //If slot empty, hand to Assigner to fill with a slave - if( currSlot->needsSlaveAssigned ) + if( currSlot->needsWorkAssigned ) { //Call plugin's Assigner to give slot a new slave HOLISTIC__Record_Assigner_start; assignedSlaveVP = @@ -233,7 +233,7 @@ if( assignedSlaveVP != NULL ) { currSlot->slaveAssignedToSlot = assignedSlaveVP; assignedSlaveVP->animSlotAssignedTo = currSlot; - currSlot->needsSlaveAssigned = FALSE; + currSlot->needsWorkAssigned = FALSE; numSlotsFilled += 1; HOLISTIC__Record_Assigner_end; @@ -270,7 +270,6 @@ //#ifdef MODE__MULTI_LANG SlaveVP *slave; PRProcess *process; - PRConstrEnvHolder *constrEnvHolder; int32 langMagicNumber; //#endif @@ -318,15 +317,15 @@ slave = currSlot->slaveAssignedToSlot; //check if the completed work was a task.. - if( slave->taskMetaInfo->isATask ) + if( slave->metaTask->isATask ) { - if( slave->reqst->type == TaskEnd ) + if( slave->request->type == TaskEnd ) { //do task end handler, which is registered separately //note, end hdlr may use semantic data from reqst.. //#ifdef MODE__MULTI_LANG //get end-task handler //taskEndHandler = lookup( slave->reqst->langMagicNumber, processEnv ); - taskEndHandler = slave->taskMetaInfo->endTaskHandler; + taskEndHandler = slave->metaTask->endTaskHandler; //#endif (*taskEndHandler)( slave, semanticEnv ); @@ -353,7 +352,7 @@ } //if has suspended slave that needs handling //if slot empty, hand to Assigner to fill with a slave - if( currSlot->needsSlaveAssigned ) + if( currSlot->needsWorkAssigned ) { //Call plugin's Assigner to give slot a new slave HOLISTIC__Record_Assigner_start; @@ -365,12 +364,12 @@ if( assignedSlaveVP != NULL ) { currSlot->slaveAssignedToSlot = assignedSlaveVP; assignedSlaveVP->animSlotAssignedTo = currSlot; - currSlot->needsSlaveAssigned = FALSE; + currSlot->needsWorkAssigned = FALSE; numSlotsFilled += 1; } else { - currSlot->needsSlaveAssigned = TRUE; //local write + currSlot->needsWorkAssigned = TRUE; //local write } HOLISTIC__Record_Assigner_end; }//if slot needs slave assigned @@ -496,7 +495,6 @@ //#ifdef MODE__MULTI_LANG SlaveVP *slave; PRProcess *process; - PRConstrEnvHolder *constrEnvHolder; int32 langMagicNumber; //#endif @@ -579,7 +577,7 @@ } //if has suspended slave that needs handling //if slot empty, hand to Assigner to fill with a slave - if( currSlot->needsSlaveAssigned ) + if( currSlot->needsWorkAssigned ) { //Call plugin's Assigner to give slot a new slave HOLISTIC__Record_Assigner_start; @@ -591,12 +589,12 @@ if( assignedSlaveVP != NULL ) { currSlot->slaveAssignedToSlot = assignedSlaveVP; assignedSlaveVP->animSlotAssignedTo = currSlot; - currSlot->needsSlaveAssigned = FALSE; + currSlot->needsWorkAssigned = FALSE; numSlotsFilled += 1; } else { - currSlot->needsSlaveAssigned = TRUE; //local write + currSlot->needsWorkAssigned = TRUE; //local write } HOLISTIC__Record_Assigner_end; }//if slot needs slave assigned @@ -618,7 +616,6 @@ void animationMaster( void *initData, SlaveVP *masterVP ) { int32 slotIdx; -// int32 numSlotsFilled; AnimSlot *currSlot; //Used while scanning and filling animation slots AnimSlot **animSlots; @@ -661,6 +658,77 @@ #endif //MODE__MULTI_LANG #endif //MODE__MULTI_PROCESS + +//This version of the master selects one of three loops, depending upon +// whether stand-alone single language (just slaves), or standalone with +// tasks, or multi-lang (implies multi-process) +void animationMaster( void *initData, SlaveVP *masterVP ) + { + int32 slotIdx; + AnimSlot *currSlot; + //Used while scanning and filling animation slots + AnimSlot **animSlots; + + //Local copies, for performance + MasterEnv *masterEnv; + int32 thisCoresIdx; + + //======================== Initializations ======================== + masterEnv = (MasterEnv*)_PRTopEnv; + + thisCoresIdx = masterVP->coreAnimatedBy; + animSlots = masterEnv->allAnimSlots[thisCoresIdx]; + + HOLISTIC__Insert_Master_Global_Vars; + + //======================== animationMaster ======================== + //Have three different modes, and the master behavior is different for + // each, so jump to the loop that corresponds to the mode. + // + switch(mode) + { case StandaloneSlavesOnly: + while(1) + { MEAS__Capture_Pre_Master_Point + for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) + { + currSlot = animSlots[ slotIdx ]; + + masterFunction_StandaloneSlavesOnly( currSlot ); + } + MEAS__Capture_Post_Master_Point; + masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master + flushRegisters(); + } + case StandaloneWTasks: + while(1) + { MEAS__Capture_Pre_Master_Point + for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) + { + currSlot = animSlots[ slotIdx ]; + + masterFunction_StandaloneWTasks( currSlot ); + } + MEAS__Capture_Post_Master_Point; + masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master + flushRegisters(); + } + case MultiLang: + while(1) + { MEAS__Capture_Pre_Master_Point + for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) + { + currSlot = animSlots[ slotIdx ]; + + masterFunction_multiLang( currSlot ); + } + MEAS__Capture_Post_Master_Point; + masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master + flushRegisters(); + } + } + } + + inline void masterFunction_multiLang( AnimSlot *currSlot ) @@ -675,6 +743,7 @@ //Check if newly-done slave in slot, which will need request handled if( currSlot->workIsDone ) { currSlot->workIsDone = FALSE; + currSlot->needsWorkAssigned = TRUE; HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot MEAS__startReqHdlr; @@ -682,94 +751,56 @@ //process the request made by the slave (held inside slave struc) slave = currSlot->slaveAssignedToSlot; - - //check if the slave was doing a task.. - //Action depends on both on the request type, and whether it's on - // a generic slave vs a suspended task - if( slave->metaTask->taskType == AtomicTask || - slave->metaTask->taskType == SuspendedTask ) - { - switch( slave->request->reqType ) - { case TaskEnd: - { PRHandle_EndTask( slave ); //if free task slave, update count, put into recycle Q -- do handler before lang's handler + req = slave->request; - //do task end handler, which is registered separately - //note, end hdlr may use semantic data from reqst.. - //get end-task handler + //If the requesting slave is a slot slave, and request is not + // task-end, then turn it into a free task slave. + if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd ) + replaceWithNewSlotSlv( slave ); - RequestHandler - taskEndHandler = slave->request->handler; - semanticEnv = PR_int__give_sem_env_for_slave( slave, - slave->request->langMagicNumber ); - (*taskEndHandler)( slave, semanticEnv ); + //Handle task create and end first -- they're special cases.. + switch( req->reqType ) + { case TaskEnd: + { //do PR handler, which calls lang's hdlr and does recycle of + // free task slave if needed -- PR handler checks for free task Slv + PRHandle_EndTask( slave ); break; + } + case TaskCreate: + { //Do PR's create-task handler, which calls the lang's hdlr + // PR handler checks for free task Slv + PRHandle_CreateTask( slave ); break; + } + case SlvCreate: PRHandle_CreateSlave( slave ); break; + case SlvDissipate: PRHandle_Dissipate( slave ); break; + case Service: PR_int__handle_PRServiceReq( slave ); break; //resume into PR's own semantic env + case Hardware: //for future expansion + case IO: //for future expansion + case OSCall: //for future expansion + PR_int__throw_exception("Not implemented"); break; + case Language: //normal sem request + magicNumber = req->langMagicNumber; + semanticEnv = PR_PI__give_sem_env_for( slave, magicNumber ); + requestHandler = semanticEnv->requestHdlr; + (*requestHandler)( req->semReq, slave, semanticEnv ); + } - goto AssignWork; - } - case TaskCreate: - { PRHandle_CreateTask( slave ); - RequestHandler - taskCreateHandler = slave->request->handler; - semanticEnv = PR_int__give_sem_env_for_slave( slave, - slave->request->langMagicNumber ); - (*taskCreateHandler)( slave, semanticEnv ); //resumes creating slave - goto AssignWork; - } - default: - { //is a task, and just suspended, so tied to a free task slave - //First turn slot slave into free task slave & make replacement - if( slave->typeOfVP == SlotTaskSlv ) - replaceWithNewSlotSlv( slave, slave->processSlaveIsIn->processEnv ); - - //goto normal slave request handling - goto SlaveReqHandling; - } - } - } - else //is a slave that suspended - { - - SlaveReqHandling: - //Q: put the switch in inline call, to clean up code? - req = slave->request; - switch( req->reqType ) - { case SlvCreate: PRHandle_CreateSlave( slave ); break; - case SlvDissipate: PRHandle_Dissipate( slave ); break; - case Service: PR_int__handle_PRServiceReq( slave ); break; //resume into PR's own semantic env - case Hardware: //for future expansion - case IO: //for future expansion - case OSCall: //for future expansion - case Language: //normal sem request - magicNumber = slave->request->langMagicNumber; - semanticEnv = PR_PI__give_sem_env_for( slave, magicNumber ); - requestHandler = semanticEnv->requestHdlr; - (*requestHandler)( slave, semanticEnv ); //(note: indirect Fn call more efficient when use fewer params, instead re-fetch from slave) - } - - HOLISTIC__Record_AppResponder_end; - MEAS__endReqHdlr; - - goto AssignWork; - } - } //if has suspended slave that needs handling + HOLISTIC__Record_AppResponder_end; + MEAS__endReqHdlr; + } //if have request to be handled - //End up here when the slot did not have ended work in it (no req) - //So, here, if slot empty, look for work to fill the slot - if( currSlot->needsSlaveAssigned ) - { HOLISTIC__Record_Assigner_start; - - AssignWork: + if( currSlot->needsWorkAssigned ) + { + HOLISTIC__Record_Assigner_start; + //Scan sem environs, looking for semEnv with ready work. // call the Assigner for that sem Env, to get a slave for the slot assignedSlaveVP = assignWork( semanticEnv, currSlot ); - //put the chosen slave into slot, and adjust flags and state + //if work found, put into slot, and adjust flags and state if( assignedSlaveVP != NULL ) { currSlot->slaveAssignedToSlot = assignedSlaveVP; assignedSlaveVP->animSlotAssignedTo = currSlot; - currSlot->needsSlaveAssigned = FALSE; - } - else - { currSlot->needsSlaveAssigned = TRUE; //local write + currSlot->needsWorkAssigned = FALSE; } HOLISTIC__Record_Assigner_end; }//if slot needs slave assigned @@ -786,6 +817,9 @@ replaceWithNewSlotSlv( SlaveVP *requestingSlv, PRProcess *process ) { SlaveVP *newSlotSlv; + When slot slave converted to a free task slave, insert the process pointer -- slot slaves are not assigned to any process; + when convert from slot slave to free task slave, check what should do about num (live slaves + live tasks) inside VSs's task stub, and properly update process's count of liveFreeTaskSlaves + //get a new slave to be the slot slave newSlotSlv = readPrivQ( process->freeTaskSlvRecycleQ ); if( newSlotSlv == NULL ) @@ -797,7 +831,7 @@ //set slave values to make it the slot slave newSlotSlv->metaTask = NULL; newSlotSlv->typeOfVP = SlotTaskSlv; - newSlotSlv->needsTaskAssigned = TRUE; +// newSlotSlv->needsTaskAssigned = TRUE; //a slot slave is pinned to a particular slot on a particular core //Note, this happens before the request is seen by handler, so nothing @@ -813,7 +847,7 @@ //Fix up requester, to be an extra slave now (but not an ended one) // because it's active, doesn't go into freeTaskSlvRecycleQ requestingSlv->typeOfVP = FreeTaskSlv; - check_if_need_to_change_metaTask_type_or_something; + requestingSlv->metaTask->taskType = FreeTask; } @@ -841,30 +875,33 @@ inline SlaveVP * assignWork( PRProcess *process, AnimSlot *slot ) { SlaveVP *returnSlv; - //VSsSemEnv *semEnv; - //VSsSemData *semData; int32 coreNum, slotNum; - PRMetaTask *newMetaTask, *assignedMetaTask; - SlaveVP *freeTaskSlv; + PRMetaTask *assignedMetaTask; coreNum = slot->coreSlotIsOn; - if( _PRTopEnv->overrideAssigner != NULL ) - { assignedMetaTask = (*_PRTopEnv->overrideAssigner)( process, slot ); + if( process->overrideAssigner != NULL ) + { assignedMetaTask = (*process->overrideAssigner)( process, slot ); if( assignedMetaTask != NULL ) { //have work, so reset Done flag (caused by work generated on other core) - if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf - process->coreIsDone[coreNum] = FALSE; //don't just write always +// if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf +// process->coreIsDone[coreNum] = FALSE; //don't just write always - switch( assignedMetaTask->taskType ) - { case GenericSlave: goto AssignSlave; - case SuspendedTask: goto AssignSlave; - case AtomicTask: goto AssignNewTask; - default: PR_int__throw_exception( "unknown task type ret by assigner" ); - } +// switch( assignedMetaTask->taskType ) +// { case GenericSlave: goto AssignSlave; +// case FreeTask: goto AssignSlave; +// case SlotTask: goto AssignNewTask; +// default: PR_int__throw_exception( "unknown task type ret by assigner" ); +// } + //If meta task has a slave attached, then goto assign slave, + // else it's a new task, so goto where assign it to a slot slave + if( assignedMetaTask->slaveAssignedTo != NULL ) + goto AssignSlave; + else + goto AssignNewTask; } - else + else //metaTask is NULL, so no work.. goto NoWork; } @@ -872,56 +909,60 @@ int32 envIdx, numEnvs; PRSemEnv **semEnvs, *semEnv; SlaveAssigner assigner; semEnvs = process->semEnvs; numEnvs = process->numSemEnvs; - for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep semEnvs in hash AND array + for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep semEnvs in hash & array { semEnv = semEnvs[envIdx]; if( semEnv->hasWork ) { assigner = semEnv->slaveAssigner; assignedMetaTask = (*assigner)( semEnv, slot ); //have work, so reset Done flag (caused by work generated on other core) - if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf - process->coreIsDone[coreNum] = FALSE; //don't just write always +// if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf +// process->coreIsDone[coreNum] = FALSE; //don't just write always - switch( assignedMetaTask->taskType ) - { case GenericSlave: goto AssignSlave; - case SuspendedTask: goto AssignSlave; - case AtomicTask: goto AssignNewTask; - default: PR_int__throw_exception( "unknown task type ret by assigner" ); - } +// switch( assignedMetaTask->taskType ) +// { case GenericSlave: goto AssignSlave; +// case FreeTask: goto AssignSlave; +// case SlotTask: goto AssignNewTask; +// default: PR_int__throw_exception( "unknown task type ret by assigner" ); +// } + //If meta task has a slave attached, then goto assign slave, + // else it's a new task, so goto where assign it to a slot slave + if( assignedMetaTask->slaveAssignedTo != NULL ) + goto AssignSlave; + else + goto AssignNewTask; } } + //If reach here, then have searched all semEnv's & none have work.. NoWork: //No work, if reach here.. { goto ReturnTheSlv; } - AssignSlave: //Have a metaTask attached to a slave, so get the slave out - { //get slave pointed to by meta task. - returnSlv = assignedMetaTask->slaveAssignedTo; - + AssignSlave: //Have a metaTask attached to a slave, so get the slave & ret it + { returnSlv = assignedMetaTask->slaveAssignedTo; returnSlv->coreAnimatedBy = coreNum; goto ReturnTheSlv; } - AssignNewTask: + AssignNewTask: //Have a new metaTask that has no slave yet.. assign to slot slv { //get the slot slave to assign the task to.. - coreNum = slot->coreSlotIsOn; slotNum = slot->slotIdx; returnSlv = process->slotTaskSlvs[coreNum][slotNum]; - //point slave to task's function, and mark slave as having task + //point slave to task's function PR_int__reset_slaveVP_to_TopLvlFn( returnSlv, assignedMetaTask->topLevelFn, assignedMetaTask->initData ); - returnSlv->metaTask = assignedMetaTask; + returnSlv->metaTask = assignedMetaTask; assignedMetaTask->slaveAssignedTo = returnSlv; - returnSlv->needsTaskAssigned = FALSE; //slot slave is a "Task" slave type +// returnSlv->needsTaskAssigned = FALSE; //slot slave is a "Task" slave type //have work, so reset Done flag, if was set - if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf - process->coreIsDone[coreNum] = FALSE; //don't just write always +// if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf +// process->coreIsDone[coreNum] = FALSE; //don't just write always goto ReturnTheSlv; } @@ -1005,12 +1046,12 @@ process->numLiveGenericSlvs += 1; metaTask = PR_int__create_slave_meta_task(); metaTask->taskID = req->ID; - metaTask->taskType = GenericSlave; +// metaTask->taskType = GenericSlave; - (*req->handler)(newSlv); + (*req->handler)( req->semReq, newSlv, requestingSlv, semEnv ); } -/*The dissipate handler has to update the number of slaves of the type, within +/*The dissipate handler has to, sdate the number of slaves of the type, within * the process, and call the langlet handler linked into the request, * and after that returns, then call the PR function that frees the slave state * (or recycles the slave). @@ -1027,52 +1068,53 @@ process = slave->processSlaveIsIn; //do the language's dissipate handler - semEnv = PR_int__give_sem_env_for( slave, slave->request->langMagicNumber ); - (*slave->request->handler)( slave, semEnv ); + semEnv = PR_int__give_sem_env_for_slave( slave, slave->request->langMagicNumber ); + (*slave->request->handler)( slave->request->semReq, slave, semEnv ); process->numLiveGenericSlvs -= 1; - PR_int__dissipate_slaveVP_multilang( slave ); //recycles and resets semDatas - + PR_int__recycle_slave_multilang( requestingSlv ); + //check End Of Process Condition if( process->numLiveTasks == 0 && process->numLiveGenericSlvs == 0 ) - signalEndOfProcess; + PR_SS__shutdown_process( process ); } /*Create task is a special form, that has PR behavior in addition to plugin - * behavior. Master calls this first, and this in turn calls the plugin's + * behavior. Master calls this first, and then calls the plugin's * create task handler. + * + *Note: the requesting slave must be either generic slave or free task slave */ -inline void -PRHandle_CreateTask( TopLevelFn topLevelFn, void *initData, PRReqst *req, - SlaveVP *requestingSlv ) - { PRMetaTask *metaTask; - PRProcess *process; - void *semEnv, _langMetaTask; +inline PRMetaTask * +PRHandle_CreateTask( PRReqst *req, SlaveVP *requestingSlv ) + { PRMetaTask *metaTask; + PRProcess *process; PRLangMetaTask *langMetaTask; - + PRSemEnv *semanticEnv; + process = requestingSlv->processSlaveIsIn; - metaTask = PR_int__create_meta_task( req ); - metaTask->taskID = req->ID; //may be NULL - metaTask->topLevelFn = topLevelFn; - metaTask->initData = initData; + metaTask = PR_int__create_meta_task( req ); + metaTask->taskID = req->ID; //may be NULL + metaTask->topLevelFn = req->topLevelFn; + metaTask->initData = req->initData; process->numLiveTasks += 1; - - //plugin tracks tasks ready, and has its own assigner, so task doesn't - // come back from lang's handler -- it's consumed and stays in semEnv. - //But handler gives back the language-specific meta-task it creates, and - // then hook that into the PR meta-task - //(Could also do PRMetaTask as a prolog -- make a Fn that takes the size - // of the lang's metaTask, and alloc's that plus the prolog and returns - // ptr to position just above the prolog) - semEnv = PR_int__give_semEnv_of_req( req, requestingSlv ); //magic num in req - _langMetaTask = (*requestingSlv->request->handler)(req, semEnv); - langMetaTask = (PRLangMetaTask *)_langMetaTask; + + semanticEnv = PR_int__give_sem_env_for_slave( slave, + req->langMagicNumber ); + + //Do the langlet's create-task handler, which keeps the task + // inside the langlet's sem env, but returns the langMetaTask + // so PR can hook it to the PRMetaTask. + //(Could also do PRMetaTask as a prolog -- make a Fn that takes the size + // of the lang's metaTask, and alloc's that plus the prolog and returns + // ptr to position just above the prolog) + langMetaTask = (*req->handler)(req->semReq, slave, semanticEnv); metaTask->langMetaTask = langMetaTask; langMetaTask->protoMetaTask = metaTask; - + return; } @@ -1087,36 +1129,43 @@ * decrement the live task count and check end condition. * *PR has to update count of live tasks, and check end of process condition. - * There are constructs that wait for a process to end, so when end detected, - * have to resume what's waiting.. - *Thing is, the wait is used in "main", so it's an OS thread. That means + * The "main" can invoke constructs that wait for a process to end, so when + * end detected, have to resume what's waiting.. + *Thing is, that wait involves the main OS thread. That means * PR internals have to do OS thread signaling. Want to do that in the - * core controller, which has the original stack of an OS thread. + * core controller, which has the original stack of an OS thread. So the + * end process handling happens in the core controller. * *So here, when detect process end, signal to the core controller, which will - * then do the condition variable notify to the OS thread that's waiting. + * then do the condition variable notify to the OS thread that's waiting. + * + *Note: slave may be either a slot slave or a free task slave. */ inline void PRHandle_EndTask( SlaveVP *requestingSlv ) - { void *semEnv; - PRReqst *req; - PRMetaTask *metaTask; + { void *semEnv; + PRReqst *req; + PRLangMetaTask *langMetaTask; PRProcess *process; - + req = requestingSlv->request; - semEnv = PR_int__give_semEnv_of_req( req, requestingSlv ); //magic num in req - metaTask = req->metaTask; - //Want to keep PRMetaTask hidden from plugin, so extract semReq.. - (*req->handler)( metaTask, req->semReq, semEnv ); + semEnv = PR_int__give_sem_env_of_req( req, requestingSlv ); //magic num in req + langMetaTask = requestingSlv->metaTask->langMetaTask; - recycleFreeTaskSlave( requestingSlv ); + //Do the langlet's request handler + //Want to keep PR structs hidden from plugin, so extract semReq.. + (*req->handler)( langMetaTask, req->semReq, semEnv ); + + //Now that the langlet's done with it, recycle the slave if it's a freeTaskSlv + if( requestingSlv->typeOfVP == FreeTaskSlv ) + PR_int__recycle_slave_multilang( requestingSlv ); process->numLiveTasks -= 1; //check End Of Process Condition if( process->numLiveTasks == 0 && process->numLiveGenericSlvs == 0 ) - signalEndOfProcessToCoreCtlr; + //Tell the core controller to do wakeup of any waiting OS thread + PR_SS__shutdown_process( process ); } - \ No newline at end of file diff -r a5fa1e087c7e -r 608833ae2c5d CoreController.c --- a/CoreController.c Thu Oct 25 23:35:36 2012 -0700 +++ b/CoreController.c Sun Nov 04 18:39:28 2012 -0800 @@ -94,11 +94,11 @@ //Assembly that saves addr of label of return instr -- label in assmbly recordCoreCtlrReturnLabelAddr((void**)&(_PRTopEnv->coreCtlrReturnPt)); - animSlots = _PRTopEnv->allAnimSlots[thisCoresIdx]; + animSlots = _PRTopEnv->allAnimSlots[ thisCoresIdx ]; currSlotIdx = 0; //start at slot 0, go up until one empty, then do master numRepetitionsWithNoWork = 0; addrOfMasterLock = &(_PRTopEnv->masterLock); - thisCoresMasterVP = _PRTopEnv->masterVPs[thisCoresIdx]; + thisCoresMasterVP = _PRTopEnv->masterVPs[ thisCoresIdx ]; //==================== pthread related stuff ====================== //pin the pthread to the core -- takes away Linux control @@ -136,22 +136,23 @@ //Alternatively, the VP suspend primitive could just not bother // returning from switchToSlv, and instead jmp directly to here. - if( currSlotIdx >= NUM_ANIM_SLOTS ) goto switchToMaster; + if( currSlotIdx >= NUM_ANIM_SLOTS ) goto SwitchToMaster; currSlot = animSlots[ currSlotIdx ]; - if( ! currSlot->needsSlaveAssigned ) //slot does have slave assigned - { if(currSlot->slaveAssignedToSlot->typeOfVP == Idle){ - numRepetitionsWithNoWork ++; - } else { - numRepetitionsWithNoWork = 0; //reset back2back master count - } + if( ! currSlot->needsWorkAssigned ) //slot does have slave assigned + { if(currSlot->slaveAssignedToSlot->typeOfVP == Idle) + { numRepetitionsWithNoWork ++; + } + else + { numRepetitionsWithNoWork = 0; //reset back2back master count + } currSlotIdx ++; currVP = currSlot->slaveAssignedToSlot; HOLISTIC__Record_last_work; } else //slot is empty, so switch to master { - switchToMaster: + SwitchToMaster: currSlotIdx = 0; //doing switch to master, so start over at slot 0 currVP = NULL; @@ -193,9 +194,9 @@ doBackoff_for_TooLongToGetLock( numTriesToGetLock, &seed1, &seed2 ); if( numTriesToGetLock > MASTERLOCK_RETRIES_BEFORE_YIELD ) { numTriesToGetLock = 0; pthread_yield(); } - } + } //while( currVP == NULL ) MEAS__Capture_Post_Master_Lock_Point; - } + } //else HOLISTIC__Record_Work_start; diff -r a5fa1e087c7e -r 608833ae2c5d PR.h --- a/PR.h Thu Oct 25 23:35:36 2012 -0700 +++ b/PR.h Sun Nov 04 18:39:28 2012 -0800 @@ -78,7 +78,6 @@ void *semReq; PRProcess *processReqIsIn; int32 langMagicNumber; - PRMetaTask *metaTask; TopLevelFn topLevelFn; void *initData; int32 *ID; @@ -121,7 +120,7 @@ struct _AnimSlot { int workIsDone; - int needsSlaveAssigned; + int needsWorkAssigned; SlaveVP *slaveAssignedToSlot; int slotIdx; //needed by Holistic Model's data gathering @@ -171,7 +170,7 @@ void *semanticData; //Lang saves lang-specific things in slave here //Task related stuff - bool needsTaskAssigned; +// bool needsTaskAssigned; //=========== MEASUREMENT STUFF ========== MEAS__Insert_Meas_Fields_into_Slave; @@ -285,8 +284,8 @@ enum PRTaskType { GenericSlave = 1, - AtomicTask, - SuspendedTask + SlotTask, + FreeTask }; struct _PRMetaTask @@ -318,6 +317,13 @@ void (*freeFn)(void *); } PRSemDataTemplate; + +typedef struct + { + void (*recycler)(void *); + void *langSemData; + } +PRSemData; typedef struct { PRSemDataTemplate **semDatas; @@ -342,12 +348,14 @@ int32 numLiveTasks; // bool32 coreIsDone[NUM_CORES][CACHE_LINE_SZ]; //Fixes false sharing - PrivQ *freeTaskSlvRecycleQ; + PrivQueueStruc *freeTaskSlvRecycleQ; SlaveVP slotTaskSlvs[NUM_CORES][NUM_ANIM_SLOTS]; void *resultToReturn; SlaveVP *seedSlv; + SlaveAssigner overrideAssigner; + //These are used to coord with OS thread waiting for process to end bool32 executionIsComplete; pthread_mutex_t doneLock; diff -r a5fa1e087c7e -r 608833ae2c5d PR__SS.c --- a/PR__SS.c Thu Oct 25 23:35:36 2012 -0700 +++ b/PR__SS.c Sun Nov 04 18:39:28 2012 -0800 @@ -223,6 +223,8 @@ } + + /*TODO: finish implementing *This function returns information about the version of PR, the language * the program is being run in, its version, and information on the @@ -230,7 +232,7 @@ */ /* char * -PR_App__give_environment_string() +PRServ___give_environment_string() { //-------------------------- fprintf(output, "#\n# >> Build information <<\n"); @@ -267,7 +269,12 @@ //-------------------------- } */ - + +void +PR_SS__shutdown_process( PRProcess *process ) + { + removes from queue of processes, and calls shutdown on each langlet started in it (which frees any langlet-alloc'd data in semEnv & semEnv itself).. then frees the process struct (which frees the proto-semEnv's in array).. then writes a done flag (in TopEnv?) and signals the condition var that any OS threads might be waiting on (the wait-for-process-to-end call); + } /*A pointer to the startup-function for the language is given as the last * argument to the call. Use this to initialize a program in the language. @@ -377,14 +384,14 @@ semEnv->numLiveThreadSlvs = 1; //must be last, counts the seed semEnv->shutdownInitiated = FALSE; - semEnv->coreIsDone = PR_int__malloc( NUM_CORES * sizeof( bool32 ) ); +// semEnv->coreIsDone = PR_int__malloc( NUM_CORES * sizeof( bool32 ) ); //For each animation slot, there is an idle slave, and an initial // slave assigned as the current-task-slave. Create them here. int32 coreNum, slotNum; SlaveVP *idleSlv, *slotTaskSlv; for( coreNum = 0; coreNum < NUM_CORES; coreNum++ ) - { semEnv->coreIsDone[coreNum] = FALSE; //use during shutdown + { //semEnv->coreIsDone[coreNum] = FALSE; //use during shutdown for( slotNum = 0; slotNum < NUM_ANIM_SLOTS; ++slotNum ) { idleSlv = PR__create_slave_helper( &idle_fn, NULL, semEnv, 0); @@ -398,7 +405,7 @@ slotTaskSlv->animSlotAssignedTo = _PRTopEnv->allAnimSlots[coreNum][slotNum]; - slotTaskSlv->needsTaskAssigned = TRUE; +// slotTaskSlv->needsTaskAssigned = TRUE; slotTaskSlv->slaveType = SlotTaskSlv; _PRTopEnv->slotTaskSlvs[coreNum][slotNum] = slotTaskSlv; } @@ -459,14 +466,13 @@ //Set state to mean "handling requests done, slot needs filling" animSlots[i]->workIsDone = FALSE; - animSlots[i]->needsSlaveAssigned = TRUE; + animSlots[i]->needsWorkAssigned = TRUE; animSlots[i]->slotIdx = i; //quick retrieval of slot pos animSlots[i]->coreSlotIsOn = coreSlotsAreOn; } return animSlots; } - void freeAnimSlots( AnimSlot **animSlots ) { int i; @@ -610,7 +616,7 @@ // shut down slave into first animulng slot. animSlots = _PRTopEnv->allAnimSlots[ coreIdx ]; animSlots[0]->slaveAssignedToSlot = shutDownSlv; - animSlots[0]->needsSlaveAssigned = FALSE; + animSlots[0]->needsWorkAssigned = FALSE; shutDownSlv->coreAnimatedBy = coreIdx; shutDownSlv->animSlotAssignedTo = animSlots[ 0 ]; } diff -r a5fa1e087c7e -r 608833ae2c5d PR__int.c --- a/PR__int.c Thu Oct 25 23:35:36 2012 -0700 +++ b/PR__int.c Sun Nov 04 18:39:28 2012 -0800 @@ -35,7 +35,7 @@ process->numLiveGenericSlvs += 1; - newSlv->needsTaskAssigned = TRUE; +// newSlv->needsTaskAssigned = TRUE; newSlv->metaTask = NULL; newSlv->typeOfVP = GenericSlave; @@ -109,6 +109,35 @@ return newStub; } +/*This calls recycle handler registered for each langlet's sem data and meta + * task. It also recycles the slave struct. + * + *This assumes that each slave has an array of + */ +void +PR_int__recycle_slave_multilang( SlaveVP *slave ) + { int32 semDataIdx, numSemDatas; + PRSemDataHolder *semDataHolder; + PRSemData *protoSemData, **semDatas; + + semDataHolder = (PRSemDataHolder *)slave->semanticData; + semDatas = semDataHolder->semDatasIter; + + for( semDataIdx = 0; semDataIdx < numSemDatas; semDataIdx++ ) + { protoSemData = semDatas[ semDataIdx ]; + //instead of looking up the semEnv, just put ptr to recycler in protoSemData + //To get by without, must iter through hash table.. + (*protoSemData->recycler)(protoSemData->langSemData); + } + for( metaTaskIdx = 0; metaTaskIdx < numMetaTasks; metaTaskIdx++ ) + { protoMetaTask = metaTasks[ metaTaskIdx ]; + //instead of looking up the semEnv, just put ptr to recycler in protoSemData + (*protoMetaTask->recycler)(protoMetaTask->langMetaTask); + } + + writePrivQ( slave, slave->processSlaveIsIn->freeTaskSlvRecycleQ ); + } + /* This is for OS requests and PR infrastructure requests, such as to create * a probe -- a probe is inside the heart of PR-core, it's not part of any @@ -244,7 +273,7 @@ inline void * -PR_int__give_semEnv_of_req( PRReqst *req, SlaveVP *requestingSlv ) +PR_int__give_sem_env_of_req( PRReqst *req, SlaveVP *requestingSlv ) { return PR_int__give_sem_env_for_process( requestingSlv->processSlaveIsIn, req->langMagicNumber );