Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
diff AnimationMaster.c @ 268:e5bd470b562b
Checkpoint 2 -- split up header file, and about to delete single lang version of AnimationMaster
| author | Sean Halle <seanhalle@yahoo.com> |
|---|---|
| date | Mon, 14 Jan 2013 15:31:23 -0800 |
| parents | 608833ae2c5d |
| children | e6a68e7ea63f |
line diff
1.1 --- a/AnimationMaster.c Sun Nov 04 18:39:28 2012 -0800 1.2 +++ b/AnimationMaster.c Mon Jan 14 15:31:23 2013 -0800 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright 2010 OpenSourceStewardshipFoundation 1.6 + * Copyright 2010 OpenSourceResearchInstitute 1.7 * 1.8 * Licensed under BSD 1.9 */ 1.10 @@ -12,9 +12,23 @@ 1.11 #include "PR.h" 1.12 #include "VSs_impl/VSs.h" 1.13 1.14 -inline void 1.15 -replaceWithNewSlotSlv( SlaveVP *slave ); 1.16 +/* 1.17 +void PRHandle_CreateTask_SL(SlaveVP *slave); 1.18 1.19 +void PRHandle_CreateSlave_SL(SlaveVP *slave); 1.20 +void PRHandle_Dissipate_SL(SlaveVP *slave); 1.21 +void PR_int__handle_PRServiceReq_SL(SlaveVP *slave); 1.22 +*/ 1.23 +inline void PRHandle_CreateTask( PRReqst *req, SlaveVP *slave ); 1.24 +inline void PRHandle_EndTask( PRReqst *req, SlaveVP *slave ); 1.25 +inline void PRHandle_CreateSlave(PRReqst *req, SlaveVP *slave ); 1.26 +void PRHandle_Dissipate( PRReqst *req, SlaveVP *slave ); 1.27 + 1.28 + 1.29 +//inline void masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot ); 1.30 +inline void masterFunction_MultiLang( AnimSlot *slot ); 1.31 +inline PRProcess * pickAProcess( AnimSlot *slot ); 1.32 +inline SlaveVP * assignWork( PRProcess *process, AnimSlot *slot ); 1.33 1.34 /*The animationMaster embodies most of the animator of the language. The 1.35 * animator is what emodies the behavior of language constructs. 1.36 @@ -40,6 +54,81 @@ 1.37 * 1.38 */ 1.39 1.40 +//This version of the master selects one of three loops, depending upon 1.41 +// whether stand-alone single language (just slaves), or standalone with 1.42 +// tasks, or multi-lang (implies multi-process) 1.43 +void animationMaster( void *_environment, SlaveVP *masterVP ) 1.44 + { 1.45 + TopEnv *masterEnv = (TopEnv *)_environment; 1.46 + int32 slotIdx; 1.47 + AnimSlot *currSlot; 1.48 + //Used while scanning and filling animation slots 1.49 + AnimSlot **animSlots; 1.50 + 1.51 + //Local copies, for performance 1.52 + int32 thisCoresIdx; 1.53 + 1.54 + //======================== Initializations ======================== 1.55 + thisCoresIdx = masterVP->coreAnimatedBy; 1.56 + animSlots = masterEnv->allAnimSlots[thisCoresIdx]; 1.57 + 1.58 + HOLISTIC__Insert_Master_Global_Vars; 1.59 + 1.60 + //======================== animationMaster ======================== 1.61 + //Have three different modes, and the master behavior is different for 1.62 + // each, so jump to the loop that corresponds to the mode. 1.63 + // 1.64 + switch(masterEnv->mode) 1.65 + { 1.66 +/* 1.67 + { case SingleLang: 1.68 + while(1) 1.69 + { MEAS__Capture_Pre_Master_Point 1.70 + for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) 1.71 + { 1.72 + currSlot = animSlots[ slotIdx ]; 1.73 + 1.74 + masterFunction_StandaloneSlavesOnly( masterEnv, currSlot ); 1.75 + } 1.76 + MEAS__Capture_Post_Master_Point; 1.77 + masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master 1.78 + flushRegisters(); 1.79 + } 1.80 + 1.81 + case SingleLang: 1.82 + { PRLangEnv *protoLangEnv = _PRTopEnv->protoLangEnv; 1.83 + while(1) 1.84 + { MEAS__Capture_Pre_Master_Point 1.85 + for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) 1.86 + { 1.87 + currSlot = animSlots[ slotIdx ]; 1.88 + 1.89 + masterFunction_SingleLang( protoLangEnv, currSlot ); 1.90 + } 1.91 + MEAS__Capture_Post_Master_Point; 1.92 + masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master 1.93 + flushRegisters(); 1.94 + } 1.95 + } 1.96 + */ 1.97 + case MultiLang: 1.98 + { while(1) 1.99 + { MEAS__Capture_Pre_Master_Point 1.100 + for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) 1.101 + { 1.102 + currSlot = animSlots[ slotIdx ]; 1.103 + 1.104 + masterFunction_MultiLang( currSlot ); 1.105 + } 1.106 + MEAS__Capture_Post_Master_Point; 1.107 + masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master 1.108 + flushRegisters(); 1.109 + } 1.110 + } 1.111 + } 1.112 + } 1.113 + 1.114 + 1.115 1.116 //===================== The versions of the Animation Master ================= 1.117 // 1.118 @@ -71,7 +160,7 @@ 1.119 * order that application code in the slaves executes. 1.120 * 1.121 *To control order of animation of slaves, the request handler has a 1.122 - * semantic environment that holds data structures used to hold slaves 1.123 + * language environment that holds data structures used to hold slaves 1.124 * and choose when they're ready to be animated. 1.125 * 1.126 *Once a slave is marked as ready to be animated by the request handler, 1.127 @@ -93,23 +182,23 @@ 1.128 *========================================================================== 1.129 *In summary, the animationMaster scans the slots, finds slaves 1.130 * just-finished, which hold requests, pass those to the request handler, 1.131 - * along with the semantic environment, and the request handler then manages 1.132 - * the structures in the semantic env, which controls the order of 1.133 + * along with the language environment, and the request handler then manages 1.134 + * the structures in the language env, which controls the order of 1.135 * animation of slaves, and so embodies the behavior of the language 1.136 * constructs. 1.137 *The animationMaster then rescans the slots, offering each empty one to 1.138 - * the Assigner, along with the semantic environment. The Assigner chooses 1.139 - * among the ready slaves in the semantic Env, finding the one best suited 1.140 + * the Assigner, along with the language environment. The Assigner chooses 1.141 + * among the ready slaves in the language env, finding the one best suited 1.142 * to be animated by that slot's associated core. 1.143 * 1.144 *========================================================================== 1.145 *Implementation Details: 1.146 * 1.147 - *There is a separate masterVP for each core, but a single semantic 1.148 + *There is a separate masterVP for each core, but a single language 1.149 * environment shared by all cores. Each core also has its own scheduling 1.150 * slots, which are used to communicate slaves between animationMaster and 1.151 * coreController. There is only one global variable, _PRTopEnv, which 1.152 - * holds the semantic env and other things shared by the different 1.153 + * holds the language env and other things shared by the different 1.154 * masterVPs. The request handler and Assigner are registered with 1.155 * the animationMaster by the language's init function, and a pointer to 1.156 * each is in the _PRTopEnv. (There are also some pthread related global 1.157 @@ -128,7 +217,7 @@ 1.158 *The core controllers access _PRTopEnv to get the masterVP, and when 1.159 * they start, the slots are all empty, so they run their associated core's 1.160 * masterVP. The first of those to get the master lock sees the seed slave 1.161 - * in the shared semantic environment, so when it runs the Assigner, that 1.162 + * in the shared language environment, so when it runs the Assigner, that 1.163 * returns the seed slave, which the animationMaster puts into a scheduling 1.164 * slot then switches to the core controller. That then switches the core 1.165 * over to the seed slave, which then proceeds to execute language 1.166 @@ -148,246 +237,100 @@ 1.167 * executing the animationMaster code, which drives for more than one. In 1.168 * practice, the best balance should be discovered by profiling. 1.169 */ 1.170 -void animationMaster( void *initData, SlaveVP *masterVP ) 1.171 +/* 1.172 +void masterFunction_StandaloneSlavesOnly( AnimSlot *slot ) 1.173 { 1.174 - //Used while scanning and filling animation slots 1.175 - int32 slotIdx, numSlotsFilled; 1.176 - AnimSlot *currSlot, **animSlots; 1.177 - SlaveVP *assignedSlaveVP; //the slave chosen by the assigner 1.178 - 1.179 - //Local copies, for performance 1.180 - MasterEnv *masterEnv; 1.181 - SlaveAssigner slaveAssigner; 1.182 - RequestHandler requestHandler; 1.183 - void *semanticEnv; 1.184 - int32 thisCoresIdx; 1.185 - 1.186 - //======================== Initializations ======================== 1.187 - masterEnv = (MasterEnv*)_PRTopEnv; 1.188 - 1.189 - thisCoresIdx = masterVP->coreAnimatedBy; 1.190 - animSlots = masterEnv->allAnimSlots[thisCoresIdx]; 1.191 - 1.192 - requestHandler = masterEnv->requestHandler; 1.193 - slaveAssigner = masterEnv->slaveAssigner; 1.194 - semanticEnv = masterEnv->semanticEnv; 1.195 - 1.196 - HOLISTIC__Insert_Master_Global_Vars; 1.197 + SlaveVP *slave; 1.198 + PRReqst *req; 1.199 + PRLangEnv *langEnv = _PRTopEnv->langEnv; 1.200 + 1.201 1.202 //======================== animationMaster ======================== 1.203 - while(1){ 1.204 - 1.205 - MEAS__Capture_Pre_Master_Point 1.206 + 1.207 + //Check if newly-done slave in slot, which will need request handled 1.208 + if( slot->workIsDone ) 1.209 + { slot->workIsDone = FALSE; 1.210 + slot->needsWorkAssigned = TRUE; 1.211 1.212 - //Scan the animation slots 1.213 - numSlotsFilled = 0; 1.214 - for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) 1.215 - { 1.216 - currSlot = animSlots[ slotIdx ]; 1.217 1.218 - //Check if newly-done slave in slot, which will need request handled 1.219 - if( currSlot->workIsDone ) 1.220 - { 1.221 - currSlot->workIsDone = FALSE; 1.222 - currSlot->needsWorkAssigned = TRUE; 1.223 - 1.224 - HOLISTIC__Record_AppResponder_start; 1.225 - MEAS__startReqHdlr; 1.226 - 1.227 - currSlot->workIsDone = FALSE; 1.228 - currSlot->needsWorkAssigned = TRUE; 1.229 - SlaveVP *currSlave = currSlot->slaveAssignedToSlot; 1.230 - 1.231 - justAddedReqHdlrChg(); 1.232 - //handle the request, either by PR or by the language 1.233 - if( currSlave->requests->reqType != LangReq ) 1.234 - { //The request is a standard PR one, not one defined by the 1.235 - // language, so PR handles it, then queues slave to be assigned 1.236 - handleReqInPR( currSlave ); 1.237 - writePrivQ( currSlave, PRReadyQ ); //Q slave to be assigned below 1.238 - } 1.239 - else 1.240 - { MEAS__startReqHdlr; 1.241 + HOLISTIC__Record_AppResponder_start; 1.242 + MEAS__startReqHdlr; 1.243 + //process the request made by the slave (held inside slave struc) 1.244 + slave = slot->slaveAssignedToSlot; 1.245 + req = slave->request; 1.246 1.247 - //Language handles request, which is held inside slave struc 1.248 - (*requestHandler)( currSlave, semanticEnv ); 1.249 - 1.250 - MEAS__endReqHdlr; 1.251 - } 1.252 - } 1.253 - 1.254 - //process the requests made by the slave (held inside slave struc) 1.255 - (*requestHandler)( currSlot->slaveAssignedToSlot, semanticEnv ); 1.256 - 1.257 - HOLISTIC__Record_AppResponder_end; 1.258 - MEAS__endReqHdlr; 1.259 - } 1.260 - //If slot empty, hand to Assigner to fill with a slave 1.261 - if( currSlot->needsWorkAssigned ) 1.262 - { //Call plugin's Assigner to give slot a new slave 1.263 - HOLISTIC__Record_Assigner_start; 1.264 - assignedSlaveVP = 1.265 - (*slaveAssigner)( semanticEnv, currSlot ); 1.266 - 1.267 - //put the chosen slave into slot, and adjust flags and state 1.268 - if( assignedSlaveVP != NULL ) 1.269 - { currSlot->slaveAssignedToSlot = assignedSlaveVP; 1.270 - assignedSlaveVP->animSlotAssignedTo = currSlot; 1.271 - currSlot->needsWorkAssigned = FALSE; 1.272 - numSlotsFilled += 1; 1.273 - 1.274 - HOLISTIC__Record_Assigner_end; 1.275 + //Handle task create and end first -- they're special cases.. 1.276 + switch( req->reqType ) 1.277 + { case SlvCreate: PRHandle_CreateSlave( slave ); break; 1.278 + case SlvDissipate: PRHandle_Dissipate( slave ); break; 1.279 + case Service: PR_int__handle_PRServiceReq( slave ); break; //resume into PR's own language env 1.280 + case Hardware: //for future expansion 1.281 + case IO: //for future expansion 1.282 + case OSCall: //for future expansion 1.283 + PR_int__throw_exception("Not implemented"); break; 1.284 + case Language: //normal lang request 1.285 + { 1.286 + (*langEnv->requestHdlr)( req->langReq, slave, langEnv ); 1.287 } 1.288 } 1.289 + HOLISTIC__Record_AppResponder_end; 1.290 + MEAS__endReqHdlr; 1.291 } 1.292 + //If slot empty, hand to Assigner to fill with a slave 1.293 + if( slot->needsWorkAssigned ) 1.294 + { //Call plugin's Assigner to give slot a new slave 1.295 + HOLISTIC__Record_Assigner_start; 1.296 1.297 - MEAS__Capture_Post_Master_Point; 1.298 + if( langEnv->hasWork ) 1.299 + { (*langEnv->slaveAssigner)( langEnv, slot ); //calls PR fn that inserts work into slot 1.300 + goto ReturnAfterAssigningWork; //quit for-loop, cause found work 1.301 + } 1.302 + else 1.303 + goto NoWork; 1.304 + } 1.305 1.306 - masterSwitchToCoreCtlr( masterVP ); 1.307 - flushRegisters(); 1.308 - DEBUG__printf(FALSE,"came back after switch to core -- so lock released!"); 1.309 - }//while(1) 1.310 + NoWork: 1.311 + //No work, if reach here.. 1.312 + { 1.313 + #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 1.314 + coreNum = slot->coreSlotIsOn; 1.315 + returnSlv = process->idleSlv[coreNum][slotNum]; 1.316 + 1.317 + //things that would normally happen in resume(), but idle VPs 1.318 + // never go there 1.319 + returnSlv->numTimesAssignedToASlot++; //gives each idle unit a unique ID 1.320 + Unit newU; 1.321 + newU.vp = returnSlv->slaveNum; 1.322 + newU.task = returnSlv->numTimesAssignedToASlot; 1.323 + addToListOfArrays(Unit,newU,process->unitList); 1.324 + 1.325 + if (returnSlv->numTimesAssignedToASlot > 1) //make a dependency from prev idle unit 1.326 + { Dependency newD; // to this one 1.327 + newD.from_vp = returnSlv->slaveNum; 1.328 + newD.from_task = returnSlv->numTimesAssignedToASlot - 1; 1.329 + newD.to_vp = returnSlv->slaveNum; 1.330 + newD.to_task = returnSlv->numTimesAssignedToASlot; 1.331 + addToListOfArrays(Dependency, newD ,process->ctlDependenciesList); 1.332 + } 1.333 + #endif 1.334 + HOLISTIC__Record_Assigner_end; 1.335 + return; 1.336 + } 1.337 + 1.338 + ReturnAfterAssigningWork: //All paths goto here.. to provide single point for holistic.. 1.339 + { 1.340 + HOLISTIC__Record_Assigner_end; 1.341 + return; 1.342 + } 1.343 } 1.344 - 1.345 - 1.346 -/* 2) This version is for a single language that has only tasks, which 1.347 - * cannot be suspended. 1.348 - */ 1.349 -void animationMaster( void *initData, SlaveVP *masterVP ) 1.350 - { 1.351 - //Used while scanning and filling animation slots 1.352 - int32 slotIdx, numSlotsFilled; 1.353 - AnimSlot *currSlot, **animSlots; 1.354 - SlaveVP *assignedSlaveVP; //the slave chosen by the assigner 1.355 - 1.356 - //Local copies, for performance 1.357 - MasterEnv *masterEnv; 1.358 - SlaveAssigner slaveAssigner; 1.359 - RequestHandler requestHandler; 1.360 - PRSemEnv *semanticEnv; 1.361 - int32 thisCoresIdx; 1.362 - 1.363 - //#ifdef MODE__MULTI_LANG 1.364 - SlaveVP *slave; 1.365 - PRProcess *process; 1.366 - int32 langMagicNumber; 1.367 - //#endif 1.368 - 1.369 - //======================== Initializations ======================== 1.370 - masterEnv = (MasterEnv*)_PRTopEnv; 1.371 - 1.372 - thisCoresIdx = masterVP->coreAnimatedBy; 1.373 - animSlots = masterEnv->allAnimSlots[thisCoresIdx]; 1.374 - 1.375 - requestHandler = masterEnv->requestHandler; 1.376 - slaveAssigner = masterEnv->slaveAssigner; 1.377 - semanticEnv = masterEnv->semanticEnv; 1.378 - 1.379 - //initialize, for non-multi-lang, non multi-proc case 1.380 - // default handler gets put into master env by a registration call by lang 1.381 - endTaskHandler = masterEnv->defaultTaskHandler; 1.382 - 1.383 - HOLISTIC__Insert_Master_Global_Vars; 1.384 - 1.385 - //======================== animationMaster ======================== 1.386 - //Do loop gets requests handled and work assigned to slots.. 1.387 - // work can either be a task or a resumed slave 1.388 - //Having two cases makes this logic complex.. can be finishing either, and 1.389 - // then the next available work may be either.. so really have two distinct 1.390 - // loops that are inter-twined.. 1.391 - while(1){ 1.392 - 1.393 - MEAS__Capture_Pre_Master_Point 1.394 - 1.395 - //Scan the animation slots 1.396 - numSlotsFilled = 0; 1.397 - for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) 1.398 - { 1.399 - currSlot = animSlots[ slotIdx ]; 1.400 - 1.401 - //Check if newly-done slave in slot, which will need request handled 1.402 - if( currSlot->workIsDone ) 1.403 - { currSlot->workIsDone = FALSE; 1.404 - 1.405 - HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot 1.406 - MEAS__startReqHdlr; 1.407 - 1.408 - 1.409 - //process the request made by the slave (held inside slave struc) 1.410 - slave = currSlot->slaveAssignedToSlot; 1.411 - 1.412 - //check if the completed work was a task.. 1.413 - if( slave->metaTask->isATask ) 1.414 - { 1.415 - if( slave->request->type == TaskEnd ) 1.416 - { //do task end handler, which is registered separately 1.417 - //note, end hdlr may use semantic data from reqst.. 1.418 - //#ifdef MODE__MULTI_LANG 1.419 - //get end-task handler 1.420 - //taskEndHandler = lookup( slave->reqst->langMagicNumber, processEnv ); 1.421 - taskEndHandler = slave->metaTask->endTaskHandler; 1.422 - //#endif 1.423 - (*taskEndHandler)( slave, semanticEnv ); 1.424 - 1.425 - goto AssignWork; 1.426 - } 1.427 - else //is a task, and just suspended 1.428 - { //turn slot slave into free task slave & make replacement 1.429 - if( slave->typeOfVP == SlotTaskSlv ) changeSlvType(); 1.430 - 1.431 - //goto normal slave request handling 1.432 - goto SlaveReqHandling; 1.433 - } 1.434 - } 1.435 - else //is a slave that suspended 1.436 - { 1.437 - SlaveReqHandling: 1.438 - (*requestHandler)( slave, semanticEnv ); //(note: indirect Fn call more efficient when use fewer params, instead re-fetch from slave) 1.439 - 1.440 - HOLISTIC__Record_AppResponder_end; 1.441 - MEAS__endReqHdlr; 1.442 - 1.443 - goto AssignWork; 1.444 - } 1.445 - } //if has suspended slave that needs handling 1.446 - 1.447 - //if slot empty, hand to Assigner to fill with a slave 1.448 - if( currSlot->needsWorkAssigned ) 1.449 - { //Call plugin's Assigner to give slot a new slave 1.450 - HOLISTIC__Record_Assigner_start; 1.451 - 1.452 - AssignWork: 1.453 - 1.454 - assignedSlaveVP = assignWork( semanticEnv, currSlot ); 1.455 - 1.456 - //put the chosen slave into slot, and adjust flags and state 1.457 - if( assignedSlaveVP != NULL ) 1.458 - { currSlot->slaveAssignedToSlot = assignedSlaveVP; 1.459 - assignedSlaveVP->animSlotAssignedTo = currSlot; 1.460 - currSlot->needsWorkAssigned = FALSE; 1.461 - numSlotsFilled += 1; 1.462 - } 1.463 - else 1.464 - { 1.465 - currSlot->needsWorkAssigned = TRUE; //local write 1.466 - } 1.467 - HOLISTIC__Record_Assigner_end; 1.468 - }//if slot needs slave assigned 1.469 - }//for( slotIdx.. 1.470 - 1.471 - MEAS__Capture_Post_Master_Point; 1.472 - 1.473 - masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master 1.474 - flushRegisters(); 1.475 - }//while(1) 1.476 - } 1.477 +*/ 1.478 1.479 1.480 /*This is the master when just multi-lang, but not multi-process mode is on. 1.481 * This version has to handle both tasks and slaves, and do extra work of 1.482 - * looking up the semantic env and handlers to use, for each completed bit of 1.483 + * looking up the language env and handlers to use, for each completed bit of 1.484 * work. 1.485 - *It also has to search through the semantic envs to find one with work, 1.486 + *It also has to search through the language envs to find one with work, 1.487 * then ask that env's assigner to return a unit of that work. 1.488 * 1.489 *The language is written to startup in the same way as if it were the only 1.490 @@ -429,9 +372,9 @@ 1.491 * 1.492 *The multi-lang thing complicates matters.. 1.493 * 1.494 - *For request handling, it means have to first fetch the semantic environment 1.495 + *For request handling, it means have to first fetch the language environment 1.496 * of the language, and then do the request handler pointed to by that 1.497 - * semantic env. 1.498 + * language env. 1.499 *For assigning, things get more complex because of competing goals.. One 1.500 * goal is for language specific stuff to be used during assignment, so 1.501 * assigner can make higher quality decisions.. but with multiple languages, 1.502 @@ -452,9 +395,9 @@ 1.503 * queue at a time.. but this is quite hack-like.. or perhaps HWSim supplies 1.504 * a task-end handler that kicks the next unit of work from HWSim internal 1.505 * priority queue, over to PR readyQ) 1.506 - *2) can have each language have its own semantic env, that holds its own 1.507 + *2) can have each language have its own language env, that holds its own 1.508 * work, which is assigned by its own assigner.. then the master searches 1.509 - * through all the semantic envs to find one with work and asks it give work.. 1.510 + * through all the language envs to find one with work and asks it give work.. 1.511 * (this has downside of blinding assigners to each other.. but does work 1.512 * for HWSim case) 1.513 *3) could make PR have a different readyQ for each core, and ask the lang 1.514 @@ -477,383 +420,217 @@ 1.515 * the languages in a unified way.. Don't really expect this to happen, 1.516 * but making it possible. 1.517 */ 1.518 -#ifdef MODE__MULTI_LANG 1.519 -void animationMaster( void *initData, SlaveVP *masterVP ) 1.520 - { 1.521 - //Used while scanning and filling animation slots 1.522 - int32 slotIdx, numSlotsFilled; 1.523 - AnimSlot *currSlot, **animSlots; 1.524 - SlaveVP *assignedSlaveVP; //the slave chosen by the assigner 1.525 +/* 1.526 +inline 1.527 +void 1.528 +masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot ) 1.529 + { //Scan the animation slots 1.530 + SlaveVP *slave; 1.531 + PRReqst *req; 1.532 + 1.533 + //Check if newly-done slave in slot, which will need request handled 1.534 + if( slot->workIsDone ) 1.535 + { slot->workIsDone = FALSE; 1.536 + slot->needsWorkAssigned = TRUE; 1.537 + 1.538 + HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot 1.539 + MEAS__startReqHdlr; 1.540 + 1.541 + 1.542 + //process the request made by the slave (held inside slave struc) 1.543 + slave = slot->slaveAssignedToSlot; 1.544 + req = slave->request; 1.545 + 1.546 + //If the requesting slave is a slot slave, and request is not 1.547 + // task-end, then turn it into a free task slave. 1.548 + if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd ) 1.549 + PR_int__replace_with_new_slot_slv( slave ); 1.550 + 1.551 + //Handle task create and end first -- they're special cases.. 1.552 + switch( req->reqType ) 1.553 + { case TaskEnd: 1.554 + { //do PR handler, which calls lang's hdlr and does recycle of 1.555 + // free task slave if needed -- PR handler checks for free task Slv 1.556 + PRHandle_EndTask_SL( slave ); break; 1.557 + } 1.558 + case TaskCreate: 1.559 + { //Do PR's create-task handler, which calls the lang's hdlr 1.560 + // PR handler checks for free task Slv 1.561 + PRHandle_CreateTask_SL( slave ); break; 1.562 + } 1.563 + case SlvCreate: PRHandle_CreateSlave_SL( slave ); break; 1.564 + case SlvDissipate: PRHandle_Dissipate_SL( slave ); break; 1.565 + case Service: PR_int__handle_PRServiceReq_SL( slave ); break; //resume into PR's own language env 1.566 + case Hardware: //for future expansion 1.567 + case IO: //for future expansion 1.568 + case OSCall: //for future expansion 1.569 + PR_int__throw_exception("Not implemented", slave, NULL); break; 1.570 + case Language: //normal lang request 1.571 + { 1.572 + (*protoLangEnv->requestHdlr)( req->langReq, slave, (void*)PR_int__give_lang_env(protoLangEnv )); 1.573 + } 1.574 + } 1.575 + 1.576 + MEAS__endReqHdlr; 1.577 + HOLISTIC__Record_AppResponder_end; 1.578 + } //if have request to be handled 1.579 + 1.580 + //If slot empty, hand to Assigner to fill with a slave 1.581 + if( slot->needsWorkAssigned ) 1.582 + { //Call plugin's Assigner to give slot a new slave 1.583 + HOLISTIC__Record_Assigner_start; 1.584 + 1.585 + if( protoLangEnv->hasWork ) 1.586 + { (*protoLangEnv->slaveAssigner)( protoLangEnv, slot ); //calls PR fn that inserts work into slot 1.587 + goto ReturnAfterAssigningWork; //quit for-loop, cause found work 1.588 + } 1.589 + else 1.590 + goto NoWork; 1.591 + } 1.592 1.593 - //Local copies, for performance 1.594 - MasterEnv *masterEnv; 1.595 - SlaveAssigner slaveAssigner; 1.596 - RequestHandler requestHandler; 1.597 - PRSemEnv *semanticEnv; 1.598 - int32 thisCoresIdx; 1.599 + NoWork: 1.600 + //No work, if reach here.. 1.601 + { 1.602 + #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 1.603 + coreNum = slot->coreSlotIsOn; 1.604 + returnSlv = process->idleSlv[coreNum][slotNum]; 1.605 + 1.606 + //things that would normally happen in resume(), but idle VPs 1.607 + // never go there 1.608 + returnSlv->numTimesAssignedToASlot++; //gives each idle unit a unique ID 1.609 + Unit newU; 1.610 + newU.vp = returnSlv->slaveNum; 1.611 + newU.task = returnSlv->numTimesAssignedToASlot; 1.612 + addToListOfArrays(Unit,newU,process->unitList); 1.613 1.614 - //#ifdef MODE__MULTI_LANG 1.615 - SlaveVP *slave; 1.616 - PRProcess *process; 1.617 - int32 langMagicNumber; 1.618 - //#endif 1.619 - 1.620 - //======================== Initializations ======================== 1.621 - masterEnv = (MasterEnv*)_PRTopEnv; 1.622 - 1.623 - thisCoresIdx = masterVP->coreAnimatedBy; 1.624 - animSlots = masterEnv->allAnimSlots[thisCoresIdx]; 1.625 - 1.626 - requestHandler = masterEnv->requestHandler; 1.627 - slaveAssigner = masterEnv->slaveAssigner; 1.628 - semanticEnv = masterEnv->semanticEnv; 1.629 - 1.630 - //initialize, for non-multi-lang, non multi-proc case 1.631 - // default handler gets put into master env by a registration call by lang 1.632 - endTaskHandler = masterEnv->defaultTaskHandler; 1.633 - 1.634 - HOLISTIC__Insert_Master_Global_Vars; 1.635 - 1.636 - //======================== animationMaster ======================== 1.637 - //Do loop gets requests handled and work assigned to slots.. 1.638 - // work can either be a task or a resumed slave 1.639 - //Having two cases makes this logic complex.. can be finishing either, and 1.640 - // then the next available work may be either.. so really have two distinct 1.641 - // loops that are inter-twined.. 1.642 - while(1){ 1.643 - 1.644 - MEAS__Capture_Pre_Master_Point 1.645 - 1.646 - //Scan the animation slots 1.647 - numSlotsFilled = 0; 1.648 - for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) 1.649 + if (returnSlv->numTimesAssignedToASlot > 1) //make a dependency from prev idle unit 1.650 + { Dependency newD; // to this one 1.651 + newD.from_vp = returnSlv->slaveNum; 1.652 + newD.from_task = returnSlv->numTimesAssignedToASlot - 1; 1.653 + newD.to_vp = returnSlv->slaveNum; 1.654 + newD.to_task = returnSlv->numTimesAssignedToASlot; 1.655 + addToListOfArrays(Dependency, newD ,process->ctlDependenciesList); 1.656 + } 1.657 + #endif 1.658 + HOLISTIC__Record_Assigner_end; 1.659 + return; 1.660 + } 1.661 + 1.662 + ReturnAfterAssigningWork: //All paths goto here.. to provide single point for holistic.. 1.663 { 1.664 - currSlot = animSlots[ slotIdx ]; 1.665 - 1.666 - //Check if newly-done slave in slot, which will need request handled 1.667 - if( currSlot->workIsDone ) 1.668 - { currSlot->workIsDone = FALSE; 1.669 - 1.670 - HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot 1.671 - MEAS__startReqHdlr; 1.672 - 1.673 - 1.674 - //process the request made by the slave (held inside slave struc) 1.675 - slave = currSlot->slaveAssignedToSlot; 1.676 - 1.677 - //check if the completed work was a task.. 1.678 - if( slave->taskMetaInfo->isATask ) 1.679 - { 1.680 - if( slave->reqst->type == TaskEnd ) 1.681 - { //do task end handler, which is registered separately 1.682 - //note, end hdlr may use semantic data from reqst.. 1.683 - //#ifdef MODE__MULTI_LANG 1.684 - //get end-task handler 1.685 - //taskEndHandler = lookup( slave->reqst->langMagicNumber, processEnv ); 1.686 - taskEndHandler = slave->taskMetaInfo->endTaskHandler; 1.687 - //#endif 1.688 - (*taskEndHandler)( slave, semanticEnv ); 1.689 - 1.690 - goto AssignWork; 1.691 - } 1.692 - else //is a task, and just suspended 1.693 - { //turn slot slave into free task slave & make replacement 1.694 - if( slave->typeOfVP == SlotTaskSlv ) changeSlvType(); 1.695 - 1.696 - //goto normal slave request handling 1.697 - goto SlaveReqHandling; 1.698 - } 1.699 - } 1.700 - else //is a slave that suspended 1.701 - { 1.702 - SlaveReqHandling: 1.703 - (*requestHandler)( slave, semanticEnv ); //(note: indirect Fn call more efficient when use fewer params, instead re-fetch from slave) 1.704 - 1.705 - HOLISTIC__Record_AppResponder_end; 1.706 - MEAS__endReqHdlr; 1.707 - 1.708 - goto AssignWork; 1.709 - } 1.710 - } //if has suspended slave that needs handling 1.711 - 1.712 - //if slot empty, hand to Assigner to fill with a slave 1.713 - if( currSlot->needsWorkAssigned ) 1.714 - { //Call plugin's Assigner to give slot a new slave 1.715 - HOLISTIC__Record_Assigner_start; 1.716 - 1.717 - AssignWork: 1.718 - 1.719 - assignedSlaveVP = assignWork( semanticEnv, currSlot ); 1.720 - 1.721 - //put the chosen slave into slot, and adjust flags and state 1.722 - if( assignedSlaveVP != NULL ) 1.723 - { currSlot->slaveAssignedToSlot = assignedSlaveVP; 1.724 - assignedSlaveVP->animSlotAssignedTo = currSlot; 1.725 - currSlot->needsWorkAssigned = FALSE; 1.726 - numSlotsFilled += 1; 1.727 - } 1.728 - else 1.729 - { 1.730 - currSlot->needsWorkAssigned = TRUE; //local write 1.731 - } 1.732 - HOLISTIC__Record_Assigner_end; 1.733 - }//if slot needs slave assigned 1.734 - }//for( slotIdx.. 1.735 - 1.736 - MEAS__Capture_Post_Master_Point; 1.737 - 1.738 - masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master 1.739 - flushRegisters(); 1.740 - }//while(1) 1.741 - } 1.742 -#endif //MODE__MULTI_LANG 1.743 - 1.744 - 1.745 - 1.746 -//This is the master when both multi-lang and multi-process modes are turned on 1.747 -//#ifdef MODE__MULTI_LANG 1.748 -//#ifdef MODE__MULTI_PROCESS 1.749 -void animationMaster( void *initData, SlaveVP *masterVP ) 1.750 - { 1.751 - int32 slotIdx; 1.752 - AnimSlot *currSlot; 1.753 - //Used while scanning and filling animation slots 1.754 - AnimSlot **animSlots; 1.755 - 1.756 - //Local copies, for performance 1.757 - MasterEnv *masterEnv; 1.758 - int32 thisCoresIdx; 1.759 - 1.760 - //======================== Initializations ======================== 1.761 - masterEnv = (MasterEnv*)_PRTopEnv; 1.762 - 1.763 - thisCoresIdx = masterVP->coreAnimatedBy; 1.764 - animSlots = masterEnv->allAnimSlots[thisCoresIdx]; 1.765 - 1.766 - HOLISTIC__Insert_Master_Global_Vars; 1.767 - 1.768 - //======================== animationMaster ======================== 1.769 - //Do loop gets requests handled and work assigned to slots.. 1.770 - // work can either be a task or a resumed slave 1.771 - //Having two cases makes this logic complex.. can be finishing either, and 1.772 - // then the next available work may be either.. so really have two distinct 1.773 - // loops that are inter-twined.. 1.774 - while(1) 1.775 - { 1.776 - MEAS__Capture_Pre_Master_Point 1.777 - 1.778 - for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) 1.779 - { 1.780 - currSlot = animSlots[ slotIdx ]; 1.781 - 1.782 - masterFunction_multiLang( currSlot ); 1.783 - } 1.784 - 1.785 - MEAS__Capture_Post_Master_Point; 1.786 - 1.787 - masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master 1.788 - flushRegisters(); 1.789 - } 1.790 - } 1.791 -#endif //MODE__MULTI_LANG 1.792 -#endif //MODE__MULTI_PROCESS 1.793 - 1.794 - 1.795 -//This version of the master selects one of three loops, depending upon 1.796 -// whether stand-alone single language (just slaves), or standalone with 1.797 -// tasks, or multi-lang (implies multi-process) 1.798 -void animationMaster( void *initData, SlaveVP *masterVP ) 1.799 - { 1.800 - int32 slotIdx; 1.801 - AnimSlot *currSlot; 1.802 - //Used while scanning and filling animation slots 1.803 - AnimSlot **animSlots; 1.804 - 1.805 - //Local copies, for performance 1.806 - MasterEnv *masterEnv; 1.807 - int32 thisCoresIdx; 1.808 - 1.809 - //======================== Initializations ======================== 1.810 - masterEnv = (MasterEnv*)_PRTopEnv; 1.811 - 1.812 - thisCoresIdx = masterVP->coreAnimatedBy; 1.813 - animSlots = masterEnv->allAnimSlots[thisCoresIdx]; 1.814 - 1.815 - HOLISTIC__Insert_Master_Global_Vars; 1.816 - 1.817 - //======================== animationMaster ======================== 1.818 - //Have three different modes, and the master behavior is different for 1.819 - // each, so jump to the loop that corresponds to the mode. 1.820 - // 1.821 - switch(mode) 1.822 - { case StandaloneSlavesOnly: 1.823 - while(1) 1.824 - { MEAS__Capture_Pre_Master_Point 1.825 - for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) 1.826 - { 1.827 - currSlot = animSlots[ slotIdx ]; 1.828 - 1.829 - masterFunction_StandaloneSlavesOnly( currSlot ); 1.830 - } 1.831 - MEAS__Capture_Post_Master_Point; 1.832 - masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master 1.833 - flushRegisters(); 1.834 - } 1.835 - case StandaloneWTasks: 1.836 - while(1) 1.837 - { MEAS__Capture_Pre_Master_Point 1.838 - for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) 1.839 - { 1.840 - currSlot = animSlots[ slotIdx ]; 1.841 - 1.842 - masterFunction_StandaloneWTasks( currSlot ); 1.843 - } 1.844 - MEAS__Capture_Post_Master_Point; 1.845 - masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master 1.846 - flushRegisters(); 1.847 - } 1.848 - case MultiLang: 1.849 - while(1) 1.850 - { MEAS__Capture_Pre_Master_Point 1.851 - for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) 1.852 - { 1.853 - currSlot = animSlots[ slotIdx ]; 1.854 - 1.855 - masterFunction_multiLang( currSlot ); 1.856 - } 1.857 - MEAS__Capture_Post_Master_Point; 1.858 - masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master 1.859 - flushRegisters(); 1.860 - } 1.861 + HOLISTIC__Record_Assigner_end; 1.862 + return; 1.863 } 1.864 } 1.865 - 1.866 +*/ 1.867 1.868 inline 1.869 void 1.870 -masterFunction_multiLang( AnimSlot *currSlot ) 1.871 +masterFunction_MultiLang( AnimSlot *slot ) 1.872 { //Scan the animation slots 1.873 int32 magicNumber; 1.874 SlaveVP *slave; 1.875 - SlaveVP *assignedSlaveVP; 1.876 - PRSemEnv *semanticEnv; 1.877 + PRLangEnv *langEnv; 1.878 PRReqst *req; 1.879 RequestHandler requestHandler; 1.880 + PRProcess *process; 1.881 1.882 - //Check if newly-done slave in slot, which will need request handled 1.883 - if( currSlot->workIsDone ) 1.884 - { currSlot->workIsDone = FALSE; 1.885 - currSlot->needsWorkAssigned = TRUE; 1.886 - 1.887 - HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot 1.888 - MEAS__startReqHdlr; 1.889 - 1.890 - 1.891 - //process the request made by the slave (held inside slave struc) 1.892 - slave = currSlot->slaveAssignedToSlot; 1.893 - req = slave->request; 1.894 + //Check if newly-done slave in slot, which will need request handled 1.895 + if( slot->workIsDone ) 1.896 + { slot->workIsDone = FALSE; 1.897 + slot->needsWorkAssigned = TRUE; 1.898 1.899 - //If the requesting slave is a slot slave, and request is not 1.900 - // task-end, then turn it into a free task slave. 1.901 - if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd ) 1.902 - replaceWithNewSlotSlv( slave ); 1.903 + HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot 1.904 + MEAS__startReqHdlr; 1.905 1.906 - //Handle task create and end first -- they're special cases.. 1.907 - switch( req->reqType ) 1.908 - { case TaskEnd: 1.909 - { //do PR handler, which calls lang's hdlr and does recycle of 1.910 - // free task slave if needed -- PR handler checks for free task Slv 1.911 - PRHandle_EndTask( slave ); break; 1.912 - } 1.913 - case TaskCreate: 1.914 - { //Do PR's create-task handler, which calls the lang's hdlr 1.915 - // PR handler checks for free task Slv 1.916 - PRHandle_CreateTask( slave ); break; 1.917 - } 1.918 - case SlvCreate: PRHandle_CreateSlave( slave ); break; 1.919 - case SlvDissipate: PRHandle_Dissipate( slave ); break; 1.920 - case Service: PR_int__handle_PRServiceReq( slave ); break; //resume into PR's own semantic env 1.921 - case Hardware: //for future expansion 1.922 - case IO: //for future expansion 1.923 - case OSCall: //for future expansion 1.924 - PR_int__throw_exception("Not implemented"); break; 1.925 - case Language: //normal sem request 1.926 - magicNumber = req->langMagicNumber; 1.927 - semanticEnv = PR_PI__give_sem_env_for( slave, magicNumber ); 1.928 - requestHandler = semanticEnv->requestHdlr; 1.929 - (*requestHandler)( req->semReq, slave, semanticEnv ); 1.930 + 1.931 + //process the request made by the slave (held inside slave struc) 1.932 + slave = slot->slaveAssignedToSlot; 1.933 + req = slave->request; 1.934 + 1.935 + //If the requesting slave is a slot slave, and request is not 1.936 + // task-end, then turn it into a free task slave. 1.937 + if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd ) 1.938 + PR_int__replace_with_new_slot_slv( slave ); 1.939 + 1.940 + //Handle task create and end first -- they're special cases.. 1.941 + switch( req->reqType ) 1.942 + { case TaskEnd: 1.943 + { //do PR handler, which calls lang's hdlr and does recycle of 1.944 + // free task slave if needed -- PR handler checks for free task Slv 1.945 + PRHandle_EndTask( req, slave ); break; 1.946 } 1.947 + case TaskCreate: 1.948 + { //Do PR's create-task handler, which calls the lang's hdlr 1.949 + // PR handler checks for free task Slv 1.950 + PRHandle_CreateTask( req, slave ); break; 1.951 + } 1.952 + case SlvCreate: PRHandle_CreateSlave( req, slave ); break; 1.953 + case SlvDissipate: PRHandle_Dissipate( req, slave ); break; 1.954 + case Service: PR_int__handle_PRServiceReq( slave ); break; //resume into PR's own language env 1.955 + case Hardware: //for future expansion 1.956 + case IO: //for future expansion 1.957 + case OSCall: //for future expansion 1.958 + PR_int__throw_exception("Not implemented", slave, NULL); break; 1.959 + case Language: //normal lang request 1.960 + { magicNumber = req->langMagicNumber; 1.961 + langEnv = PR_PI__give_lang_env_for( slave, magicNumber ); 1.962 + (*req->handler)( req->langReq, slave, langEnv ); 1.963 + } 1.964 + } 1.965 1.966 + MEAS__endReqHdlr; 1.967 HOLISTIC__Record_AppResponder_end; 1.968 - MEAS__endReqHdlr; 1.969 - } //if have request to be handled 1.970 - 1.971 - if( currSlot->needsWorkAssigned ) 1.972 - { 1.973 - HOLISTIC__Record_Assigner_start; 1.974 - 1.975 - //Scan sem environs, looking for semEnv with ready work. 1.976 - // call the Assigner for that sem Env, to get a slave for the slot 1.977 - assignedSlaveVP = assignWork( semanticEnv, currSlot ); 1.978 - 1.979 - //if work found, put into slot, and adjust flags and state 1.980 - if( assignedSlaveVP != NULL ) 1.981 - { currSlot->slaveAssignedToSlot = assignedSlaveVP; 1.982 - assignedSlaveVP->animSlotAssignedTo = currSlot; 1.983 - currSlot->needsWorkAssigned = FALSE; 1.984 - } 1.985 - HOLISTIC__Record_Assigner_end; 1.986 - }//if slot needs slave assigned 1.987 + } //if have request to be handled 1.988 + 1.989 + if( slot->needsWorkAssigned ) 1.990 + { 1.991 + HOLISTIC__Record_Assigner_start; 1.992 + 1.993 + //Pick a process to get this slot 1.994 + process = pickAProcess( slot ); 1.995 + 1.996 + //Scan lang environs, looking for langEnv with ready work. 1.997 + // call the Assigner for that lang Env, to get a slave for the slot 1.998 + assignWork( process, slot ); 1.999 + 1.1000 + HOLISTIC__Record_Assigner_end; 1.1001 + }//if slot needs slave assigned 1.1002 } 1.1003 1.1004 -//========================================================================== 1.1005 -/*When a task in a slot slave suspends, the slot slave has to be changed to 1.1006 - * a free task slave, then the slot slave replaced. The replacement can be 1.1007 - * either a recycled free task slave that finished it's task and has been 1.1008 - * idle in the recycle queue, or else create a new slave to be the slot slave. 1.1009 - *The master only calls this with a slot slave that needs to be replaced. 1.1010 +/*When several processes exist, use some pattern for picking one to give 1.1011 + * the animation slot to. 1.1012 + *First, it has to be a process that has work available. 1.1013 + *For now, just do a round-robin 1.1014 */ 1.1015 -inline void 1.1016 -replaceWithNewSlotSlv( SlaveVP *requestingSlv, PRProcess *process ) 1.1017 - { SlaveVP *newSlotSlv; 1.1018 - 1.1019 - When slot slave converted to a free task slave, insert the process pointer -- slot slaves are not assigned to any process; 1.1020 - 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.1021 - 1.1022 - //get a new slave to be the slot slave 1.1023 - newSlotSlv = readPrivQ( process->freeTaskSlvRecycleQ ); 1.1024 - if( newSlotSlv == NULL ) 1.1025 - { newSlotSlv = PR_int__create_slaveVP( &idle_fn, NULL, process, 0); 1.1026 - //just made a new free task slave, so count it 1.1027 - process->numLiveFreeTaskSlvs += 1; 1.1028 +inline 1.1029 +PRProcess * 1.1030 +pickAProcess( AnimSlot *slot ) 1.1031 + { int32 idx; 1.1032 + PRProcess *process; 1.1033 + 1.1034 + for( idx = _PRTopEnv->currProcessIdx; idx < _PRTopEnv->numProcesses; idx++) 1.1035 + { 1.1036 + process = _PRTopEnv->processes[ idx ]; 1.1037 + if( process->numEnvsWithWork != 0 ) 1.1038 + { _PRTopEnv->currProcessIdx = idx; 1.1039 + return process; 1.1040 + } 1.1041 } 1.1042 - 1.1043 - //set slave values to make it the slot slave 1.1044 - newSlotSlv->metaTask = NULL; 1.1045 - newSlotSlv->typeOfVP = SlotTaskSlv; 1.1046 -// newSlotSlv->needsTaskAssigned = TRUE; 1.1047 - 1.1048 - //a slot slave is pinned to a particular slot on a particular core 1.1049 - //Note, this happens before the request is seen by handler, so nothing 1.1050 - // has had a chance to change the coreAnimatedBy or anything else.. 1.1051 - newSlotSlv->animSlotAssignedTo = requestingSlv->animSlotAssignedTo; 1.1052 - newSlotSlv->coreAnimatedBy = requestingSlv->coreAnimatedBy; 1.1053 - 1.1054 - //put it into the slot slave matrix 1.1055 - int32 slotNum = requestingSlv->animSlotAssignedTo->slotIdx; 1.1056 - int32 coreNum = requestingSlv->coreAnimatedBy; 1.1057 - process->slotTaskSlvs[coreNum][slotNum] = newSlotSlv; 1.1058 - 1.1059 - //Fix up requester, to be an extra slave now (but not an ended one) 1.1060 - // because it's active, doesn't go into freeTaskSlvRecycleQ 1.1061 - requestingSlv->typeOfVP = FreeTaskSlv; 1.1062 - requestingSlv->metaTask->taskType = FreeTask; 1.1063 + for( idx = 0; idx < _PRTopEnv->currProcessIdx; idx++) 1.1064 + { 1.1065 + process = _PRTopEnv->processes[ idx ]; 1.1066 + if( process->numEnvsWithWork != 0 ) 1.1067 + { _PRTopEnv->currProcessIdx = idx; 1.1068 + return process; 1.1069 + } 1.1070 + } 1.1071 + //none found 1.1072 + return NULL; 1.1073 } 1.1074 1.1075 - 1.1076 - 1.1077 /*This does: 1.1078 - * 1) searches the semantic environments for one with work ready 1.1079 + * 1) searches the language environments for one with work ready 1.1080 * if finds one, asks its assigner to return work 1.1081 * 2) checks what kind of work: new task, resuming task, resuming slave 1.1082 * if new task, gets the slot slave and assigns task to it and returns slave 1.1083 @@ -861,10 +638,10 @@ 1.1084 * 3) if no work found, then prune former task slaves waiting to be recycled. 1.1085 * If no work and no slaves to prune, check for shutdown conditions. 1.1086 * 1.1087 - * Semantic env keeps its own work in its own structures, and has its own 1.1088 + * language env keeps its own work in its own structures, and has its own 1.1089 * assigner. It chooses 1.1090 * However, include a switch that switches-in an override assigner, which 1.1091 - * sees all the work in all the semantic env's. This is most likely 1.1092 + * sees all the work in all the language env's. This is most likely 1.1093 * generated by static tools and included in the executable. That means it 1.1094 * has to be called via a registered pointer from here. The idea is that 1.1095 * the static tools know which languages are grouped together.. and the 1.1096 @@ -872,7 +649,8 @@ 1.1097 * all the languages in a unified way.. Don't really expect this to happen, 1.1098 * but am making it possible. 1.1099 */ 1.1100 -inline SlaveVP * 1.1101 +inline 1.1102 +SlaveVP * 1.1103 assignWork( PRProcess *process, AnimSlot *slot ) 1.1104 { SlaveVP *returnSlv; 1.1105 int32 coreNum, slotNum; 1.1106 @@ -881,147 +659,75 @@ 1.1107 coreNum = slot->coreSlotIsOn; 1.1108 1.1109 if( process->overrideAssigner != NULL ) 1.1110 - { assignedMetaTask = (*process->overrideAssigner)( process, slot ); 1.1111 - if( assignedMetaTask != NULL ) 1.1112 - { 1.1113 - //have work, so reset Done flag (caused by work generated on other core) 1.1114 -// if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf 1.1115 -// process->coreIsDone[coreNum] = FALSE; //don't just write always 1.1116 - 1.1117 -// switch( assignedMetaTask->taskType ) 1.1118 -// { case GenericSlave: goto AssignSlave; 1.1119 -// case FreeTask: goto AssignSlave; 1.1120 -// case SlotTask: goto AssignNewTask; 1.1121 -// default: PR_int__throw_exception( "unknown task type ret by assigner" ); 1.1122 -// } 1.1123 - //If meta task has a slave attached, then goto assign slave, 1.1124 - // else it's a new task, so goto where assign it to a slot slave 1.1125 - if( assignedMetaTask->slaveAssignedTo != NULL ) 1.1126 - goto AssignSlave; 1.1127 - else 1.1128 - goto AssignNewTask; 1.1129 + { if( process->numEnvsWithWork != 0 ) 1.1130 + { (*process->overrideAssigner)( process, slot ); //calls PR fn that inserts work into slot 1.1131 + goto ReturnAfterAssigningWork; //quit for-loop, cause found work 1.1132 } 1.1133 - else //metaTask is NULL, so no work.. 1.1134 + else 1.1135 goto NoWork; 1.1136 } 1.1137 1.1138 - //If here, then no override assigner, so search semantic envs for work 1.1139 - int32 envIdx, numEnvs; PRSemEnv **semEnvs, *semEnv; SlaveAssigner assigner; 1.1140 - semEnvs = process->semEnvs; 1.1141 - numEnvs = process->numSemEnvs; 1.1142 - for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep semEnvs in hash & array 1.1143 - { semEnv = semEnvs[envIdx]; 1.1144 - if( semEnv->hasWork ) 1.1145 - { assigner = semEnv->slaveAssigner; 1.1146 - assignedMetaTask = (*assigner)( semEnv, slot ); 1.1147 - 1.1148 - //have work, so reset Done flag (caused by work generated on other core) 1.1149 -// if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf 1.1150 -// process->coreIsDone[coreNum] = FALSE; //don't just write always 1.1151 - 1.1152 -// switch( assignedMetaTask->taskType ) 1.1153 -// { case GenericSlave: goto AssignSlave; 1.1154 -// case FreeTask: goto AssignSlave; 1.1155 -// case SlotTask: goto AssignNewTask; 1.1156 -// default: PR_int__throw_exception( "unknown task type ret by assigner" ); 1.1157 -// } 1.1158 - //If meta task has a slave attached, then goto assign slave, 1.1159 - // else it's a new task, so goto where assign it to a slot slave 1.1160 - if( assignedMetaTask->slaveAssignedTo != NULL ) 1.1161 - goto AssignSlave; 1.1162 - else 1.1163 - goto AssignNewTask; 1.1164 + //If here, then no override assigner, so search language envs for work 1.1165 + int32 envIdx, numEnvs; PRLangEnv **langEnvsList, *langEnv; 1.1166 + langEnvsList = process->langEnvsList; 1.1167 + numEnvs = process->numLangEnvs; 1.1168 + for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep langEnvs in hash & array 1.1169 + { langEnv = langEnvsList[envIdx]; 1.1170 + if( langEnv->hasWork ) 1.1171 + { (*langEnv->slaveAssigner)( langEnv, slot ); //assigner calls PR to put slave/task into slot 1.1172 + goto ReturnAfterAssigningWork; //quit for-loop, cause found work 1.1173 + //NOTE: bad search alg -- should start where left off, then wrap around 1.1174 } 1.1175 } 1.1176 - //If reach here, then have searched all semEnv's & none have work.. 1.1177 + //If reach here, then have searched all langEnv's & none have work.. 1.1178 1.1179 - NoWork: 1.1180 - //No work, if reach here.. 1.1181 - { goto ReturnTheSlv; 1.1182 - } 1.1183 - 1.1184 - AssignSlave: //Have a metaTask attached to a slave, so get the slave & ret it 1.1185 - { returnSlv = assignedMetaTask->slaveAssignedTo; 1.1186 - returnSlv->coreAnimatedBy = coreNum; 1.1187 - 1.1188 - goto ReturnTheSlv; 1.1189 - } 1.1190 - 1.1191 - AssignNewTask: //Have a new metaTask that has no slave yet.. assign to slot slv 1.1192 + NoWork: //No work, if end up here.. 1.1193 { 1.1194 - //get the slot slave to assign the task to.. 1.1195 - slotNum = slot->slotIdx; 1.1196 - returnSlv = process->slotTaskSlvs[coreNum][slotNum]; 1.1197 - 1.1198 - //point slave to task's function 1.1199 - PR_int__reset_slaveVP_to_TopLvlFn( returnSlv, 1.1200 - assignedMetaTask->topLevelFn, assignedMetaTask->initData ); 1.1201 - returnSlv->metaTask = assignedMetaTask; 1.1202 - assignedMetaTask->slaveAssignedTo = returnSlv; 1.1203 -// returnSlv->needsTaskAssigned = FALSE; //slot slave is a "Task" slave type 1.1204 - 1.1205 - //have work, so reset Done flag, if was set 1.1206 -// if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf 1.1207 -// process->coreIsDone[coreNum] = FALSE; //don't just write always 1.1208 - 1.1209 - goto ReturnTheSlv; 1.1210 - } 1.1211 - 1.1212 - 1.1213 - ReturnTheSlv: //All paths goto here.. to provide single point for holistic.. 1.1214 - 1.1215 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 1.1216 - if( returnSlv == NULL ) 1.1217 - { returnSlv = process->idleSlv[coreNum][slotNum]; 1.1218 + returnSlv = process->idleSlv[coreNum][slotNum]; 1.1219 1.1220 //things that would normally happen in resume(), but idle VPs 1.1221 // never go there 1.1222 returnSlv->numTimesAssignedToASlot++; //gives each idle unit a unique ID 1.1223 Unit newU; 1.1224 - newU.vp = returnSlv->slaveID; 1.1225 + newU.vp = returnSlv->slaveNum; 1.1226 newU.task = returnSlv->numTimesAssignedToASlot; 1.1227 addToListOfArrays(Unit,newU,process->unitList); 1.1228 1.1229 if (returnSlv->numTimesAssignedToASlot > 1) //make a dependency from prev idle unit 1.1230 { Dependency newD; // to this one 1.1231 - newD.from_vp = returnSlv->slaveID; 1.1232 + newD.from_vp = returnSlv->slaveNum; 1.1233 newD.from_task = returnSlv->numTimesAssignedToASlot - 1; 1.1234 - newD.to_vp = returnSlv->slaveID; 1.1235 + newD.to_vp = returnSlv->slaveNum; 1.1236 newD.to_task = returnSlv->numTimesAssignedToASlot; 1.1237 addToListOfArrays(Dependency, newD ,process->ctlDependenciesList); 1.1238 } 1.1239 + #endif 1.1240 + HOLISTIC__Record_Assigner_end; 1.1241 + return; 1.1242 } 1.1243 - else //have a slave will be assigned to the slot 1.1244 - { //assignSlv->numTimesAssigned++; 1.1245 - //get previous occupant of the slot 1.1246 - Unit prev_in_slot = 1.1247 - process->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum]; 1.1248 - if(prev_in_slot.vp != 0) //if not first slave in slot, make dependency 1.1249 - { Dependency newD; // is a hardware dependency 1.1250 - newD.from_vp = prev_in_slot.vp; 1.1251 - newD.from_task = prev_in_slot.task; 1.1252 - newD.to_vp = returnSlv->slaveID; 1.1253 - newD.to_task = returnSlv->numTimesAssignedToASlot; 1.1254 - addToListOfArrays(Dependency,newD,process->hwArcs); 1.1255 - } 1.1256 - prev_in_slot.vp = returnSlv->slaveID; //make new slave the new previous 1.1257 - prev_in_slot.task = returnSlv->numTimesAssignedToASlot; 1.1258 - process->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum] = 1.1259 - prev_in_slot; 1.1260 + 1.1261 + ReturnAfterAssigningWork: //All paths goto here.. to provide single point for holistic.. 1.1262 + { 1.1263 + HOLISTIC__Record_Assigner_end; 1.1264 + return; 1.1265 } 1.1266 - #endif 1.1267 - 1.1268 - return( returnSlv ); 1.1269 } 1.1270 1.1271 1.1272 -/*In creator, only PR related things happen, and things in the langlet whose 1.1273 + 1.1274 +/*This is first thing called when creating a slave.. it hands off to the 1.1275 + * langlet's creator, then adds updates of its own.. 1.1276 + * 1.1277 + *There's a question of things like lang data, meta tasks, and such.. 1.1278 + *In creator, only PR related things happen, and things for the langlet whose 1.1279 * creator construct was used. 1.1280 - *Other langlet still gets a chance to create semData -- but by registering a 1.1281 - * "createSemData" handler in the semEnv. When a construct of the langlet 1.1282 - * calls "PR__give_sem_data()", if there is no semData for that langlet, 1.1283 - * the PR will call the creator in the langlet's semEnv, place whatever it 1.1284 - * makes as the semData in that slave for that langlet, and return that semData 1.1285 + * 1.1286 + *Other langlets still get a chance to create langData -- but by registering a 1.1287 + * "createLangData" handler in the langEnv. When a construct of the langlet 1.1288 + * calls "PR__give_lang_data()", if there is no langData for that langlet, 1.1289 + * the PR will call the creator in the langlet's langEnv, place whatever it 1.1290 + * makes as the langData in that slave for that langlet, and return that langData 1.1291 * 1.1292 *So, as far as counting things, a langlet is only allowed to count creation 1.1293 * of slaves it creates itself.. may have to change this later.. add a way for 1.1294 @@ -1034,87 +740,92 @@ 1.1295 *PR itself needs to create the slave, then update numLiveSlaves in process, 1.1296 * copy processID from requestor to newly created 1.1297 */ 1.1298 -PRHandle_CreateSlave( PRReqst *req, SlaveVP *requestingSlv ) 1.1299 - { SlaveVP *newSlv; 1.1300 - PRMetaTask metaTask; 1.1301 +inline 1.1302 +void 1.1303 +PRHandle_CreateSlave( PRReqst *req, SlaveVP *slave ) 1.1304 + { SlaveVP *newSlv; 1.1305 PRProcess *process; 1.1306 + PRLangEnv *protoLangEnv; 1.1307 1.1308 - process = requestingSlv->processSlaveIsIn; 1.1309 - newSlv = PR_int__create_slaveVP(); 1.1310 + process = slave->processSlaveIsIn; 1.1311 + protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, req->langMagicNumber ); 1.1312 + 1.1313 +// newSlv = PR_int__create_slave( req->topLevelFn, req->initData ); 1.1314 + 1.1315 + //create slv has diff prototype than standard reqst hdlr 1.1316 + newSlv = 1.1317 + (*req->createHdlr)(req->langReq, slave, PR_int__give_lang_env(protoLangEnv)); 1.1318 + 1.1319 newSlv->typeOfVP = GenericSlv; 1.1320 newSlv->processSlaveIsIn = process; 1.1321 + newSlv->ID = req->ID; 1.1322 process->numLiveGenericSlvs += 1; 1.1323 - metaTask = PR_int__create_slave_meta_task(); 1.1324 - metaTask->taskID = req->ID; 1.1325 -// metaTask->taskType = GenericSlave; 1.1326 - 1.1327 - (*req->handler)( req->semReq, newSlv, requestingSlv, semEnv ); 1.1328 } 1.1329 1.1330 -/*The dissipate handler has to, sdate the number of slaves of the type, within 1.1331 +/*The dissipate handler has to, update the number of slaves of the type, within 1.1332 * the process, and call the langlet handler linked into the request, 1.1333 * and after that returns, then call the PR function that frees the slave state 1.1334 * (or recycles the slave). 1.1335 * 1.1336 *The PR function that frees the slave state has to also free all of the 1.1337 - * semData in the slave.. or else reset all of the semDatas.. by, say, marking 1.1338 - * them, then in PR__give_semData( magicNum ) call the langlet registered 1.1339 - * "resetSemData" Fn. 1.1340 + * langData in the slave.. or else reset all of the langDatas.. by, say, marking 1.1341 + * them, then in PR__give_langData( magicNum ) call the langlet registered 1.1342 + * "resetLangData" Fn. 1.1343 */ 1.1344 -PRHandle_Dissipate( SlaveVP *slave ) 1.1345 +inline 1.1346 +void 1.1347 +PRHandle_Dissipate( PRReqst *req, SlaveVP *slave ) 1.1348 { PRProcess *process; 1.1349 - void *semEnv; 1.1350 + PRLangEnv *protoLangEnv; 1.1351 1.1352 process = slave->processSlaveIsIn; 1.1353 1.1354 //do the language's dissipate handler 1.1355 - semEnv = PR_int__give_sem_env_for_slave( slave, slave->request->langMagicNumber ); 1.1356 - (*slave->request->handler)( slave->request->semReq, slave, semEnv ); 1.1357 + protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, slave->request->langMagicNumber ); 1.1358 + 1.1359 + if(req->handler != NULL) 1.1360 + (*req->handler)( req->langReq, slave, PR_int__give_lang_env(protoLangEnv) ); 1.1361 1.1362 process->numLiveGenericSlvs -= 1; 1.1363 - PR_int__recycle_slave_multilang( requestingSlv ); 1.1364 + PR_int__recycle_slave__ML( slave ); 1.1365 1.1366 //check End Of Process Condition 1.1367 if( process->numLiveTasks == 0 && 1.1368 process->numLiveGenericSlvs == 0 ) 1.1369 - PR_SS__shutdown_process( process ); 1.1370 + PR_SS__shutdown_process__ML( process ); 1.1371 } 1.1372 1.1373 /*Create task is a special form, that has PR behavior in addition to plugin 1.1374 - * behavior. Master calls this first, and then calls the plugin's 1.1375 + * behavior. Master calls this first, and it then calls the plugin's 1.1376 * create task handler. 1.1377 * 1.1378 *Note: the requesting slave must be either generic slave or free task slave 1.1379 */ 1.1380 -inline PRMetaTask * 1.1381 -PRHandle_CreateTask( PRReqst *req, SlaveVP *requestingSlv ) 1.1382 +inline 1.1383 +void 1.1384 +PRHandle_CreateTask( PRReqst *req, SlaveVP *slave ) 1.1385 { PRMetaTask *metaTask; 1.1386 PRProcess *process; 1.1387 - PRLangMetaTask *langMetaTask; 1.1388 - PRSemEnv *semanticEnv; 1.1389 + PRLangEnv *protoLangEnv; 1.1390 + void *task; 1.1391 1.1392 - process = requestingSlv->processSlaveIsIn; 1.1393 - 1.1394 - metaTask = PR_int__create_meta_task( req ); 1.1395 - metaTask->taskID = req->ID; //may be NULL 1.1396 + process = slave->processSlaveIsIn; 1.1397 + 1.1398 + protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, 1.1399 + req->langMagicNumber ); 1.1400 + 1.1401 + //Do the langlet's create-task handler, which keeps the task 1.1402 + // inside the langlet's lang env, but returns the langMetaTask 1.1403 + // so PR can put stuff into the prolog 1.1404 + task = 1.1405 + (*req->createHdlr)(req->langReq, slave, PR_int__give_lang_env(protoLangEnv) ); 1.1406 + metaTask = PR_int__give_prolog_of_task( task ); 1.1407 + metaTask->ID = req->ID; //may be NULL 1.1408 metaTask->topLevelFn = req->topLevelFn; 1.1409 metaTask->initData = req->initData; 1.1410 1.1411 process->numLiveTasks += 1; 1.1412 1.1413 - semanticEnv = PR_int__give_sem_env_for_slave( slave, 1.1414 - req->langMagicNumber ); 1.1415 - 1.1416 - //Do the langlet's create-task handler, which keeps the task 1.1417 - // inside the langlet's sem env, but returns the langMetaTask 1.1418 - // so PR can hook it to the PRMetaTask. 1.1419 - //(Could also do PRMetaTask as a prolog -- make a Fn that takes the size 1.1420 - // of the lang's metaTask, and alloc's that plus the prolog and returns 1.1421 - // ptr to position just above the prolog) 1.1422 - langMetaTask = (*req->handler)(req->semReq, slave, semanticEnv); 1.1423 - metaTask->langMetaTask = langMetaTask; 1.1424 - langMetaTask->protoMetaTask = metaTask; 1.1425 - 1.1426 return; 1.1427 } 1.1428 1.1429 @@ -1125,7 +836,7 @@ 1.1430 * so, here, don't worry about assigning a new task to the slot slave. 1.1431 *For 2, the task's slot slave has been converted to a free task slave, which 1.1432 * now has nothing more to do, so send it to the recycle Q (which includes 1.1433 - * freeing all the semData and meta task structs alloc'd for it). Then 1.1434 + * freeing all the langData and meta task structs alloc'd for it). Then 1.1435 * decrement the live task count and check end condition. 1.1436 * 1.1437 *PR has to update count of live tasks, and check end of process condition. 1.1438 @@ -1141,31 +852,31 @@ 1.1439 * 1.1440 *Note: slave may be either a slot slave or a free task slave. 1.1441 */ 1.1442 -inline void 1.1443 -PRHandle_EndTask( SlaveVP *requestingSlv ) 1.1444 - { void *semEnv; 1.1445 - PRReqst *req; 1.1446 - PRLangMetaTask *langMetaTask; 1.1447 +inline 1.1448 +void 1.1449 +PRHandle_EndTask( PRReqst *req, SlaveVP *requestingSlv ) 1.1450 + { void *langEnv; 1.1451 PRProcess *process; 1.1452 + void *langMetaTask; 1.1453 1.1454 - req = requestingSlv->request; 1.1455 - semEnv = PR_int__give_sem_env_of_req( req, requestingSlv ); //magic num in req 1.1456 - langMetaTask = requestingSlv->metaTask->langMetaTask; 1.1457 + langEnv = PR_int__give_lang_env_of_req__ML( req, requestingSlv ); //magic num in req 1.1458 + langMetaTask = PR_int__give_lang_meta_task_from_slave__ML( requestingSlv, req->langMagicNumber); 1.1459 1.1460 //Do the langlet's request handler 1.1461 - //Want to keep PR structs hidden from plugin, so extract semReq.. 1.1462 - (*req->handler)( langMetaTask, req->semReq, semEnv ); 1.1463 + //Want to keep PR structs hidden from plugin, so extract langReq.. 1.1464 + (*req->handler)( req->langReq, requestingSlv, langEnv ); 1.1465 1.1466 //Now that the langlet's done with it, recycle the slave if it's a freeTaskSlv 1.1467 if( requestingSlv->typeOfVP == FreeTaskSlv ) 1.1468 - PR_int__recycle_slave_multilang( requestingSlv ); 1.1469 + PR_int__recycle_slave__ML( requestingSlv ); 1.1470 1.1471 process->numLiveTasks -= 1; 1.1472 1.1473 //check End Of Process Condition 1.1474 if( process->numLiveTasks == 0 && 1.1475 process->numLiveGenericSlvs == 0 ) 1.1476 - //Tell the core controller to do wakeup of any waiting OS thread 1.1477 - PR_SS__shutdown_process( process ); 1.1478 + { //Tell the core controller to do wakeup of any waiting OS thread 1.1479 + PR_SS__shutdown_process__ML( process ); 1.1480 + } 1.1481 } 1.1482
