Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
comparison AnimationMaster.c @ 269:e6a68e7ea63f
Removed the extra level of core controller -- now only one anim slot and master
called after every work unit
| author | Sean Halle <seanhalle@yahoo.com> |
|---|---|
| date | Mon, 14 Jan 2013 16:10:37 -0800 |
| parents | e5bd470b562b |
| children | 292393c6bef1 |
comparison
equal
deleted
inserted
replaced
| 13:c8131981ef5d | 14:098c51086089 |
|---|---|
| 20 void PR_int__handle_PRServiceReq_SL(SlaveVP *slave); | 20 void PR_int__handle_PRServiceReq_SL(SlaveVP *slave); |
| 21 */ | 21 */ |
| 22 inline void PRHandle_CreateTask( PRReqst *req, SlaveVP *slave ); | 22 inline void PRHandle_CreateTask( PRReqst *req, SlaveVP *slave ); |
| 23 inline void PRHandle_EndTask( PRReqst *req, SlaveVP *slave ); | 23 inline void PRHandle_EndTask( PRReqst *req, SlaveVP *slave ); |
| 24 inline void PRHandle_CreateSlave(PRReqst *req, SlaveVP *slave ); | 24 inline void PRHandle_CreateSlave(PRReqst *req, SlaveVP *slave ); |
| 25 void PRHandle_Dissipate( PRReqst *req, SlaveVP *slave ); | 25 void PRHandle_EndSlave( PRReqst *req, SlaveVP *slave ); |
| 26 | 26 |
| 27 | 27 |
| 28 //inline void masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot ); | 28 //inline void masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot ); |
| 29 inline void masterFunction_MultiLang( AnimSlot *slot ); | 29 inline void masterFunction( AnimSlot *slot ); |
| 30 inline PRProcess * pickAProcess( AnimSlot *slot ); | 30 inline PRProcess * pickAProcess( AnimSlot *slot ); |
| 31 inline SlaveVP * assignWork( PRProcess *process, AnimSlot *slot ); | 31 inline SlaveVP * assignWork( PRProcess *process, AnimSlot *slot ); |
| 32 | 32 |
| 33 /*The animationMaster embodies most of the animator of the language. The | 33 /*The animationMaster embodies most of the animator of the language. The |
| 34 * animator is what emodies the behavior of language constructs. | 34 * animator is what emodies the behavior of language constructs. |
| 76 | 76 |
| 77 //======================== animationMaster ======================== | 77 //======================== animationMaster ======================== |
| 78 //Have three different modes, and the master behavior is different for | 78 //Have three different modes, and the master behavior is different for |
| 79 // each, so jump to the loop that corresponds to the mode. | 79 // each, so jump to the loop that corresponds to the mode. |
| 80 // | 80 // |
| 81 switch(masterEnv->mode) | 81 while(1) |
| 82 { | 82 { MEAS__Capture_Pre_Master_Point |
| 83 /* | 83 for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) |
| 84 { case SingleLang: | 84 { |
| 85 while(1) | 85 currSlot = animSlots[ slotIdx ]; |
| 86 { MEAS__Capture_Pre_Master_Point | 86 |
| 87 for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) | 87 masterFunction( currSlot ); |
| 88 { | 88 } |
| 89 currSlot = animSlots[ slotIdx ]; | 89 MEAS__Capture_Post_Master_Point; |
| 90 | 90 masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master |
| 91 masterFunction_StandaloneSlavesOnly( masterEnv, currSlot ); | 91 flushRegisters(); |
| 92 } | 92 } |
| 93 MEAS__Capture_Post_Master_Point; | 93 } |
| 94 masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master | 94 |
| 95 flushRegisters(); | |
| 96 } | |
| 97 | |
| 98 case SingleLang: | |
| 99 { PRLangEnv *protoLangEnv = _PRTopEnv->protoLangEnv; | |
| 100 while(1) | |
| 101 { MEAS__Capture_Pre_Master_Point | |
| 102 for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) | |
| 103 { | |
| 104 currSlot = animSlots[ slotIdx ]; | |
| 105 | |
| 106 masterFunction_SingleLang( protoLangEnv, currSlot ); | |
| 107 } | |
| 108 MEAS__Capture_Post_Master_Point; | |
| 109 masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master | |
| 110 flushRegisters(); | |
| 111 } | |
| 112 } | |
| 113 */ | |
| 114 case MultiLang: | |
| 115 { while(1) | |
| 116 { MEAS__Capture_Pre_Master_Point | |
| 117 for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) | |
| 118 { | |
| 119 currSlot = animSlots[ slotIdx ]; | |
| 120 | |
| 121 masterFunction_MultiLang( currSlot ); | |
| 122 } | |
| 123 MEAS__Capture_Post_Master_Point; | |
| 124 masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master | |
| 125 flushRegisters(); | |
| 126 } | |
| 127 } | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 | |
| 132 | |
| 133 //===================== The versions of the Animation Master ================= | |
| 134 // | |
| 135 //============================================================================== | |
| 136 | |
| 137 /* 1) This version is for a single language, that has only slaves, no tasks, | |
| 138 * such as Vthread or SSR. | |
| 139 *This version is for when an application has only a single language, and | |
| 140 * that language exposes slaves explicitly (as opposed to a task based | |
| 141 * language like pure dataflow). | |
| 142 * | |
| 143 * | |
| 144 *It scans the animation slots for just-completed slaves. | |
| 145 * Each completed slave has a request in it. So, the master hands each to | |
| 146 * the plugin's request handler (there is only one plugin, because only one | |
| 147 * lang). | |
| 148 *Each request represents a language construct that has been encountered | |
| 149 * by the application code in the slave. Passing the request to the | |
| 150 * request handler is how that language construct's behavior gets invoked. | |
| 151 * The request handler then performs the actions of the construct's | |
| 152 * behavior. So, the request handler encodes the behavior of the | |
| 153 * language's parallelism constructs, and performs that when the master | |
| 154 * hands it a slave containing a request to perform that construct. | |
| 155 * | |
| 156 *On a shared-memory machine, the behavior of parallelism constructs | |
| 157 * equals control, over order of execution of code. Hence, the behavior | |
| 158 * of the language constructs performed by the request handler is to | |
| 159 * choose the order that slaves get animated, and thereby control the | |
| 160 * order that application code in the slaves executes. | |
| 161 * | |
| 162 *To control order of animation of slaves, the request handler has a | |
| 163 * language environment that holds data structures used to hold slaves | |
| 164 * and choose when they're ready to be animated. | |
| 165 * | |
| 166 *Once a slave is marked as ready to be animated by the request handler, | |
| 167 * it is the second plugin function, the Assigner, which chooses the core | |
| 168 * the slave gets assigned to for animation. Hence, the Assigner doesn't | |
| 169 * perform any of the semantic behavior of language constructs, rather | |
| 170 * it gives the language a chance to improve performance. The performance | |
| 171 * of application code is strongly related to communication between | |
| 172 * cores. On shared-memory machines, communication is caused during | |
| 173 * execution of code, by memory accesses, and how much depends on contents | |
| 174 * of caches connected to the core executing the code. So, the placement | |
| 175 * of slaves determines the communication caused during execution of the | |
| 176 * slave's code. | |
| 177 *The point of the Assigner, then, is to use application information during | |
| 178 * execution of the program, to make choices about slave placement onto | |
| 179 * cores, with the aim to put slaves close to caches containing the data | |
| 180 * used by the slave's code. | |
| 181 * | |
| 182 *========================================================================== | |
| 183 *In summary, the animationMaster scans the slots, finds slaves | |
| 184 * just-finished, which hold requests, pass those to the request handler, | |
| 185 * along with the language environment, and the request handler then manages | |
| 186 * the structures in the language env, which controls the order of | |
| 187 * animation of slaves, and so embodies the behavior of the language | |
| 188 * constructs. | |
| 189 *The animationMaster then rescans the slots, offering each empty one to | |
| 190 * the Assigner, along with the language environment. The Assigner chooses | |
| 191 * among the ready slaves in the language env, finding the one best suited | |
| 192 * to be animated by that slot's associated core. | |
| 193 * | |
| 194 *========================================================================== | |
| 195 *Implementation Details: | |
| 196 * | |
| 197 *There is a separate masterVP for each core, but a single language | |
| 198 * environment shared by all cores. Each core also has its own scheduling | |
| 199 * slots, which are used to communicate slaves between animationMaster and | |
| 200 * coreController. There is only one global variable, _PRTopEnv, which | |
| 201 * holds the language env and other things shared by the different | |
| 202 * masterVPs. The request handler and Assigner are registered with | |
| 203 * the animationMaster by the language's init function, and a pointer to | |
| 204 * each is in the _PRTopEnv. (There are also some pthread related global | |
| 205 * vars, but they're only used during init of PR). | |
| 206 *PR gains control over the cores by essentially "turning off" the OS's | |
| 207 * scheduler, using pthread pin-to-core commands. | |
| 208 * | |
| 209 *The masterVPs are created during init, with this animationMaster as their | |
| 210 * top level function. The masterVPs use the same SlaveVP data structure, | |
| 211 * even though they're not slave VPs. | |
| 212 *A "seed slave" is also created during init -- this is equivalent to the | |
| 213 * "main" function in C, and acts as the entry-point to the PR-language- | |
| 214 * based application. | |
| 215 *The masterVPs share a single system-wide master-lock, so only one | |
| 216 * masterVP may be animated at a time. | |
| 217 *The core controllers access _PRTopEnv to get the masterVP, and when | |
| 218 * they start, the slots are all empty, so they run their associated core's | |
| 219 * masterVP. The first of those to get the master lock sees the seed slave | |
| 220 * in the shared language environment, so when it runs the Assigner, that | |
| 221 * returns the seed slave, which the animationMaster puts into a scheduling | |
| 222 * slot then switches to the core controller. That then switches the core | |
| 223 * over to the seed slave, which then proceeds to execute language | |
| 224 * constructs to create more slaves, and so on. Each of those constructs | |
| 225 * causes the seed slave to suspend, switching over to the core controller, | |
| 226 * which eventually switches to the masterVP, which executes the | |
| 227 * request handler, which uses PR primitives to carry out the creation of | |
| 228 * new slave VPs, which are marked as ready for the Assigner, and so on.. | |
| 229 * | |
| 230 *On animation slots, and system behavior: | |
| 231 * A request may linger in an animation slot for a long time while | |
| 232 * the slaves in the other slots are animated. This only becomes a problem | |
| 233 * when such a request is a choke-point in the constraints, and is needed | |
| 234 * to free work for *other* cores. To reduce this occurrence, the number | |
| 235 * of animation slots should be kept low. In balance, having multiple | |
| 236 * animation slots amortizes the overhead of switching to the masterVP and | |
| 237 * executing the animationMaster code, which drives for more than one. In | |
| 238 * practice, the best balance should be discovered by profiling. | |
| 239 */ | |
| 240 /* | |
| 241 void masterFunction_StandaloneSlavesOnly( AnimSlot *slot ) | |
| 242 { | |
| 243 SlaveVP *slave; | |
| 244 PRReqst *req; | |
| 245 PRLangEnv *langEnv = _PRTopEnv->langEnv; | |
| 246 | |
| 247 | |
| 248 //======================== animationMaster ======================== | |
| 249 | |
| 250 //Check if newly-done slave in slot, which will need request handled | |
| 251 if( slot->workIsDone ) | |
| 252 { slot->workIsDone = FALSE; | |
| 253 slot->needsWorkAssigned = TRUE; | |
| 254 | |
| 255 | |
| 256 HOLISTIC__Record_AppResponder_start; | |
| 257 MEAS__startReqHdlr; | |
| 258 //process the request made by the slave (held inside slave struc) | |
| 259 slave = slot->slaveAssignedToSlot; | |
| 260 req = slave->request; | |
| 261 | |
| 262 //Handle task create and end first -- they're special cases.. | |
| 263 switch( req->reqType ) | |
| 264 { case SlvCreate: PRHandle_CreateSlave( slave ); break; | |
| 265 case SlvDissipate: PRHandle_Dissipate( slave ); break; | |
| 266 case Service: PR_int__handle_PRServiceReq( slave ); break; //resume into PR's own language env | |
| 267 case Hardware: //for future expansion | |
| 268 case IO: //for future expansion | |
| 269 case OSCall: //for future expansion | |
| 270 PR_int__throw_exception("Not implemented"); break; | |
| 271 case Language: //normal lang request | |
| 272 { | |
| 273 (*langEnv->requestHdlr)( req->langReq, slave, langEnv ); | |
| 274 } | |
| 275 } | |
| 276 HOLISTIC__Record_AppResponder_end; | |
| 277 MEAS__endReqHdlr; | |
| 278 } | |
| 279 //If slot empty, hand to Assigner to fill with a slave | |
| 280 if( slot->needsWorkAssigned ) | |
| 281 { //Call plugin's Assigner to give slot a new slave | |
| 282 HOLISTIC__Record_Assigner_start; | |
| 283 | |
| 284 if( langEnv->hasWork ) | |
| 285 { (*langEnv->slaveAssigner)( langEnv, slot ); //calls PR fn that inserts work into slot | |
| 286 goto ReturnAfterAssigningWork; //quit for-loop, cause found work | |
| 287 } | |
| 288 else | |
| 289 goto NoWork; | |
| 290 } | |
| 291 | |
| 292 NoWork: | |
| 293 //No work, if reach here.. | |
| 294 { | |
| 295 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC | |
| 296 coreNum = slot->coreSlotIsOn; | |
| 297 returnSlv = process->idleSlv[coreNum][slotNum]; | |
| 298 | |
| 299 //things that would normally happen in resume(), but idle VPs | |
| 300 // never go there | |
| 301 returnSlv->numTimesAssignedToASlot++; //gives each idle unit a unique ID | |
| 302 Unit newU; | |
| 303 newU.vp = returnSlv->slaveNum; | |
| 304 newU.task = returnSlv->numTimesAssignedToASlot; | |
| 305 addToListOfArrays(Unit,newU,process->unitList); | |
| 306 | |
| 307 if (returnSlv->numTimesAssignedToASlot > 1) //make a dependency from prev idle unit | |
| 308 { Dependency newD; // to this one | |
| 309 newD.from_vp = returnSlv->slaveNum; | |
| 310 newD.from_task = returnSlv->numTimesAssignedToASlot - 1; | |
| 311 newD.to_vp = returnSlv->slaveNum; | |
| 312 newD.to_task = returnSlv->numTimesAssignedToASlot; | |
| 313 addToListOfArrays(Dependency, newD ,process->ctlDependenciesList); | |
| 314 } | |
| 315 #endif | |
| 316 HOLISTIC__Record_Assigner_end; | |
| 317 return; | |
| 318 } | |
| 319 | |
| 320 ReturnAfterAssigningWork: //All paths goto here.. to provide single point for holistic.. | |
| 321 { | |
| 322 HOLISTIC__Record_Assigner_end; | |
| 323 return; | |
| 324 } | |
| 325 } | |
| 326 */ | |
| 327 | |
| 328 | |
| 329 /*This is the master when just multi-lang, but not multi-process mode is on. | |
| 330 * This version has to handle both tasks and slaves, and do extra work of | |
| 331 * looking up the language env and handlers to use, for each completed bit of | |
| 332 * work. | |
| 333 *It also has to search through the language envs to find one with work, | |
| 334 * then ask that env's assigner to return a unit of that work. | |
| 335 * | |
| 336 *The language is written to startup in the same way as if it were the only | |
| 337 * language in the app, and it operates in the same way, | |
| 338 * the only difference between single language and multi-lang is here, in the | |
| 339 * master. | |
| 340 *This invisibility to mode is why the language has to use registration calls | |
| 341 * for everything during startup -- those calls do different things depending | |
| 342 * on whether it's single-language or multi-language mode. | |
| 343 * | |
| 344 *In this version of the master, work can either be a task or a resumed slave | |
| 345 *Having two cases makes this logic complex.. can be finishing either, and | |
| 346 * then the next available work may be either.. so really have two distinct | |
| 347 * loops that are inter-twined.. | |
| 348 * | |
| 349 *Some special cases: | |
| 350 * A task-end is a special case for a few reasons (below). | |
| 351 * A task-end can't block a slave (can't cause it to "logically suspend") | |
| 352 * A task available for work can only be assigned to a special slave, which | |
| 353 * has been set aside for doing tasks, one such task-slave is always | |
| 354 * assigned to each slot. So, when a task ends, a new task is assigned to | |
| 355 * that slot's task-slave right away. | |
| 356 * But if no tasks are available, then have to switch over to looking at | |
| 357 * slaves to find one ready to resume, to find work for the slot. | |
| 358 * If a task just suspends, not ends, then its task-slave is no longer | |
| 359 * available to take new tasks, so a new task-slave has to be assigned to | |
| 360 * that slot. Then the slave of the suspended task is turned into a free | |
| 361 * task-slave and request handling is done on it as if it were a slave | |
| 362 * that suspended. | |
| 363 * After request handling, do the same sequence of looking for a task to be | |
| 364 * work, and if none, look for a slave ready to resume, as work for the slot. | |
| 365 * If a slave suspends, handle its request, then look for work.. first for a | |
| 366 * task to assign, and if none, slaves ready to resume. | |
| 367 * Another special case is when task-end is done on a free task-slave.. in | |
| 368 * that case, the slave has no more work and no way to get more.. so place | |
| 369 * it into a recycle queue. | |
| 370 * If no work is found of either type, then do a special thing to prune down | |
| 371 * the extra slaves in the recycle queue, just so don't get too many.. | |
| 372 * | |
| 373 *The multi-lang thing complicates matters.. | |
| 374 * | |
| 375 *For request handling, it means have to first fetch the language environment | |
| 376 * of the language, and then do the request handler pointed to by that | |
| 377 * language env. | |
| 378 *For assigning, things get more complex because of competing goals.. One | |
| 379 * goal is for language specific stuff to be used during assignment, so | |
| 380 * assigner can make higher quality decisions.. but with multiple languages, | |
| 381 * which only get mixed in the application, the assigners can't be written | |
| 382 * with knowledge of each other. So, they can only make localized decisions, | |
| 383 * and so different language's assigners may interfere with each other.. | |
| 384 * | |
| 385 *So, have some possibilities available: | |
| 386 *1) can have a fixed scheduler in the proto-runtime, that all the | |
| 387 * languages give their work to.. (but then lose language-specific info, | |
| 388 * there is a standard PR format for assignment info, and the langauge | |
| 389 * attaches this to the work-unit when it gives it to PR.. also have issue | |
| 390 * with HWSim, which uses a priority Q instead of FIFO, and requests can | |
| 391 * "undo" previous work put in, so request handlers need way to manipulate | |
| 392 * the work-holding Q..) (this might be fudgeable with | |
| 393 * HWSim, if the master did a lang-supplied callback each time it assigns a | |
| 394 * unit to a slot.. then HWSim can keep exactly one unit of work in PR's | |
| 395 * queue at a time.. but this is quite hack-like.. or perhaps HWSim supplies | |
| 396 * a task-end handler that kicks the next unit of work from HWSim internal | |
| 397 * priority queue, over to PR readyQ) | |
| 398 *2) can have each language have its own language env, that holds its own | |
| 399 * work, which is assigned by its own assigner.. then the master searches | |
| 400 * through all the language envs to find one with work and asks it give work.. | |
| 401 * (this has downside of blinding assigners to each other.. but does work | |
| 402 * for HWSim case) | |
| 403 *3) could make PR have a different readyQ for each core, and ask the lang | |
| 404 * to put work to the core it prefers.. but the work may be moved by PR if | |
| 405 * needed, say if one core idles for too long. This is a hybrid approach, | |
| 406 * letting the language decide which core, but PR keeps the work and does it | |
| 407 * FIFO style.. (this might als be fudgeable with HWSim, in similar fashion, | |
| 408 * but it would be complicated by having to track cores separately) | |
| 409 * | |
| 410 *Choosing 2, to keep compatibility with single-lang mode.. it allows the same | |
| 411 * assigner to be used for single-lang as for multi-lang.. the overhead of | |
| 412 * the extra master search for work is part of the price of the flexibility, | |
| 413 * but should be fairly small.. takes the first env that has work available, | |
| 414 * and whatever it returns is assigned to the slot.. | |
| 415 * | |
| 416 *As a hybrid, giving an option for a unified override assigner to be registered | |
| 417 * and used.. This allows something like a static analysis to detect | |
| 418 * which languages are grouped together, and then analyze the pattern of | |
| 419 * construct calls, and generate a custom assigner that uses info from all | |
| 420 * the languages in a unified way.. Don't really expect this to happen, | |
| 421 * but making it possible. | |
| 422 */ | |
| 423 /* | |
| 424 inline | |
| 425 void | |
| 426 masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot ) | |
| 427 { //Scan the animation slots | |
| 428 SlaveVP *slave; | |
| 429 PRReqst *req; | |
| 430 | |
| 431 //Check if newly-done slave in slot, which will need request handled | |
| 432 if( slot->workIsDone ) | |
| 433 { slot->workIsDone = FALSE; | |
| 434 slot->needsWorkAssigned = TRUE; | |
| 435 | |
| 436 HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot | |
| 437 MEAS__startReqHdlr; | |
| 438 | |
| 439 | |
| 440 //process the request made by the slave (held inside slave struc) | |
| 441 slave = slot->slaveAssignedToSlot; | |
| 442 req = slave->request; | |
| 443 | |
| 444 //If the requesting slave is a slot slave, and request is not | |
| 445 // task-end, then turn it into a free task slave. | |
| 446 if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd ) | |
| 447 PR_int__replace_with_new_slot_slv( slave ); | |
| 448 | |
| 449 //Handle task create and end first -- they're special cases.. | |
| 450 switch( req->reqType ) | |
| 451 { case TaskEnd: | |
| 452 { //do PR handler, which calls lang's hdlr and does recycle of | |
| 453 // free task slave if needed -- PR handler checks for free task Slv | |
| 454 PRHandle_EndTask_SL( slave ); break; | |
| 455 } | |
| 456 case TaskCreate: | |
| 457 { //Do PR's create-task handler, which calls the lang's hdlr | |
| 458 // PR handler checks for free task Slv | |
| 459 PRHandle_CreateTask_SL( slave ); break; | |
| 460 } | |
| 461 case SlvCreate: PRHandle_CreateSlave_SL( slave ); break; | |
| 462 case SlvDissipate: PRHandle_Dissipate_SL( slave ); break; | |
| 463 case Service: PR_int__handle_PRServiceReq_SL( slave ); break; //resume into PR's own language env | |
| 464 case Hardware: //for future expansion | |
| 465 case IO: //for future expansion | |
| 466 case OSCall: //for future expansion | |
| 467 PR_int__throw_exception("Not implemented", slave, NULL); break; | |
| 468 case Language: //normal lang request | |
| 469 { | |
| 470 (*protoLangEnv->requestHdlr)( req->langReq, slave, (void*)PR_int__give_lang_env(protoLangEnv )); | |
| 471 } | |
| 472 } | |
| 473 | |
| 474 MEAS__endReqHdlr; | |
| 475 HOLISTIC__Record_AppResponder_end; | |
| 476 } //if have request to be handled | |
| 477 | |
| 478 //If slot empty, hand to Assigner to fill with a slave | |
| 479 if( slot->needsWorkAssigned ) | |
| 480 { //Call plugin's Assigner to give slot a new slave | |
| 481 HOLISTIC__Record_Assigner_start; | |
| 482 | |
| 483 if( protoLangEnv->hasWork ) | |
| 484 { (*protoLangEnv->slaveAssigner)( protoLangEnv, slot ); //calls PR fn that inserts work into slot | |
| 485 goto ReturnAfterAssigningWork; //quit for-loop, cause found work | |
| 486 } | |
| 487 else | |
| 488 goto NoWork; | |
| 489 } | |
| 490 | |
| 491 NoWork: | |
| 492 //No work, if reach here.. | |
| 493 { | |
| 494 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC | |
| 495 coreNum = slot->coreSlotIsOn; | |
| 496 returnSlv = process->idleSlv[coreNum][slotNum]; | |
| 497 | |
| 498 //things that would normally happen in resume(), but idle VPs | |
| 499 // never go there | |
| 500 returnSlv->numTimesAssignedToASlot++; //gives each idle unit a unique ID | |
| 501 Unit newU; | |
| 502 newU.vp = returnSlv->slaveNum; | |
| 503 newU.task = returnSlv->numTimesAssignedToASlot; | |
| 504 addToListOfArrays(Unit,newU,process->unitList); | |
| 505 | |
| 506 if (returnSlv->numTimesAssignedToASlot > 1) //make a dependency from prev idle unit | |
| 507 { Dependency newD; // to this one | |
| 508 newD.from_vp = returnSlv->slaveNum; | |
| 509 newD.from_task = returnSlv->numTimesAssignedToASlot - 1; | |
| 510 newD.to_vp = returnSlv->slaveNum; | |
| 511 newD.to_task = returnSlv->numTimesAssignedToASlot; | |
| 512 addToListOfArrays(Dependency, newD ,process->ctlDependenciesList); | |
| 513 } | |
| 514 #endif | |
| 515 HOLISTIC__Record_Assigner_end; | |
| 516 return; | |
| 517 } | |
| 518 | |
| 519 ReturnAfterAssigningWork: //All paths goto here.. to provide single point for holistic.. | |
| 520 { | |
| 521 HOLISTIC__Record_Assigner_end; | |
| 522 return; | |
| 523 } | |
| 524 } | |
| 525 */ | |
| 526 | 95 |
| 527 inline | 96 inline |
| 528 void | 97 void |
| 529 masterFunction_MultiLang( AnimSlot *slot ) | 98 masterFunction( AnimSlot *slot ) |
| 530 { //Scan the animation slots | 99 { //Scan the animation slots |
| 531 int32 magicNumber; | 100 int32 magicNumber; |
| 532 SlaveVP *slave; | 101 SlaveVP *slave; |
| 533 PRLangEnv *langEnv; | 102 PRLangEnv *langEnv; |
| 534 PRReqst *req; | 103 PRReqst *req; |
| 535 RequestHandler requestHandler; | |
| 536 PRProcess *process; | 104 PRProcess *process; |
| 537 | 105 |
| 538 //Check if newly-done slave in slot, which will need request handled | 106 //Check if newly-done slave in slot, which will need request handled |
| 539 if( slot->workIsDone ) | 107 if( slot->workIsDone ) |
| 540 { slot->workIsDone = FALSE; | 108 { slot->workIsDone = FALSE; |
| 564 { //Do PR's create-task handler, which calls the lang's hdlr | 132 { //Do PR's create-task handler, which calls the lang's hdlr |
| 565 // PR handler checks for free task Slv | 133 // PR handler checks for free task Slv |
| 566 PRHandle_CreateTask( req, slave ); break; | 134 PRHandle_CreateTask( req, slave ); break; |
| 567 } | 135 } |
| 568 case SlvCreate: PRHandle_CreateSlave( req, slave ); break; | 136 case SlvCreate: PRHandle_CreateSlave( req, slave ); break; |
| 569 case SlvDissipate: PRHandle_Dissipate( req, slave ); break; | 137 case SlvDissipate: PRHandle_EndSlave( req, slave ); break; |
| 570 case Service: PR_int__handle_PRServiceReq( slave ); break; //resume into PR's own language env | 138 case Service: PR_int__handle_PRServiceReq( slave ); break; //resumes into Service lang env |
| 571 case Hardware: //for future expansion | 139 case Hardware: //for future expansion |
| 572 case IO: //for future expansion | 140 case IO: //for future expansion |
| 573 case OSCall: //for future expansion | 141 case OSCall: //for future expansion |
| 574 PR_int__throw_exception("Not implemented", slave, NULL); break; | 142 PR_int__throw_exception("Not implemented", slave, NULL); break; |
| 575 case Language: //normal lang request | 143 case Language: //normal lang request |
| 702 newD.to_task = returnSlv->numTimesAssignedToASlot; | 270 newD.to_task = returnSlv->numTimesAssignedToASlot; |
| 703 addToListOfArrays(Dependency, newD ,process->ctlDependenciesList); | 271 addToListOfArrays(Dependency, newD ,process->ctlDependenciesList); |
| 704 } | 272 } |
| 705 #endif | 273 #endif |
| 706 HOLISTIC__Record_Assigner_end; | 274 HOLISTIC__Record_Assigner_end; |
| 707 return; | 275 return FALSE; |
| 708 } | 276 } |
| 709 | 277 |
| 710 ReturnAfterAssigningWork: //All paths goto here.. to provide single point for holistic.. | 278 ReturnAfterAssigningWork: //All paths goto here.. to provide single point for holistic.. |
| 711 { | 279 { |
| 712 HOLISTIC__Record_Assigner_end; | 280 HOLISTIC__Record_Assigner_end; |
| 713 return; | 281 return TRUE; |
| 714 } | 282 } |
| 715 } | 283 } |
| 716 | 284 |
| 717 | 285 |
| 718 | 286 |
| 772 * them, then in PR__give_langData( magicNum ) call the langlet registered | 340 * them, then in PR__give_langData( magicNum ) call the langlet registered |
| 773 * "resetLangData" Fn. | 341 * "resetLangData" Fn. |
| 774 */ | 342 */ |
| 775 inline | 343 inline |
| 776 void | 344 void |
| 777 PRHandle_Dissipate( PRReqst *req, SlaveVP *slave ) | 345 PRHandle_EndSlave( PRReqst *req, SlaveVP *slave ) |
| 778 { PRProcess *process; | 346 { PRProcess *process; |
| 779 PRLangEnv *protoLangEnv; | 347 PRLangEnv *protoLangEnv; |
| 780 | 348 |
| 781 process = slave->processSlaveIsIn; | 349 process = slave->processSlaveIsIn; |
| 782 | 350 |
