Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
changeset 267:608833ae2c5d Dev_ML
Checkpoint -- about to clean up AnimationMaster, deleting a bunch of stuff
| author | Sean Halle <seanhalle@yahoo.com> |
|---|---|
| date | Sun, 04 Nov 2012 18:39:28 -0800 |
| parents | a5fa1e087c7e |
| children | e5bd470b562b |
| files | AnimationMaster.c CoreController.c PR.h PR__SS.c PR__int.c |
| diffstat | 5 files changed, 300 insertions(+), 207 deletions(-) [+] |
line diff
1.1 --- a/AnimationMaster.c Thu Oct 25 23:35:36 2012 -0700 1.2 +++ b/AnimationMaster.c Sun Nov 04 18:39:28 2012 -0800 1.3 @@ -13,7 +13,7 @@ 1.4 #include "VSs_impl/VSs.h" 1.5 1.6 inline void 1.7 -replaceWithNewSlotSlv( SlaveVP *requestingSlv, PRProcessEnv *processEnv ); 1.8 +replaceWithNewSlotSlv( SlaveVP *slave ); 1.9 1.10 1.11 /*The animationMaster embodies most of the animator of the language. The 1.12 @@ -189,13 +189,13 @@ 1.13 if( currSlot->workIsDone ) 1.14 { 1.15 currSlot->workIsDone = FALSE; 1.16 - currSlot->needsSlaveAssigned = TRUE; 1.17 + currSlot->needsWorkAssigned = TRUE; 1.18 1.19 HOLISTIC__Record_AppResponder_start; 1.20 MEAS__startReqHdlr; 1.21 1.22 currSlot->workIsDone = FALSE; 1.23 - currSlot->needsSlaveAssigned = TRUE; 1.24 + currSlot->needsWorkAssigned = TRUE; 1.25 SlaveVP *currSlave = currSlot->slaveAssignedToSlot; 1.26 1.27 justAddedReqHdlrChg(); 1.28 @@ -223,7 +223,7 @@ 1.29 MEAS__endReqHdlr; 1.30 } 1.31 //If slot empty, hand to Assigner to fill with a slave 1.32 - if( currSlot->needsSlaveAssigned ) 1.33 + if( currSlot->needsWorkAssigned ) 1.34 { //Call plugin's Assigner to give slot a new slave 1.35 HOLISTIC__Record_Assigner_start; 1.36 assignedSlaveVP = 1.37 @@ -233,7 +233,7 @@ 1.38 if( assignedSlaveVP != NULL ) 1.39 { currSlot->slaveAssignedToSlot = assignedSlaveVP; 1.40 assignedSlaveVP->animSlotAssignedTo = currSlot; 1.41 - currSlot->needsSlaveAssigned = FALSE; 1.42 + currSlot->needsWorkAssigned = FALSE; 1.43 numSlotsFilled += 1; 1.44 1.45 HOLISTIC__Record_Assigner_end; 1.46 @@ -270,7 +270,6 @@ 1.47 //#ifdef MODE__MULTI_LANG 1.48 SlaveVP *slave; 1.49 PRProcess *process; 1.50 - PRConstrEnvHolder *constrEnvHolder; 1.51 int32 langMagicNumber; 1.52 //#endif 1.53 1.54 @@ -318,15 +317,15 @@ 1.55 slave = currSlot->slaveAssignedToSlot; 1.56 1.57 //check if the completed work was a task.. 1.58 - if( slave->taskMetaInfo->isATask ) 1.59 + if( slave->metaTask->isATask ) 1.60 { 1.61 - if( slave->reqst->type == TaskEnd ) 1.62 + if( slave->request->type == TaskEnd ) 1.63 { //do task end handler, which is registered separately 1.64 //note, end hdlr may use semantic data from reqst.. 1.65 //#ifdef MODE__MULTI_LANG 1.66 //get end-task handler 1.67 //taskEndHandler = lookup( slave->reqst->langMagicNumber, processEnv ); 1.68 - taskEndHandler = slave->taskMetaInfo->endTaskHandler; 1.69 + taskEndHandler = slave->metaTask->endTaskHandler; 1.70 //#endif 1.71 (*taskEndHandler)( slave, semanticEnv ); 1.72 1.73 @@ -353,7 +352,7 @@ 1.74 } //if has suspended slave that needs handling 1.75 1.76 //if slot empty, hand to Assigner to fill with a slave 1.77 - if( currSlot->needsSlaveAssigned ) 1.78 + if( currSlot->needsWorkAssigned ) 1.79 { //Call plugin's Assigner to give slot a new slave 1.80 HOLISTIC__Record_Assigner_start; 1.81 1.82 @@ -365,12 +364,12 @@ 1.83 if( assignedSlaveVP != NULL ) 1.84 { currSlot->slaveAssignedToSlot = assignedSlaveVP; 1.85 assignedSlaveVP->animSlotAssignedTo = currSlot; 1.86 - currSlot->needsSlaveAssigned = FALSE; 1.87 + currSlot->needsWorkAssigned = FALSE; 1.88 numSlotsFilled += 1; 1.89 } 1.90 else 1.91 { 1.92 - currSlot->needsSlaveAssigned = TRUE; //local write 1.93 + currSlot->needsWorkAssigned = TRUE; //local write 1.94 } 1.95 HOLISTIC__Record_Assigner_end; 1.96 }//if slot needs slave assigned 1.97 @@ -496,7 +495,6 @@ 1.98 //#ifdef MODE__MULTI_LANG 1.99 SlaveVP *slave; 1.100 PRProcess *process; 1.101 - PRConstrEnvHolder *constrEnvHolder; 1.102 int32 langMagicNumber; 1.103 //#endif 1.104 1.105 @@ -579,7 +577,7 @@ 1.106 } //if has suspended slave that needs handling 1.107 1.108 //if slot empty, hand to Assigner to fill with a slave 1.109 - if( currSlot->needsSlaveAssigned ) 1.110 + if( currSlot->needsWorkAssigned ) 1.111 { //Call plugin's Assigner to give slot a new slave 1.112 HOLISTIC__Record_Assigner_start; 1.113 1.114 @@ -591,12 +589,12 @@ 1.115 if( assignedSlaveVP != NULL ) 1.116 { currSlot->slaveAssignedToSlot = assignedSlaveVP; 1.117 assignedSlaveVP->animSlotAssignedTo = currSlot; 1.118 - currSlot->needsSlaveAssigned = FALSE; 1.119 + currSlot->needsWorkAssigned = FALSE; 1.120 numSlotsFilled += 1; 1.121 } 1.122 else 1.123 { 1.124 - currSlot->needsSlaveAssigned = TRUE; //local write 1.125 + currSlot->needsWorkAssigned = TRUE; //local write 1.126 } 1.127 HOLISTIC__Record_Assigner_end; 1.128 }//if slot needs slave assigned 1.129 @@ -618,7 +616,6 @@ 1.130 void animationMaster( void *initData, SlaveVP *masterVP ) 1.131 { 1.132 int32 slotIdx; 1.133 -// int32 numSlotsFilled; 1.134 AnimSlot *currSlot; 1.135 //Used while scanning and filling animation slots 1.136 AnimSlot **animSlots; 1.137 @@ -661,6 +658,77 @@ 1.138 #endif //MODE__MULTI_LANG 1.139 #endif //MODE__MULTI_PROCESS 1.140 1.141 + 1.142 +//This version of the master selects one of three loops, depending upon 1.143 +// whether stand-alone single language (just slaves), or standalone with 1.144 +// tasks, or multi-lang (implies multi-process) 1.145 +void animationMaster( void *initData, SlaveVP *masterVP ) 1.146 + { 1.147 + int32 slotIdx; 1.148 + AnimSlot *currSlot; 1.149 + //Used while scanning and filling animation slots 1.150 + AnimSlot **animSlots; 1.151 + 1.152 + //Local copies, for performance 1.153 + MasterEnv *masterEnv; 1.154 + int32 thisCoresIdx; 1.155 + 1.156 + //======================== Initializations ======================== 1.157 + masterEnv = (MasterEnv*)_PRTopEnv; 1.158 + 1.159 + thisCoresIdx = masterVP->coreAnimatedBy; 1.160 + animSlots = masterEnv->allAnimSlots[thisCoresIdx]; 1.161 + 1.162 + HOLISTIC__Insert_Master_Global_Vars; 1.163 + 1.164 + //======================== animationMaster ======================== 1.165 + //Have three different modes, and the master behavior is different for 1.166 + // each, so jump to the loop that corresponds to the mode. 1.167 + // 1.168 + switch(mode) 1.169 + { case StandaloneSlavesOnly: 1.170 + while(1) 1.171 + { MEAS__Capture_Pre_Master_Point 1.172 + for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) 1.173 + { 1.174 + currSlot = animSlots[ slotIdx ]; 1.175 + 1.176 + masterFunction_StandaloneSlavesOnly( currSlot ); 1.177 + } 1.178 + MEAS__Capture_Post_Master_Point; 1.179 + masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master 1.180 + flushRegisters(); 1.181 + } 1.182 + case StandaloneWTasks: 1.183 + while(1) 1.184 + { MEAS__Capture_Pre_Master_Point 1.185 + for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) 1.186 + { 1.187 + currSlot = animSlots[ slotIdx ]; 1.188 + 1.189 + masterFunction_StandaloneWTasks( currSlot ); 1.190 + } 1.191 + MEAS__Capture_Post_Master_Point; 1.192 + masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master 1.193 + flushRegisters(); 1.194 + } 1.195 + case MultiLang: 1.196 + while(1) 1.197 + { MEAS__Capture_Pre_Master_Point 1.198 + for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) 1.199 + { 1.200 + currSlot = animSlots[ slotIdx ]; 1.201 + 1.202 + masterFunction_multiLang( currSlot ); 1.203 + } 1.204 + MEAS__Capture_Post_Master_Point; 1.205 + masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master 1.206 + flushRegisters(); 1.207 + } 1.208 + } 1.209 + } 1.210 + 1.211 + 1.212 inline 1.213 void 1.214 masterFunction_multiLang( AnimSlot *currSlot ) 1.215 @@ -675,6 +743,7 @@ 1.216 //Check if newly-done slave in slot, which will need request handled 1.217 if( currSlot->workIsDone ) 1.218 { currSlot->workIsDone = FALSE; 1.219 + currSlot->needsWorkAssigned = TRUE; 1.220 1.221 HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot 1.222 MEAS__startReqHdlr; 1.223 @@ -682,94 +751,56 @@ 1.224 1.225 //process the request made by the slave (held inside slave struc) 1.226 slave = currSlot->slaveAssignedToSlot; 1.227 - 1.228 - //check if the slave was doing a task.. 1.229 - //Action depends on both on the request type, and whether it's on 1.230 - // a generic slave vs a suspended task 1.231 - if( slave->metaTask->taskType == AtomicTask || 1.232 - slave->metaTask->taskType == SuspendedTask ) 1.233 - { 1.234 - switch( slave->request->reqType ) 1.235 - { case TaskEnd: 1.236 - { PRHandle_EndTask( slave ); //if free task slave, update count, put into recycle Q -- do handler before lang's handler 1.237 + req = slave->request; 1.238 1.239 - //do task end handler, which is registered separately 1.240 - //note, end hdlr may use semantic data from reqst.. 1.241 - //get end-task handler 1.242 + //If the requesting slave is a slot slave, and request is not 1.243 + // task-end, then turn it into a free task slave. 1.244 + if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd ) 1.245 + replaceWithNewSlotSlv( slave ); 1.246 1.247 - RequestHandler 1.248 - taskEndHandler = slave->request->handler; 1.249 - semanticEnv = PR_int__give_sem_env_for_slave( slave, 1.250 - slave->request->langMagicNumber ); 1.251 - (*taskEndHandler)( slave, semanticEnv ); 1.252 + //Handle task create and end first -- they're special cases.. 1.253 + switch( req->reqType ) 1.254 + { case TaskEnd: 1.255 + { //do PR handler, which calls lang's hdlr and does recycle of 1.256 + // free task slave if needed -- PR handler checks for free task Slv 1.257 + PRHandle_EndTask( slave ); break; 1.258 + } 1.259 + case TaskCreate: 1.260 + { //Do PR's create-task handler, which calls the lang's hdlr 1.261 + // PR handler checks for free task Slv 1.262 + PRHandle_CreateTask( slave ); break; 1.263 + } 1.264 + case SlvCreate: PRHandle_CreateSlave( slave ); break; 1.265 + case SlvDissipate: PRHandle_Dissipate( slave ); break; 1.266 + case Service: PR_int__handle_PRServiceReq( slave ); break; //resume into PR's own semantic env 1.267 + case Hardware: //for future expansion 1.268 + case IO: //for future expansion 1.269 + case OSCall: //for future expansion 1.270 + PR_int__throw_exception("Not implemented"); break; 1.271 + case Language: //normal sem request 1.272 + magicNumber = req->langMagicNumber; 1.273 + semanticEnv = PR_PI__give_sem_env_for( slave, magicNumber ); 1.274 + requestHandler = semanticEnv->requestHdlr; 1.275 + (*requestHandler)( req->semReq, slave, semanticEnv ); 1.276 + } 1.277 1.278 - goto AssignWork; 1.279 - } 1.280 - case TaskCreate: 1.281 - { PRHandle_CreateTask( slave ); 1.282 - RequestHandler 1.283 - taskCreateHandler = slave->request->handler; 1.284 - semanticEnv = PR_int__give_sem_env_for_slave( slave, 1.285 - slave->request->langMagicNumber ); 1.286 - (*taskCreateHandler)( slave, semanticEnv ); //resumes creating slave 1.287 - goto AssignWork; 1.288 - } 1.289 - default: 1.290 - { //is a task, and just suspended, so tied to a free task slave 1.291 - //First turn slot slave into free task slave & make replacement 1.292 - if( slave->typeOfVP == SlotTaskSlv ) 1.293 - replaceWithNewSlotSlv( slave, slave->processSlaveIsIn->processEnv ); 1.294 - 1.295 - //goto normal slave request handling 1.296 - goto SlaveReqHandling; 1.297 - } 1.298 - } 1.299 - } 1.300 - else //is a slave that suspended 1.301 - { 1.302 - 1.303 - SlaveReqHandling: 1.304 - //Q: put the switch in inline call, to clean up code? 1.305 - req = slave->request; 1.306 - switch( req->reqType ) 1.307 - { case SlvCreate: PRHandle_CreateSlave( slave ); break; 1.308 - case SlvDissipate: PRHandle_Dissipate( slave ); break; 1.309 - case Service: PR_int__handle_PRServiceReq( slave ); break; //resume into PR's own semantic env 1.310 - case Hardware: //for future expansion 1.311 - case IO: //for future expansion 1.312 - case OSCall: //for future expansion 1.313 - case Language: //normal sem request 1.314 - magicNumber = slave->request->langMagicNumber; 1.315 - semanticEnv = PR_PI__give_sem_env_for( slave, magicNumber ); 1.316 - requestHandler = semanticEnv->requestHdlr; 1.317 - (*requestHandler)( slave, semanticEnv ); //(note: indirect Fn call more efficient when use fewer params, instead re-fetch from slave) 1.318 - } 1.319 - 1.320 - HOLISTIC__Record_AppResponder_end; 1.321 - MEAS__endReqHdlr; 1.322 - 1.323 - goto AssignWork; 1.324 - } 1.325 - } //if has suspended slave that needs handling 1.326 + HOLISTIC__Record_AppResponder_end; 1.327 + MEAS__endReqHdlr; 1.328 + } //if have request to be handled 1.329 1.330 - //End up here when the slot did not have ended work in it (no req) 1.331 - //So, here, if slot empty, look for work to fill the slot 1.332 - if( currSlot->needsSlaveAssigned ) 1.333 - { HOLISTIC__Record_Assigner_start; 1.334 - 1.335 - AssignWork: 1.336 + if( currSlot->needsWorkAssigned ) 1.337 + { 1.338 + HOLISTIC__Record_Assigner_start; 1.339 + 1.340 //Scan sem environs, looking for semEnv with ready work. 1.341 // call the Assigner for that sem Env, to get a slave for the slot 1.342 assignedSlaveVP = assignWork( semanticEnv, currSlot ); 1.343 1.344 - //put the chosen slave into slot, and adjust flags and state 1.345 + //if work found, put into slot, and adjust flags and state 1.346 if( assignedSlaveVP != NULL ) 1.347 { currSlot->slaveAssignedToSlot = assignedSlaveVP; 1.348 assignedSlaveVP->animSlotAssignedTo = currSlot; 1.349 - currSlot->needsSlaveAssigned = FALSE; 1.350 - } 1.351 - else 1.352 - { currSlot->needsSlaveAssigned = TRUE; //local write 1.353 + currSlot->needsWorkAssigned = FALSE; 1.354 } 1.355 HOLISTIC__Record_Assigner_end; 1.356 }//if slot needs slave assigned 1.357 @@ -786,6 +817,9 @@ 1.358 replaceWithNewSlotSlv( SlaveVP *requestingSlv, PRProcess *process ) 1.359 { SlaveVP *newSlotSlv; 1.360 1.361 + When slot slave converted to a free task slave, insert the process pointer -- slot slaves are not assigned to any process; 1.362 + 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 1.363 + 1.364 //get a new slave to be the slot slave 1.365 newSlotSlv = readPrivQ( process->freeTaskSlvRecycleQ ); 1.366 if( newSlotSlv == NULL ) 1.367 @@ -797,7 +831,7 @@ 1.368 //set slave values to make it the slot slave 1.369 newSlotSlv->metaTask = NULL; 1.370 newSlotSlv->typeOfVP = SlotTaskSlv; 1.371 - newSlotSlv->needsTaskAssigned = TRUE; 1.372 +// newSlotSlv->needsTaskAssigned = TRUE; 1.373 1.374 //a slot slave is pinned to a particular slot on a particular core 1.375 //Note, this happens before the request is seen by handler, so nothing 1.376 @@ -813,7 +847,7 @@ 1.377 //Fix up requester, to be an extra slave now (but not an ended one) 1.378 // because it's active, doesn't go into freeTaskSlvRecycleQ 1.379 requestingSlv->typeOfVP = FreeTaskSlv; 1.380 - check_if_need_to_change_metaTask_type_or_something; 1.381 + requestingSlv->metaTask->taskType = FreeTask; 1.382 } 1.383 1.384 1.385 @@ -841,30 +875,33 @@ 1.386 inline SlaveVP * 1.387 assignWork( PRProcess *process, AnimSlot *slot ) 1.388 { SlaveVP *returnSlv; 1.389 - //VSsSemEnv *semEnv; 1.390 - //VSsSemData *semData; 1.391 int32 coreNum, slotNum; 1.392 - PRMetaTask *newMetaTask, *assignedMetaTask; 1.393 - SlaveVP *freeTaskSlv; 1.394 + PRMetaTask *assignedMetaTask; 1.395 1.396 coreNum = slot->coreSlotIsOn; 1.397 1.398 - if( _PRTopEnv->overrideAssigner != NULL ) 1.399 - { assignedMetaTask = (*_PRTopEnv->overrideAssigner)( process, slot ); 1.400 + if( process->overrideAssigner != NULL ) 1.401 + { assignedMetaTask = (*process->overrideAssigner)( process, slot ); 1.402 if( assignedMetaTask != NULL ) 1.403 { 1.404 //have work, so reset Done flag (caused by work generated on other core) 1.405 - if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf 1.406 - process->coreIsDone[coreNum] = FALSE; //don't just write always 1.407 +// if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf 1.408 +// process->coreIsDone[coreNum] = FALSE; //don't just write always 1.409 1.410 - switch( assignedMetaTask->taskType ) 1.411 - { case GenericSlave: goto AssignSlave; 1.412 - case SuspendedTask: goto AssignSlave; 1.413 - case AtomicTask: goto AssignNewTask; 1.414 - default: PR_int__throw_exception( "unknown task type ret by assigner" ); 1.415 - } 1.416 +// switch( assignedMetaTask->taskType ) 1.417 +// { case GenericSlave: goto AssignSlave; 1.418 +// case FreeTask: goto AssignSlave; 1.419 +// case SlotTask: goto AssignNewTask; 1.420 +// default: PR_int__throw_exception( "unknown task type ret by assigner" ); 1.421 +// } 1.422 + //If meta task has a slave attached, then goto assign slave, 1.423 + // else it's a new task, so goto where assign it to a slot slave 1.424 + if( assignedMetaTask->slaveAssignedTo != NULL ) 1.425 + goto AssignSlave; 1.426 + else 1.427 + goto AssignNewTask; 1.428 } 1.429 - else 1.430 + else //metaTask is NULL, so no work.. 1.431 goto NoWork; 1.432 } 1.433 1.434 @@ -872,56 +909,60 @@ 1.435 int32 envIdx, numEnvs; PRSemEnv **semEnvs, *semEnv; SlaveAssigner assigner; 1.436 semEnvs = process->semEnvs; 1.437 numEnvs = process->numSemEnvs; 1.438 - for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep semEnvs in hash AND array 1.439 + for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep semEnvs in hash & array 1.440 { semEnv = semEnvs[envIdx]; 1.441 if( semEnv->hasWork ) 1.442 { assigner = semEnv->slaveAssigner; 1.443 assignedMetaTask = (*assigner)( semEnv, slot ); 1.444 1.445 //have work, so reset Done flag (caused by work generated on other core) 1.446 - if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf 1.447 - process->coreIsDone[coreNum] = FALSE; //don't just write always 1.448 +// if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf 1.449 +// process->coreIsDone[coreNum] = FALSE; //don't just write always 1.450 1.451 - switch( assignedMetaTask->taskType ) 1.452 - { case GenericSlave: goto AssignSlave; 1.453 - case SuspendedTask: goto AssignSlave; 1.454 - case AtomicTask: goto AssignNewTask; 1.455 - default: PR_int__throw_exception( "unknown task type ret by assigner" ); 1.456 - } 1.457 +// switch( assignedMetaTask->taskType ) 1.458 +// { case GenericSlave: goto AssignSlave; 1.459 +// case FreeTask: goto AssignSlave; 1.460 +// case SlotTask: goto AssignNewTask; 1.461 +// default: PR_int__throw_exception( "unknown task type ret by assigner" ); 1.462 +// } 1.463 + //If meta task has a slave attached, then goto assign slave, 1.464 + // else it's a new task, so goto where assign it to a slot slave 1.465 + if( assignedMetaTask->slaveAssignedTo != NULL ) 1.466 + goto AssignSlave; 1.467 + else 1.468 + goto AssignNewTask; 1.469 } 1.470 } 1.471 + //If reach here, then have searched all semEnv's & none have work.. 1.472 1.473 NoWork: 1.474 //No work, if reach here.. 1.475 { goto ReturnTheSlv; 1.476 } 1.477 1.478 - AssignSlave: //Have a metaTask attached to a slave, so get the slave out 1.479 - { //get slave pointed to by meta task. 1.480 - returnSlv = assignedMetaTask->slaveAssignedTo; 1.481 - 1.482 + AssignSlave: //Have a metaTask attached to a slave, so get the slave & ret it 1.483 + { returnSlv = assignedMetaTask->slaveAssignedTo; 1.484 returnSlv->coreAnimatedBy = coreNum; 1.485 1.486 goto ReturnTheSlv; 1.487 } 1.488 1.489 - AssignNewTask: 1.490 + AssignNewTask: //Have a new metaTask that has no slave yet.. assign to slot slv 1.491 { 1.492 //get the slot slave to assign the task to.. 1.493 - coreNum = slot->coreSlotIsOn; 1.494 slotNum = slot->slotIdx; 1.495 returnSlv = process->slotTaskSlvs[coreNum][slotNum]; 1.496 1.497 - //point slave to task's function, and mark slave as having task 1.498 + //point slave to task's function 1.499 PR_int__reset_slaveVP_to_TopLvlFn( returnSlv, 1.500 assignedMetaTask->topLevelFn, assignedMetaTask->initData ); 1.501 - returnSlv->metaTask = assignedMetaTask; 1.502 + returnSlv->metaTask = assignedMetaTask; 1.503 assignedMetaTask->slaveAssignedTo = returnSlv; 1.504 - returnSlv->needsTaskAssigned = FALSE; //slot slave is a "Task" slave type 1.505 +// returnSlv->needsTaskAssigned = FALSE; //slot slave is a "Task" slave type 1.506 1.507 //have work, so reset Done flag, if was set 1.508 - if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf 1.509 - process->coreIsDone[coreNum] = FALSE; //don't just write always 1.510 +// if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf 1.511 +// process->coreIsDone[coreNum] = FALSE; //don't just write always 1.512 1.513 goto ReturnTheSlv; 1.514 } 1.515 @@ -1005,12 +1046,12 @@ 1.516 process->numLiveGenericSlvs += 1; 1.517 metaTask = PR_int__create_slave_meta_task(); 1.518 metaTask->taskID = req->ID; 1.519 - metaTask->taskType = GenericSlave; 1.520 +// metaTask->taskType = GenericSlave; 1.521 1.522 - (*req->handler)(newSlv); 1.523 + (*req->handler)( req->semReq, newSlv, requestingSlv, semEnv ); 1.524 } 1.525 1.526 -/*The dissipate handler has to update the number of slaves of the type, within 1.527 +/*The dissipate handler has to, sdate the number of slaves of the type, within 1.528 * the process, and call the langlet handler linked into the request, 1.529 * and after that returns, then call the PR function that frees the slave state 1.530 * (or recycles the slave). 1.531 @@ -1027,52 +1068,53 @@ 1.532 process = slave->processSlaveIsIn; 1.533 1.534 //do the language's dissipate handler 1.535 - semEnv = PR_int__give_sem_env_for( slave, slave->request->langMagicNumber ); 1.536 - (*slave->request->handler)( slave, semEnv ); 1.537 + semEnv = PR_int__give_sem_env_for_slave( slave, slave->request->langMagicNumber ); 1.538 + (*slave->request->handler)( slave->request->semReq, slave, semEnv ); 1.539 1.540 process->numLiveGenericSlvs -= 1; 1.541 - PR_int__dissipate_slaveVP_multilang( slave ); //recycles and resets semDatas 1.542 - 1.543 + PR_int__recycle_slave_multilang( requestingSlv ); 1.544 + 1.545 //check End Of Process Condition 1.546 if( process->numLiveTasks == 0 && 1.547 process->numLiveGenericSlvs == 0 ) 1.548 - signalEndOfProcess; 1.549 + PR_SS__shutdown_process( process ); 1.550 } 1.551 1.552 /*Create task is a special form, that has PR behavior in addition to plugin 1.553 - * behavior. Master calls this first, and this in turn calls the plugin's 1.554 + * behavior. Master calls this first, and then calls the plugin's 1.555 * create task handler. 1.556 + * 1.557 + *Note: the requesting slave must be either generic slave or free task slave 1.558 */ 1.559 -inline void 1.560 -PRHandle_CreateTask( TopLevelFn topLevelFn, void *initData, PRReqst *req, 1.561 - SlaveVP *requestingSlv ) 1.562 - { PRMetaTask *metaTask; 1.563 - PRProcess *process; 1.564 - void *semEnv, _langMetaTask; 1.565 +inline PRMetaTask * 1.566 +PRHandle_CreateTask( PRReqst *req, SlaveVP *requestingSlv ) 1.567 + { PRMetaTask *metaTask; 1.568 + PRProcess *process; 1.569 PRLangMetaTask *langMetaTask; 1.570 - 1.571 + PRSemEnv *semanticEnv; 1.572 + 1.573 process = requestingSlv->processSlaveIsIn; 1.574 1.575 - metaTask = PR_int__create_meta_task( req ); 1.576 - metaTask->taskID = req->ID; //may be NULL 1.577 - metaTask->topLevelFn = topLevelFn; 1.578 - metaTask->initData = initData; 1.579 + metaTask = PR_int__create_meta_task( req ); 1.580 + metaTask->taskID = req->ID; //may be NULL 1.581 + metaTask->topLevelFn = req->topLevelFn; 1.582 + metaTask->initData = req->initData; 1.583 1.584 process->numLiveTasks += 1; 1.585 - 1.586 - //plugin tracks tasks ready, and has its own assigner, so task doesn't 1.587 - // come back from lang's handler -- it's consumed and stays in semEnv. 1.588 - //But handler gives back the language-specific meta-task it creates, and 1.589 - // then hook that into the PR meta-task 1.590 - //(Could also do PRMetaTask as a prolog -- make a Fn that takes the size 1.591 - // of the lang's metaTask, and alloc's that plus the prolog and returns 1.592 - // ptr to position just above the prolog) 1.593 - semEnv = PR_int__give_semEnv_of_req( req, requestingSlv ); //magic num in req 1.594 - _langMetaTask = (*requestingSlv->request->handler)(req, semEnv); 1.595 - langMetaTask = (PRLangMetaTask *)_langMetaTask; 1.596 + 1.597 + semanticEnv = PR_int__give_sem_env_for_slave( slave, 1.598 + req->langMagicNumber ); 1.599 + 1.600 + //Do the langlet's create-task handler, which keeps the task 1.601 + // inside the langlet's sem env, but returns the langMetaTask 1.602 + // so PR can hook it to the PRMetaTask. 1.603 + //(Could also do PRMetaTask as a prolog -- make a Fn that takes the size 1.604 + // of the lang's metaTask, and alloc's that plus the prolog and returns 1.605 + // ptr to position just above the prolog) 1.606 + langMetaTask = (*req->handler)(req->semReq, slave, semanticEnv); 1.607 metaTask->langMetaTask = langMetaTask; 1.608 langMetaTask->protoMetaTask = metaTask; 1.609 - 1.610 + 1.611 return; 1.612 } 1.613 1.614 @@ -1087,36 +1129,43 @@ 1.615 * decrement the live task count and check end condition. 1.616 * 1.617 *PR has to update count of live tasks, and check end of process condition. 1.618 - * There are constructs that wait for a process to end, so when end detected, 1.619 - * have to resume what's waiting.. 1.620 - *Thing is, the wait is used in "main", so it's an OS thread. That means 1.621 + * The "main" can invoke constructs that wait for a process to end, so when 1.622 + * end detected, have to resume what's waiting.. 1.623 + *Thing is, that wait involves the main OS thread. That means 1.624 * PR internals have to do OS thread signaling. Want to do that in the 1.625 - * core controller, which has the original stack of an OS thread. 1.626 + * core controller, which has the original stack of an OS thread. So the 1.627 + * end process handling happens in the core controller. 1.628 * 1.629 *So here, when detect process end, signal to the core controller, which will 1.630 - * then do the condition variable notify to the OS thread that's waiting. 1.631 + * then do the condition variable notify to the OS thread that's waiting. 1.632 + * 1.633 + *Note: slave may be either a slot slave or a free task slave. 1.634 */ 1.635 inline void 1.636 PRHandle_EndTask( SlaveVP *requestingSlv ) 1.637 - { void *semEnv; 1.638 - PRReqst *req; 1.639 - PRMetaTask *metaTask; 1.640 + { void *semEnv; 1.641 + PRReqst *req; 1.642 + PRLangMetaTask *langMetaTask; 1.643 PRProcess *process; 1.644 - 1.645 + 1.646 req = requestingSlv->request; 1.647 - semEnv = PR_int__give_semEnv_of_req( req, requestingSlv ); //magic num in req 1.648 - metaTask = req->metaTask; 1.649 - //Want to keep PRMetaTask hidden from plugin, so extract semReq.. 1.650 - (*req->handler)( metaTask, req->semReq, semEnv ); 1.651 + semEnv = PR_int__give_sem_env_of_req( req, requestingSlv ); //magic num in req 1.652 + langMetaTask = requestingSlv->metaTask->langMetaTask; 1.653 1.654 - recycleFreeTaskSlave( requestingSlv ); 1.655 + //Do the langlet's request handler 1.656 + //Want to keep PR structs hidden from plugin, so extract semReq.. 1.657 + (*req->handler)( langMetaTask, req->semReq, semEnv ); 1.658 + 1.659 + //Now that the langlet's done with it, recycle the slave if it's a freeTaskSlv 1.660 + if( requestingSlv->typeOfVP == FreeTaskSlv ) 1.661 + PR_int__recycle_slave_multilang( requestingSlv ); 1.662 1.663 process->numLiveTasks -= 1; 1.664 1.665 //check End Of Process Condition 1.666 if( process->numLiveTasks == 0 && 1.667 process->numLiveGenericSlvs == 0 ) 1.668 - signalEndOfProcessToCoreCtlr; 1.669 + //Tell the core controller to do wakeup of any waiting OS thread 1.670 + PR_SS__shutdown_process( process ); 1.671 } 1.672 1.673 - 1.674 \ No newline at end of file
2.1 --- a/CoreController.c Thu Oct 25 23:35:36 2012 -0700 2.2 +++ b/CoreController.c Sun Nov 04 18:39:28 2012 -0800 2.3 @@ -94,11 +94,11 @@ 2.4 //Assembly that saves addr of label of return instr -- label in assmbly 2.5 recordCoreCtlrReturnLabelAddr((void**)&(_PRTopEnv->coreCtlrReturnPt)); 2.6 2.7 - animSlots = _PRTopEnv->allAnimSlots[thisCoresIdx]; 2.8 + animSlots = _PRTopEnv->allAnimSlots[ thisCoresIdx ]; 2.9 currSlotIdx = 0; //start at slot 0, go up until one empty, then do master 2.10 numRepetitionsWithNoWork = 0; 2.11 addrOfMasterLock = &(_PRTopEnv->masterLock); 2.12 - thisCoresMasterVP = _PRTopEnv->masterVPs[thisCoresIdx]; 2.13 + thisCoresMasterVP = _PRTopEnv->masterVPs[ thisCoresIdx ]; 2.14 2.15 //==================== pthread related stuff ====================== 2.16 //pin the pthread to the core -- takes away Linux control 2.17 @@ -136,22 +136,23 @@ 2.18 //Alternatively, the VP suspend primitive could just not bother 2.19 // returning from switchToSlv, and instead jmp directly to here. 2.20 2.21 - if( currSlotIdx >= NUM_ANIM_SLOTS ) goto switchToMaster; 2.22 + if( currSlotIdx >= NUM_ANIM_SLOTS ) goto SwitchToMaster; 2.23 currSlot = animSlots[ currSlotIdx ]; 2.24 2.25 - if( ! currSlot->needsSlaveAssigned ) //slot does have slave assigned 2.26 - { if(currSlot->slaveAssignedToSlot->typeOfVP == Idle){ 2.27 - numRepetitionsWithNoWork ++; 2.28 - } else { 2.29 - numRepetitionsWithNoWork = 0; //reset back2back master count 2.30 - } 2.31 + if( ! currSlot->needsWorkAssigned ) //slot does have slave assigned 2.32 + { if(currSlot->slaveAssignedToSlot->typeOfVP == Idle) 2.33 + { numRepetitionsWithNoWork ++; 2.34 + } 2.35 + else 2.36 + { numRepetitionsWithNoWork = 0; //reset back2back master count 2.37 + } 2.38 currSlotIdx ++; 2.39 currVP = currSlot->slaveAssignedToSlot; 2.40 HOLISTIC__Record_last_work; 2.41 } 2.42 else //slot is empty, so switch to master 2.43 { 2.44 - switchToMaster: 2.45 + SwitchToMaster: 2.46 currSlotIdx = 0; //doing switch to master, so start over at slot 0 2.47 currVP = NULL; 2.48 2.49 @@ -193,9 +194,9 @@ 2.50 doBackoff_for_TooLongToGetLock( numTriesToGetLock, &seed1, &seed2 ); 2.51 if( numTriesToGetLock > MASTERLOCK_RETRIES_BEFORE_YIELD ) 2.52 { numTriesToGetLock = 0; pthread_yield(); } 2.53 - } 2.54 + } //while( currVP == NULL ) 2.55 MEAS__Capture_Post_Master_Lock_Point; 2.56 - } 2.57 + } //else 2.58 2.59 HOLISTIC__Record_Work_start; 2.60
3.1 --- a/PR.h Thu Oct 25 23:35:36 2012 -0700 3.2 +++ b/PR.h Sun Nov 04 18:39:28 2012 -0800 3.3 @@ -78,7 +78,6 @@ 3.4 void *semReq; 3.5 PRProcess *processReqIsIn; 3.6 int32 langMagicNumber; 3.7 - PRMetaTask *metaTask; 3.8 TopLevelFn topLevelFn; 3.9 void *initData; 3.10 int32 *ID; 3.11 @@ -121,7 +120,7 @@ 3.12 struct _AnimSlot 3.13 { 3.14 int workIsDone; 3.15 - int needsSlaveAssigned; 3.16 + int needsWorkAssigned; 3.17 SlaveVP *slaveAssignedToSlot; 3.18 3.19 int slotIdx; //needed by Holistic Model's data gathering 3.20 @@ -171,7 +170,7 @@ 3.21 void *semanticData; //Lang saves lang-specific things in slave here 3.22 3.23 //Task related stuff 3.24 - bool needsTaskAssigned; 3.25 +// bool needsTaskAssigned; 3.26 3.27 //=========== MEASUREMENT STUFF ========== 3.28 MEAS__Insert_Meas_Fields_into_Slave; 3.29 @@ -285,8 +284,8 @@ 3.30 3.31 enum PRTaskType 3.32 { GenericSlave = 1, 3.33 - AtomicTask, 3.34 - SuspendedTask 3.35 + SlotTask, 3.36 + FreeTask 3.37 }; 3.38 3.39 struct _PRMetaTask 3.40 @@ -318,6 +317,13 @@ 3.41 void (*freeFn)(void *); 3.42 } 3.43 PRSemDataTemplate; 3.44 + 3.45 +typedef struct 3.46 + { 3.47 + void (*recycler)(void *); 3.48 + void *langSemData; 3.49 + } 3.50 +PRSemData; 3.51 3.52 typedef struct 3.53 { PRSemDataTemplate **semDatas; 3.54 @@ -342,12 +348,14 @@ 3.55 int32 numLiveTasks; 3.56 // bool32 coreIsDone[NUM_CORES][CACHE_LINE_SZ]; //Fixes false sharing 3.57 3.58 - PrivQ *freeTaskSlvRecycleQ; 3.59 + PrivQueueStruc *freeTaskSlvRecycleQ; 3.60 SlaveVP slotTaskSlvs[NUM_CORES][NUM_ANIM_SLOTS]; 3.61 void *resultToReturn; 3.62 3.63 SlaveVP *seedSlv; 3.64 3.65 + SlaveAssigner overrideAssigner; 3.66 + 3.67 //These are used to coord with OS thread waiting for process to end 3.68 bool32 executionIsComplete; 3.69 pthread_mutex_t doneLock;
4.1 --- a/PR__SS.c Thu Oct 25 23:35:36 2012 -0700 4.2 +++ b/PR__SS.c Sun Nov 04 18:39:28 2012 -0800 4.3 @@ -223,6 +223,8 @@ 4.4 } 4.5 4.6 4.7 + 4.8 + 4.9 /*TODO: finish implementing 4.10 *This function returns information about the version of PR, the language 4.11 * the program is being run in, its version, and information on the 4.12 @@ -230,7 +232,7 @@ 4.13 */ 4.14 /* 4.15 char * 4.16 -PR_App__give_environment_string() 4.17 +PRServ___give_environment_string() 4.18 { 4.19 //-------------------------- 4.20 fprintf(output, "#\n# >> Build information <<\n"); 4.21 @@ -267,7 +269,12 @@ 4.22 //-------------------------- 4.23 } 4.24 */ 4.25 - 4.26 + 4.27 +void 4.28 +PR_SS__shutdown_process( PRProcess *process ) 4.29 + { 4.30 + 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); 4.31 + } 4.32 4.33 /*A pointer to the startup-function for the language is given as the last 4.34 * argument to the call. Use this to initialize a program in the language. 4.35 @@ -377,14 +384,14 @@ 4.36 semEnv->numLiveThreadSlvs = 1; //must be last, counts the seed 4.37 4.38 semEnv->shutdownInitiated = FALSE; 4.39 - semEnv->coreIsDone = PR_int__malloc( NUM_CORES * sizeof( bool32 ) ); 4.40 +// semEnv->coreIsDone = PR_int__malloc( NUM_CORES * sizeof( bool32 ) ); 4.41 4.42 //For each animation slot, there is an idle slave, and an initial 4.43 // slave assigned as the current-task-slave. Create them here. 4.44 int32 coreNum, slotNum; 4.45 SlaveVP *idleSlv, *slotTaskSlv; 4.46 for( coreNum = 0; coreNum < NUM_CORES; coreNum++ ) 4.47 - { semEnv->coreIsDone[coreNum] = FALSE; //use during shutdown 4.48 + { //semEnv->coreIsDone[coreNum] = FALSE; //use during shutdown 4.49 4.50 for( slotNum = 0; slotNum < NUM_ANIM_SLOTS; ++slotNum ) 4.51 { idleSlv = PR__create_slave_helper( &idle_fn, NULL, semEnv, 0); 4.52 @@ -398,7 +405,7 @@ 4.53 slotTaskSlv->animSlotAssignedTo = 4.54 _PRTopEnv->allAnimSlots[coreNum][slotNum]; 4.55 4.56 - slotTaskSlv->needsTaskAssigned = TRUE; 4.57 +// slotTaskSlv->needsTaskAssigned = TRUE; 4.58 slotTaskSlv->slaveType = SlotTaskSlv; 4.59 _PRTopEnv->slotTaskSlvs[coreNum][slotNum] = slotTaskSlv; 4.60 } 4.61 @@ -459,14 +466,13 @@ 4.62 4.63 //Set state to mean "handling requests done, slot needs filling" 4.64 animSlots[i]->workIsDone = FALSE; 4.65 - animSlots[i]->needsSlaveAssigned = TRUE; 4.66 + animSlots[i]->needsWorkAssigned = TRUE; 4.67 animSlots[i]->slotIdx = i; //quick retrieval of slot pos 4.68 animSlots[i]->coreSlotIsOn = coreSlotsAreOn; 4.69 } 4.70 return animSlots; 4.71 } 4.72 4.73 - 4.74 void 4.75 freeAnimSlots( AnimSlot **animSlots ) 4.76 { int i; 4.77 @@ -610,7 +616,7 @@ 4.78 // shut down slave into first animulng slot. 4.79 animSlots = _PRTopEnv->allAnimSlots[ coreIdx ]; 4.80 animSlots[0]->slaveAssignedToSlot = shutDownSlv; 4.81 - animSlots[0]->needsSlaveAssigned = FALSE; 4.82 + animSlots[0]->needsWorkAssigned = FALSE; 4.83 shutDownSlv->coreAnimatedBy = coreIdx; 4.84 shutDownSlv->animSlotAssignedTo = animSlots[ 0 ]; 4.85 }
5.1 --- a/PR__int.c Thu Oct 25 23:35:36 2012 -0700 5.2 +++ b/PR__int.c Sun Nov 04 18:39:28 2012 -0800 5.3 @@ -35,7 +35,7 @@ 5.4 5.5 process->numLiveGenericSlvs += 1; 5.6 5.7 - newSlv->needsTaskAssigned = TRUE; 5.8 +// newSlv->needsTaskAssigned = TRUE; 5.9 newSlv->metaTask = NULL; 5.10 newSlv->typeOfVP = GenericSlave; 5.11 5.12 @@ -109,6 +109,35 @@ 5.13 return newStub; 5.14 } 5.15 5.16 +/*This calls recycle handler registered for each langlet's sem data and meta 5.17 + * task. It also recycles the slave struct. 5.18 + * 5.19 + *This assumes that each slave has an array of 5.20 + */ 5.21 +void 5.22 +PR_int__recycle_slave_multilang( SlaveVP *slave ) 5.23 + { int32 semDataIdx, numSemDatas; 5.24 + PRSemDataHolder *semDataHolder; 5.25 + PRSemData *protoSemData, **semDatas; 5.26 + 5.27 + semDataHolder = (PRSemDataHolder *)slave->semanticData; 5.28 + semDatas = semDataHolder->semDatasIter; 5.29 + 5.30 + for( semDataIdx = 0; semDataIdx < numSemDatas; semDataIdx++ ) 5.31 + { protoSemData = semDatas[ semDataIdx ]; 5.32 + //instead of looking up the semEnv, just put ptr to recycler in protoSemData 5.33 + //To get by without, must iter through hash table.. 5.34 + (*protoSemData->recycler)(protoSemData->langSemData); 5.35 + } 5.36 + for( metaTaskIdx = 0; metaTaskIdx < numMetaTasks; metaTaskIdx++ ) 5.37 + { protoMetaTask = metaTasks[ metaTaskIdx ]; 5.38 + //instead of looking up the semEnv, just put ptr to recycler in protoSemData 5.39 + (*protoMetaTask->recycler)(protoMetaTask->langMetaTask); 5.40 + } 5.41 + 5.42 + writePrivQ( slave, slave->processSlaveIsIn->freeTaskSlvRecycleQ ); 5.43 + } 5.44 + 5.45 5.46 /* This is for OS requests and PR infrastructure requests, such as to create 5.47 * a probe -- a probe is inside the heart of PR-core, it's not part of any 5.48 @@ -244,7 +273,7 @@ 5.49 5.50 inline 5.51 void * 5.52 -PR_int__give_semEnv_of_req( PRReqst *req, SlaveVP *requestingSlv ) 5.53 +PR_int__give_sem_env_of_req( PRReqst *req, SlaveVP *requestingSlv ) 5.54 { 5.55 return PR_int__give_sem_env_for_process( requestingSlv->processSlaveIsIn, 5.56 req->langMagicNumber );
