Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
changeset 268:e5bd470b562b Dev_ML
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 |
files | AnimationMaster.c CoreController.c Defines/MEAS__macros_to_be_moved_to_langs.h Defines/PR_defs.h Defines/PR_defs__HW_constants.h HW_Dependent_Primitives/PR__HW_measurement.h HW_Dependent_Primitives/PR__MetaInfo.c HW_Dependent_Primitives/PR__primitives.h HW_Dependent_Primitives/PR__primitives_asm.s PR.h PR__PI.c PR__PI.h PR__SS.c PR__WL.c PR__WL.h PR__int.c PR__int.h PR__structs.h PR_primitive_data_types.h Services_Offered_by_PR/Measurement_and_Stats/MEAS__macros.h Services_Offered_by_PR/Memory_Handling/vmalloc.c |
diffstat | 21 files changed, 2584 insertions(+), 1908 deletions(-) [+] |
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
2.1 --- a/CoreController.c Sun Nov 04 18:39:28 2012 -0800 2.2 +++ b/CoreController.c Mon Jan 14 15:31:23 2013 -0800 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright 2010 OpenSourceStewardshipFoundation 2.6 + * Copyright 2010 OpenSourceResearchInstitute 2.7 * 2.8 * Licensed under BSD 2.9 */ 2.10 @@ -113,12 +113,12 @@ 2.11 2.12 //make sure the controllers all start at same time, by making them wait 2.13 pthread_mutex_lock( &suspendLock ); 2.14 - while( !(_PRTopEnv->setupComplete) ) 2.15 + while( !(_PRTopEnv->firstProcessReady) ) 2.16 { pthread_cond_wait( &suspendCond, &suspendLock ); 2.17 } 2.18 pthread_mutex_unlock( &suspendLock ); 2.19 2.20 - HOLISTIC__CoreCtrl_Setup; 2.21 + HOLISTIC__CoreCtrl_Setup; 2.22 2.23 DEBUG__printf1(TRUE, "started coreCtrlr", thisCoresIdx ); 2.24 2.25 @@ -219,7 +219,7 @@ 2.26 terminateCoreCtlr(SlaveVP *currSlv) 2.27 { 2.28 //first, free shutdown Slv that jumped here, then end the pthread 2.29 - PR_int__dissipate_slaveVP( currSlv ); 2.30 + PR_int__dissipate_slaveVP__SL( currSlv ); 2.31 pthread_exit( NULL ); 2.32 } 2.33
3.1 --- a/Defines/MEAS__macros_to_be_moved_to_langs.h Sun Nov 04 18:39:28 2012 -0800 3.2 +++ b/Defines/MEAS__macros_to_be_moved_to_langs.h Mon Jan 14 15:31:23 2013 -0800 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright 2009 OpenSourceStewardshipFoundation.org 3.6 + * Copyright 2009 OpenSourceResearchInstitute.org 3.7 * Licensed under GNU General Public License version 2 3.8 * 3.9 * Author: seanhalle@yahoo.com
4.1 --- a/Defines/PR_defs.h Sun Nov 04 18:39:28 2012 -0800 4.2 +++ b/Defines/PR_defs.h Mon Jan 14 15:31:23 2013 -0800 4.3 @@ -1,5 +1,5 @@ 4.4 /* 4.5 - * Copyright 2009 OpenSourceStewardshipFoundation.org 4.6 + * Copyright 2009 OpenSourceResearchInstitute.org 4.7 * Licensed under GNU General Public License version 2 4.8 * 4.9 * Author: seanhalle@yahoo.com
5.1 --- a/Defines/PR_defs__HW_constants.h Sun Nov 04 18:39:28 2012 -0800 5.2 +++ b/Defines/PR_defs__HW_constants.h Mon Jan 14 15:31:23 2013 -0800 5.3 @@ -1,5 +1,5 @@ 5.4 /* 5.5 - * Copyright 2012 OpenSourceStewardshipFoundation 5.6 + * Copyright 2012 OpenSourceResearchInstitute 5.7 * Licensed under BSD 5.8 * 5.9 * Author: seanhalle@yahoo.com 5.10 @@ -20,9 +20,9 @@ 5.11 // when work-stealing, can make bigger, at risk of losing cache affinity 5.12 #define NUM_ANIM_SLOTS 1 5.13 5.14 - //number of PRSemEnv structs created inside a process -- can't start more 5.15 + //number of PRLangEnv structs created inside a process -- can't start more 5.16 // than this many langlets inside a single process 5.17 -#define NUM_SEM_ENVS_IN_PROCESS 64 5.18 +#define NUM_IN_COLLECTION 64 5.19 5.20 //These are for backoff inside core-loop, which reduces lock contention 5.21 #define NUM_REPS_W_NO_WORK_BEFORE_YIELD 10
6.1 --- a/HW_Dependent_Primitives/PR__HW_measurement.h Sun Nov 04 18:39:28 2012 -0800 6.2 +++ b/HW_Dependent_Primitives/PR__HW_measurement.h Mon Jan 14 15:31:23 2013 -0800 6.3 @@ -1,5 +1,5 @@ 6.4 /* 6.5 - * Copyright 2009 OpenSourceStewardshipFoundation.org 6.6 + * Copyright 2009 OpenSourceResearchInstitute.org 6.7 * Licensed under GNU General Public License version 2 6.8 * 6.9 * Author: seanhalle@yahoo.com
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/HW_Dependent_Primitives/PR__MetaInfo.c Mon Jan 14 15:31:23 2013 -0800 7.3 @@ -0,0 +1,26 @@ 7.4 +#include <unistd.h> 7.5 +#include <fcntl.h> 7.6 +#include <linux/types.h> 7.7 +#include <linux/perf_event.h> 7.8 +#include <errno.h> 7.9 +#include <sys/syscall.h> 7.10 +#include <linux/prctl.h> 7.11 + 7.12 +#include "../PR.h" 7.13 + 7.14 +void PR_SS__set_meta_info() 7.15 + { 7.16 + garbage__delete; 7.17 + 7.18 + _PRTopEnv->metaInfo = PR_int__malloc( sizeof(PRSysMetaInfo) ); 7.19 + //Meta info gets set by calls from the language during its init, 7.20 + // and info registered by calls from inside the application 7.21 + _PRTopEnv->metaInfo->assignerInfo; 7.22 + 7.23 + //-------------------------- 7.24 + //Application 7.25 + j += sprintf(buffer+j, "#\n# >> Application <<\n"); 7.26 + j += sprintf(buffer+j, "# Name: %s\n", _PRTopEnv->metaInfo->appInfo); 7.27 + j += sprintf(buffer+j, "# Data Set:\n%s\n",_PRTopEnv->metaInfo->inputSet); 7.28 + 7.29 + } 7.30 \ No newline at end of file
8.1 --- a/HW_Dependent_Primitives/PR__primitives.h Sun Nov 04 18:39:28 2012 -0800 8.2 +++ b/HW_Dependent_Primitives/PR__primitives.h Mon Jan 14 15:31:23 2013 -0800 8.3 @@ -1,5 +1,5 @@ 8.4 /* 8.5 - * Copyright 2009 OpenSourceStewardshipFoundation.org 8.6 + * Copyright 2009 OpenSourceResearchInstitute.org 8.7 * Licensed under GNU General Public License version 2 8.8 * 8.9 * Author: seanhalle@yahoo.com
9.1 --- a/HW_Dependent_Primitives/PR__primitives_asm.s Sun Nov 04 18:39:28 2012 -0800 9.2 +++ b/HW_Dependent_Primitives/PR__primitives_asm.s Mon Jan 14 15:31:23 2013 -0800 9.3 @@ -164,7 +164,7 @@ 9.4 movq 0x20(%rdi), %rsp #restore stack pointer 9.5 movq 0x18(%rdi), %rbp #restore frame pointer 9.6 #argument is in %rdi 9.7 - call PR_int__dissipate_slaveVP 9.8 + call PR_int__dissipate_slaveVP__SL 9.9 movq %rbp , %rsp #goto the coreCtlrs stack 9.10 pop %rbp #restore the old framepointer 9.11 ret #return from core controller
10.1 --- a/PR.h Sun Nov 04 18:39:28 2012 -0800 10.2 +++ b/PR.h Mon Jan 14 15:31:23 2013 -0800 10.3 @@ -1,5 +1,5 @@ 10.4 /* 10.5 - * Copyright 2009 OpenSourceStewardshipFoundation.org 10.6 + * Copyright 2009 OpenSourceResearchInstitute.org 10.7 * Licensed under GNU General Public License version 2 10.8 * 10.9 * Author: seanhalle@yahoo.com 10.10 @@ -30,25 +30,7 @@ 10.11 10.12 //================================ Typedefs ================================= 10.13 // 10.14 -typedef unsigned long long TSCount; 10.15 - 10.16 -typedef struct _AnimSlot AnimSlot; 10.17 -typedef struct _PRReqst PRReqst; 10.18 -typedef struct _SlaveVP SlaveVP; 10.19 -typedef struct _MasterVP MasterVP; 10.20 -typedef struct _IntervalProbe IntervalProbe; 10.21 -typedef struct _PRMetaTask PRMetaTask; 10.22 - 10.23 - 10.24 -typedef SlaveVP *(*SlaveAssigner) ( void *, AnimSlot*); //semEnv, slot for HW info 10.25 -typedef void (*RequestHandler) ( SlaveVP *, void * ); //prWReqst, semEnv 10.26 -typedef void (*IndivReqHandler)( SlaveVP *, void * ); //prWReqst, semEnv 10.27 -typedef void (*TopLevelFnPtr) ( void *, SlaveVP * ); //initData, animSlv 10.28 -typedef void TopLevelFn ( void *, SlaveVP * ); //initData, animSlv 10.29 -typedef void (*ResumeSlvFnPtr) ( SlaveVP *, void * ); 10.30 - //=========== MEASUREMENT STUFF ========== 10.31 - MEAS__Insert_Counter_Handler 10.32 - //======================================== 10.33 +#include "PR__structs.h" 10.34 10.35 //============================ HW Dependent Fns ================================ 10.36 10.37 @@ -56,338 +38,9 @@ 10.38 #include "HW_Dependent_Primitives/PR__primitives.h" 10.39 10.40 10.41 -//============= Request Related =========== 10.42 -// 10.43 - 10.44 -enum PRReqstType //avoid starting enums at 0, for debug reasons 10.45 - { 10.46 - TaskCreate = 1, 10.47 - TaskEnd, 10.48 - SlvCreate, 10.49 - SlvDissipate, 10.50 - Language, 10.51 - Service, //To invoke a PR provided equivalent of a language request (ex: probe) 10.52 - Hardware, 10.53 - IO, 10.54 - OSCall 10.55 - }; 10.56 - 10.57 -struct _PRReqst 10.58 - { 10.59 - enum PRReqstType reqType;//used for special forms that have PR behavior 10.60 - void *semReq; 10.61 - PRProcess *processReqIsIn; 10.62 - int32 langMagicNumber; 10.63 - TopLevelFn topLevelFn; 10.64 - void *initData; 10.65 - int32 *ID; 10.66 - 10.67 - //The request handling structure is a bit messy.. for special forms, 10.68 - // such as create and dissipate, the language inserts pointer to handler 10.69 - // fn directly into the request.. might change to this for all requests 10.70 - IndivReqHandler handler; //pointer to handler fn for create, dissip, etc 10.71 - 10.72 - PRReqst *nextReqst; 10.73 - }; 10.74 -//PRReqst 10.75 - 10.76 -enum PRServReqType //These are equivalent to semantic requests, but for 10.77 - { // PR's services available directly to app, like OS 10.78 - make_probe = 1, // and probe services -- like a PR-wide built-in lang 10.79 - throw_excp, 10.80 - openFile, 10.81 - otherIO 10.82 - }; 10.83 - 10.84 -typedef struct 10.85 - { enum PRServReqType reqType; 10.86 - SlaveVP *requestingSlv; 10.87 - char *nameStr; //for create probe 10.88 - char *msgStr; //for exception 10.89 - void *exceptionData; 10.90 - } 10.91 -PRServReq; 10.92 - 10.93 - 10.94 -//==================== Core data structures =================== 10.95 - 10.96 -typedef struct 10.97 - { 10.98 - //for future expansion 10.99 - } 10.100 -SlotPerfInfo; 10.101 - 10.102 -struct _AnimSlot 10.103 - { 10.104 - int workIsDone; 10.105 - int needsWorkAssigned; 10.106 - SlaveVP *slaveAssignedToSlot; 10.107 - 10.108 - int slotIdx; //needed by Holistic Model's data gathering 10.109 - int coreSlotIsOn; 10.110 - SlotPerfInfo *perfInfo; //used by assigner to pick best slave for core 10.111 - }; 10.112 -//AnimSlot 10.113 - 10.114 -enum VPtype 10.115 - { SlotTaskSlv = 1,//Slave tied to an anim slot, only animates tasks 10.116 - FreeTaskSlv, //When a suspended task ends, the slave becomes this 10.117 - GenericSlv, //the VP is explicitly seen in the app code, or task suspends 10.118 - Master, 10.119 - Shutdown, 10.120 - Idle 10.121 - }; 10.122 - 10.123 -/*This structure embodies the state of a slaveVP. It is reused for masterVP 10.124 - * and shutdownVPs. 10.125 - */ 10.126 -struct _SlaveVP 10.127 - { //The offsets of these fields are hard-coded into assembly 10.128 - void *stackPtr; //save the core's stack ptr when suspend 10.129 - void *framePtr; //save core's frame ptr when suspend 10.130 - void *resumeInstrPtr; //save core's program-counter when suspend 10.131 - void *coreCtlrFramePtr; //restore before jmp back to core controller 10.132 - void *coreCtlrStackPtr; //restore before jmp back to core controller 10.133 - 10.134 - //============ below this, no fields are used in asm ============= 10.135 - 10.136 - void *startOfStack; //used to free, and to point slave to Fn 10.137 - PRProcess *processSlaveIsIn; 10.138 - PRMetaTask *metaTask; 10.139 - enum VPtype typeOfVP; //Slave vs Master vs Shutdown.. 10.140 - int slaveID; //each slave given a globally unique ID 10.141 - int coreAnimatedBy; 10.142 - int numTimesAssignedToASlot; //Each assign is for one work-unit, so is an ID 10.143 - //note, a scheduling decision is uniquely identified by the triple: 10.144 - // <slaveID, coreAnimatedBy, numTimesAssignedToASlot> -- used in record & replay 10.145 - 10.146 - //for comm -- between master and coreCtlr & btwn wrapper lib and plugin 10.147 - AnimSlot *animSlotAssignedTo; 10.148 - PRReqst *request; //wrapper lib puts in requests, plugin takes out 10.149 - void *dataRetFromReq;//Return vals from plugin to Wrapper Lib 10.150 - 10.151 - //For language specific data that needs to be in the slave 10.152 - void *semanticData; //Lang saves lang-specific things in slave here 10.153 - 10.154 - //Task related stuff 10.155 -// bool needsTaskAssigned; 10.156 - 10.157 - //=========== MEASUREMENT STUFF ========== 10.158 - MEAS__Insert_Meas_Fields_into_Slave; 10.159 - float64 createPtInSecs; //time VP created, in seconds 10.160 - //======================================== 10.161 - }; 10.162 -//SlaveVP 10.163 - 10.164 - 10.165 -/* The one and only global variable, holds many odds and ends 10.166 - */ 10.167 -typedef struct 10.168 - { //The offsets of these fields are hard-coded into assembly 10.169 - void *coreCtlrReturnPt; //offset to this field used in asm 10.170 - int8 falseSharePad1[256 - sizeof(void*)]; 10.171 - int32 masterLock; //offset to this field used in asm 10.172 - int8 falseSharePad2[256 - sizeof(int32)]; 10.173 - //============ below this, no fields are used in asm ============= 10.174 - 10.175 - //Basic PR infrastructure 10.176 - SlaveVP **masterVPs; 10.177 - AnimSlot ***allAnimSlots; 10.178 - 10.179 - PRProcess **processes; 10.180 - 10.181 -//move to processEnv //Slave creation -- global count of slaves existing, across langs and processes 10.182 - int32 numSlavesCreated; //used to give unique ID to processor 10.183 - int32 numTasksCreated; //to give unique ID to a task 10.184 - 10.185 - //Initialization related 10.186 - int32 setupComplete; //use while starting up coreCtlr 10.187 - 10.188 - //Memory management related 10.189 - MallocArrays *freeLists; 10.190 - int32 amtOfOutstandingMem;//total currently allocated 10.191 - 10.192 - //Random number seeds -- random nums used in various places 10.193 - uint32_t seed1; 10.194 - uint32_t seed2; 10.195 - 10.196 - These_Prob_belong_in_PRPRocess; 10.197 -// SlaveVP *slotTaskSlvs[NUM_CORES][NUM_ANIM_SLOTS]; 10.198 -// int32 numLiveFreeTaskSlvs; 10.199 -// int32 numLiveThreadSlvs; 10.200 -// bool32 *coreIsDone; 10.201 -// int32 numCoresDone; 10.202 - 10.203 -// SlaveVP* idleSlv[NUM_CORES][NUM_ANIM_SLOTS]; 10.204 -// int shutdownInitiated; 10.205 - 10.206 - //=========== MEASUREMENT STUFF ============= 10.207 - IntervalProbe **intervalProbes; 10.208 - PrivDynArrayInfo *dynIntervalProbesInfo; 10.209 - HashTable *probeNameHashTbl; 10.210 - int32 masterCreateProbeID; 10.211 - float64 createPtInSecs; //real-clock time PR initialized 10.212 - Histogram **measHists; 10.213 - PrivDynArrayInfo *measHistsInfo; 10.214 - MEAS__Insert_Susp_Meas_Fields_into_MasterEnv; 10.215 - MEAS__Insert_Master_Meas_Fields_into_MasterEnv; 10.216 - MEAS__Insert_Master_Lock_Meas_Fields_into_MasterEnv; 10.217 - MEAS__Insert_Malloc_Meas_Fields_into_MasterEnv; 10.218 - MEAS__Insert_Plugin_Meas_Fields_into_MasterEnv; 10.219 - MEAS__Insert_System_Meas_Fields_into_MasterEnv; 10.220 - MEAS__Insert_Counter_Meas_Fields_into_MasterEnv; 10.221 - //========================================== 10.222 - } 10.223 -MasterEnv; 10.224 - 10.225 -//===================== 10.226 -typedef struct 10.227 - { int32 langMagicNumber; //indexes into hash array of semEnvs in PRProcess 10.228 - PRSemEnv *chainedSemEnv; //chains to semEnvs with same hash 10.229 - void *langSemEnv; 10.230 - 10.231 - SlaveAssigner slaveAssigner; 10.232 - RequestHandler requestHdlr; 10.233 - 10.234 - RequestHandler createTaskHdlr; 10.235 - RequestHandler endTaskHdlr; 10.236 - RequestHandler createSlaveHdlr; 10.237 - RequestHandler dissipateSlaveHdlr; 10.238 - RequestHandler semDataCreator; 10.239 - RequestHandler semDataInitializer; 10.240 - 10.241 - 10.242 - //Track slaves created, separately for each langlet? (in each process) 10.243 -// int32 numSlavesCreated; //gives ordering to processor creation 10.244 -// int32 numSlavesAlive; //used to detect fail-safe shutdown 10.245 - 10.246 - //when multi-lang, master polls sem env's to find one with work in it.. 10.247 - // in single-lang case, flag ignored, master always asks lang for work 10.248 - int32 hasWork; 10.249 - } 10.250 -PRSemEnv; 10.251 - 10.252 -//The semantic env of every langlet must start with these two fields, so that 10.253 -// PR can cast the void * to this struct, in order to access these two fields 10.254 -typedef struct 10.255 - { int32 langMagicNumber; 10.256 - PRSemEnv *protoSemEnv; 10.257 - } 10.258 -PRLangSemEnv; 10.259 - 10.260 -//can cast any langlet's sem env to one of these, so PR can access values 10.261 -typedef struct 10.262 - { int32 langMagicNumber; 10.263 - PRSemEnv *protoSemEnv; 10.264 - } 10.265 -PRServSemEnv; 10.266 - 10.267 -enum PRTaskType 10.268 - { GenericSlave = 1, 10.269 - SlotTask, 10.270 - FreeTask 10.271 - }; 10.272 - 10.273 -struct _PRMetaTask 10.274 - { 10.275 - PRTaskType taskType; 10.276 -// RequestHandler reqHandler; //Lang-specific hdlr for create, end, etc 10.277 - int32 *taskID; //is standard PR ID 10.278 - SlaveVP *slaveAssignedTo; //no valid until task animated 10.279 - TopLevelFn topLevelFn; //This is the Fn executes as the task 10.280 - void *initData; //The data taken by the function 10.281 - void *langMetaTask; 10.282 - 10.283 - //NOTE: info needed for "wait" functionality is inside lang's metaTask 10.284 - }; 10.285 -//PRMetaTask 10.286 - 10.287 -/*The language's meta task is cast to this struct, inside PR, then the 10.288 - * back pointer to protoMetaTask is set. Keeps existence of PRMetaTask hidden 10.289 - * from plugin -- so can change later. 10.290 - */ 10.291 -typedef struct 10.292 - { int32 langMagicNumber; 10.293 - PRMetaTask *protoMetaTask; 10.294 - } 10.295 -PRLangMetaTask; 10.296 - 10.297 -typedef struct 10.298 - { 10.299 - void (*freeFn)(void *); 10.300 - } 10.301 -PRSemDataTemplate; 10.302 - 10.303 -typedef struct 10.304 - { 10.305 - void (*recycler)(void *); 10.306 - void *langSemData; 10.307 - } 10.308 -PRSemData; 10.309 - 10.310 -typedef struct 10.311 - { PRSemDataTemplate **semDatas; 10.312 - PRSemDataTemplate **semDatasIter; 10.313 - int32 numSemDatas; 10.314 - } 10.315 -PRSemDataHolder; 10.316 -//===================== Top Process level Data Strucs ====================== 10.317 - 10.318 -/*This structure holds all the information PR needs to manage a program. PR 10.319 - * stores information about what percent of CPU time the program is getting, 10.320 - * 10.321 - */ 10.322 -typedef struct 10.323 - { 10.324 - PRSemEnv semEnvs[NUM_SEM_ENVS_IN_PROCESS]; //used as a hash table 10.325 - PRSemEnv semEnvList[NUM_SEM_ENVS_IN_PROCESS]; //lines up the semEnvs, so can iterate through 10.326 - int32 numSemEnvs; //must be less than num sem envs.. used to iterate through 10.327 - 10.328 - int32 numLiveGenericSlvs; 10.329 - int32 numLiveFreeTaskSlvs; 10.330 - int32 numLiveTasks; 10.331 -// bool32 coreIsDone[NUM_CORES][CACHE_LINE_SZ]; //Fixes false sharing 10.332 - 10.333 - PrivQueueStruc *freeTaskSlvRecycleQ; 10.334 - SlaveVP slotTaskSlvs[NUM_CORES][NUM_ANIM_SLOTS]; 10.335 - void *resultToReturn; 10.336 - 10.337 - SlaveVP *seedSlv; 10.338 - 10.339 - SlaveAssigner overrideAssigner; 10.340 - 10.341 - //These are used to coord with OS thread waiting for process to end 10.342 - bool32 executionIsComplete; 10.343 - pthread_mutex_t doneLock; 10.344 - pthread_cond_t doneCond; 10.345 - } 10.346 -PRProcess; 10.347 - 10.348 - 10.349 -//========================= Extra Stuff Data Strucs ======================= 10.350 -typedef struct 10.351 - { 10.352 - 10.353 - } 10.354 -PRExcp; //exception 10.355 - 10.356 -//======================= OS Thread related =============================== 10.357 - 10.358 -void * coreController( void *paramsIn ); //standard PThreads fn prototype 10.359 -void * coreCtlr_Seq( void *paramsIn ); //standard PThreads fn prototype 10.360 -void animationMaster( void *initData, SlaveVP *masterVP ); 10.361 - 10.362 - 10.363 -typedef struct 10.364 - { 10.365 - void *endThdPt; 10.366 - unsigned int coreNum; 10.367 - } 10.368 -ThdParams; 10.369 - 10.370 //============================= Global Vars ================================ 10.371 10.372 -volatile MasterEnv *_PRTopEnv __align_to_cacheline__; 10.373 +volatile TopEnv *_PRTopEnv __align_to_cacheline__; 10.374 10.375 //these are global, but only used for startup and shutdown 10.376 pthread_t coreCtlrThdHandles[ NUM_CORES ]; //pthread's virt-procr state 10.377 @@ -403,7 +56,7 @@ 10.378 * WL Wrapper Library -- wrapper lib code should only use these 10.379 * PI Plugin -- plugin code should only use these 10.380 * SS Startup and Shutdown -- designates these relate to startup & shutdown 10.381 - * int internal to PR -- should not be used in wrapper lib or plugin 10.382 + * int32internal to PR -- should not be used in wrapper lib or plugin 10.383 * PROS means "OS functions for applications to use" 10.384 * 10.385 * PR_int__ functions touch internal PR data structs and are only safe 10.386 @@ -413,184 +66,32 @@ 10.387 * 10.388 * PR_WL__ functions are all safe for use outside the master lock. 10.389 * 10.390 - * PROS are only safe for applications to use -- they're like a second 10.391 + * PR_OS are only safe for applications to use -- they're like a second 10.392 * language mixed in -- but they can't be used inside plugin code, and 10.393 * aren't meant for use in wrapper libraries, because they are themselves 10.394 * wrapper-library calls! 10.395 */ 10.396 -//========== Startup and shutdown ========== 10.397 -void 10.398 -PR__start(); 10.399 10.400 -SlaveVP* 10.401 -PR_SS__create_shutdown_slave(); 10.402 +//============== include internally used fn prototypes ================ 10.403 10.404 -void 10.405 -PR_SS__shutdown(); 10.406 +//include fn prototypes used internally in the proto-runtime implementation 10.407 +#include "PR__int.h" 10.408 10.409 -void 10.410 -PR_SS__cleanup_at_end_of_shutdown(); 10.411 +//include fn prototypes used by plugin 10.412 +#include "PR__PI.h" 10.413 10.414 -void 10.415 -PR_SS__register_langlets_semEnv( PRSemEnv *semEnv, SlaveVP *seedVP, int32 VSs_MAGIC_NUMBER ); 10.416 +//include fn prototype used by wrapper library 10.417 +#include "PR__WL.h" 10.418 10.419 +//================================= 10.420 +#define implement_me printf("Unimpl Fn: \n%s \n%s : %s\n", __FILE__, __FUNCTION__, __LINE__) 10.421 +//#define fix_me printf("Fix me at: \n%s \n%s : %s\n", __FILE__, __FUNCTION__, __LINE__) 10.422 10.423 -//============== =============== 10.424 10.425 -inline SlaveVP * 10.426 -PR_int__create_slaveVP( TopLevelFnPtr fnPtr, void *dataParam ); 10.427 -#define PR_PI__create_slaveVP PR_int__create_slaveVP 10.428 -#define PR_WL__create_slaveVP PR_int__create_slaveVP 10.429 - 10.430 -inline 10.431 -SlaveVP * 10.432 -PR_int__create_slot_slave(); 10.433 - 10.434 -inline 10.435 -SlaveVP * 10.436 -PR_int__create_slaveVP_helper( SlaveVP *newSlv, TopLevelFnPtr fnPtr, 10.437 - void *dataParam, void *stackLocs ); 10.438 - 10.439 -inline 10.440 -PRMetaTask * 10.441 -PR_int__create_generic_slave_meta_task( void *initData ); 10.442 - 10.443 -inline 10.444 -void 10.445 -PR_int__reset_slaveVP_to_TopLvlFn( SlaveVP *slaveVP, TopLevelFnPtr fnPtr, 10.446 - void *dataParam); 10.447 - 10.448 -inline 10.449 -void 10.450 -PR_int__point_slaveVP_to_OneParamFn( SlaveVP *slaveVP, void *fnPtr, 10.451 - void *param); 10.452 - 10.453 -inline 10.454 -void 10.455 -PR_int__point_slaveVP_to_TwoParamFn( SlaveVP *slaveVP, void *fnPtr, 10.456 - void *param1, void *param2); 10.457 - 10.458 -inline 10.459 -void 10.460 -PR_int__dissipate_slaveVP( SlaveVP *slaveToDissipate ); 10.461 -#define PR_PI__dissipate_slaveVP PR_int__dissipate_slaveVP 10.462 -//WL: dissipate a SlaveVP by sending a request 10.463 - 10.464 -inline 10.465 -void 10.466 -PR_int__dissipate_slaveVP_multilang( SlaveVP *slaveToDissipate ); 10.467 - 10.468 -inline 10.469 -void 10.470 -PR_int__throw_exception( char *msgStr, SlaveVP *reqstSlv, PRExcp *excpData ); 10.471 -#define PR_PI__throw_exception PR_int__throw_exception 10.472 -void 10.473 -PR_WL__throw_exception( char *msgStr, SlaveVP *reqstSlv, PRExcp *excpData ); 10.474 -#define PR_App__throw_exception PR_WL__throw_exception 10.475 - 10.476 -inline 10.477 -void * 10.478 -PR_int__give_sem_env_for_slave( SlaveVP *slave, int32 magicNumber ); 10.479 -#define PR_PI__give_sem_env_for PR_int__give_sem_env_for_slave 10.480 -#define PR_SS__give_sem_env_for_slave PR_int__give_sem_env_for_slave 10.481 -//No WL version -- not safe! if use env in WL, be sure data rd & wr is stable 10.482 -inline 10.483 -PRSemEnv * 10.484 -PR_int__give_proto_sem_env_for_slave( SlaveVP *slave, int32 magicNumber ); 10.485 -#define PR_PI__give_proto_sem_env_for PR_int__give_proto_sem_env_for_slave 10.486 -#define PR_SS__give_proto_sem_env_for_slave PR_int__give_proto_sem_env_for_slave 10.487 -//No WL version -- not safe! if use env in WL, be sure data rd & wr is stable 10.488 -inline 10.489 -void * 10.490 -PR_int__give_sem_env_from_process( PRProcess *process, int32 magicNumer ); 10.491 -#define PR_PI__give_sem_env_from_process PR_int__give_sem_env_from_process 10.492 -#define PR_SS__give_sem_env_from_process PR_int__give_sem_env_from_process 10.493 -//#define PR_WL__give_sem_env_from_process PR_int__give_sem_env_from_process 10.494 -//No WL version -- not safe! if use env in WL, be sure data rd & wr is stable 10.495 - 10.496 -inline 10.497 -void * 10.498 -PR_int__give_sem_data( SlaveVP *slave, int32 magicNumer ); 10.499 -#define PR_PI__give_sem_data PR_int__give_sem_data 10.500 -#define PR_SS__give_sem_data PR_int__give_sem_data 10.501 -#define PR_WL__give_sem_data PR_int__give_sem_data 10.502 - 10.503 - 10.504 -#define PR_int__give_lang_meta_task( slave, magicNumber )\ 10.505 - slave->metaTask->langMetaTask; 10.506 -#define PR_PI__give_lang_meta_task PR_int__give_lang_meta_task 10.507 -#define PR_SS__give_lang_meta_task PR_int__give_lang_meta_task 10.508 -#define PR_WL__give_lang_meta_task PR_int__give_lang_meta_task 10.509 - 10.510 -inline 10.511 -SlaveVP * 10.512 -PR_PI__give_slave_assigned_to( PRLangMetaTask *langMetaTask ); 10.513 - 10.514 -void 10.515 -idle_fn(void* data, SlaveVP *animatingSlv); 10.516 - 10.517 -inline void 10.518 -PR_int__get_master_lock(); 10.519 - 10.520 -#define PR_int__release_master_lock() _PRTopEnv->masterLock = UNLOCKED 10.521 - 10.522 -inline uint32_t 10.523 -PR_int__randomNumber(); 10.524 - 10.525 -//============== Request Related =============== 10.526 - 10.527 -void 10.528 -PR_WL__suspend_slaveVP_and_send_req( SlaveVP *callingSlv ); 10.529 - 10.530 -inline void 10.531 -PR_WL__add_sem_request_in_mallocd_PRReqst( void *semReqData, SlaveVP *callingSlv ); 10.532 - 10.533 -inline void 10.534 -PR_WL__send_sem_request( void *semReq, SlaveVP *callingSlv, int32 magicNum ); 10.535 - 10.536 -void 10.537 -PR_WL__send_create_slaveVP_req( void *semReqData, SlaveVP *reqstingSlv ); 10.538 - 10.539 -void inline 10.540 -PR_WL__send_dissipate_req( SlaveVP *prToDissipate ); 10.541 - 10.542 -inline void 10.543 -PR_WL__send_service_request( void *semReqData, SlaveVP *callingSlv ); 10.544 - 10.545 -PRReqst * 10.546 -PR_PI__take_next_request_out_of( SlaveVP *slaveWithReq ); 10.547 -//#define PR_PI__take_next_request_out_of( slave ) slave->requests 10.548 - 10.549 -//inline void * 10.550 -//PR_PI__take_sem_reqst_from( PRReqst *req ); 10.551 -#define PR_PI__take_sem_reqst_from( req ) req->semReqData 10.552 - 10.553 -void inline 10.554 -PR_int__handle_PRServiceReq( PRReqst *req, SlaveVP *requestingSlv, void *semEnv, 10.555 - ResumeSlvFnPtr resumeSlvFnPtr ); 10.556 - 10.557 -//======================== MEASUREMENT ====================== 10.558 -uint64 10.559 -PR_WL__give_num_plugin_cycles(); 10.560 -uint32 10.561 -PR_WL__give_num_plugin_animations(); 10.562 - 10.563 - 10.564 -//========================= Utilities ======================= 10.565 -inline char * 10.566 -PR_int__strDup( char *str ); 10.567 - 10.568 - 10.569 -//========================= PR request handlers ======================== 10.570 -void inline 10.571 -handleMakeProbe( PRServReq *semReq, void *semEnv, ResumeSlvFnPtr resumeFn ); 10.572 - 10.573 -void inline 10.574 -handleThrowException( PRServReq *semReq, void *semEnv, ResumeSlvFnPtr resumeFn ); 10.575 -//======================================================================= 10.576 - 10.577 -//========================= Probes ======================= 10.578 -#include "Services_Offered_by_PR/Measurement_and_Stats/probes.h" 10.579 +//========================= Services ======================= 10.580 +//#include "Services_Offered_by_PR/Measurement_and_Stats/probes.h" 10.581 +//#include "Services_Offered_by_PR/Services_Language/PRServ.h" 10.582 +//#include "Services_Offered_by_PR/Services_Language/libPRServ.h" 10.583 10.584 //================================================ 10.585 #endif /* _PR_H */
11.1 --- a/PR__PI.c Sun Nov 04 18:39:28 2012 -0800 11.2 +++ b/PR__PI.c Mon Jan 14 15:31:23 2013 -0800 11.3 @@ -1,5 +1,5 @@ 11.4 /* 11.5 - * Copyright 2010 OpenSourceStewardshipFoundation 11.6 + * Copyright 2010 OpenSourceResearchInstitute 11.7 * 11.8 * Licensed under BSD 11.9 */ 11.10 @@ -44,9 +44,9 @@ 11.11 *Turn function into macro that just accesses the request field 11.12 * 11.13 inline void * 11.14 -PR_PI__take_sem_reqst_from( PRReqst *req ) 11.15 +PR_PI__take_lang_reqst_from( PRReqst *req ) 11.16 { 11.17 - return req->semReqData; 11.18 + return req->langReqData; 11.19 } 11.20 */ 11.21
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/PR__PI.h Mon Jan 14 15:31:23 2013 -0800 12.3 @@ -0,0 +1,54 @@ 12.4 +/* 12.5 + * Copyright 2009 OpenSourceResearchInstitute.org 12.6 + * Licensed under GNU General Public License version 2 12.7 + * 12.8 + * Author: seanhalle@yahoo.com 12.9 + * 12.10 + */ 12.11 + 12.12 +#ifndef _PR__PI_H 12.13 +#define _PR__PI_H 12.14 +#define _GNU_SOURCE 12.15 + 12.16 + 12.17 +#include "PR_primitive_data_types.h" 12.18 + 12.19 +//========================= Function Prototypes =========================== 12.20 +/* MEANING OF WL PI SS int PROS 12.21 + * These indicate which places the function is safe to use. They stand for: 12.22 + * 12.23 + * WL Wrapper Library -- wrapper lib code should only use these 12.24 + * PI Plugin -- plugin code should only use these 12.25 + * SS Startup and Shutdown -- designates these relate to startup & shutdown 12.26 + * int32internal to PR -- should not be used in wrapper lib or plugin 12.27 + * PROS means "OS functions for applications to use" 12.28 + * 12.29 + * PR_int__ functions touch internal PR data structs and are only safe 12.30 + * to be used inside the master lock. However, occasionally, they appear 12.31 + * in wrapper-lib or plugin code. In those cases, very careful analysis 12.32 + * has been done to be sure no concurrency issues could arise. 12.33 + * 12.34 + * PR_WL__ functions are all safe for use outside the master lock. 12.35 + * 12.36 + * PROS are only safe for applications to use -- they're like a second 12.37 + * language mixed in -- but they can't be used inside plugin code, and 12.38 + * aren't meant for use in wrapper libraries, because they are themselves 12.39 + * wrapper-library calls! 12.40 + */ 12.41 + 12.42 +inline 12.43 +SlaveVP * 12.44 +PR_PI__give_slave_lang_meta_task_assigned_to( void *langMetaTask ); 12.45 + 12.46 + 12.47 +PRReqst * 12.48 +PR_PI__take_next_request_out_of( SlaveVP *slaveWithReq ); 12.49 +//#define PR_PI__take_next_request_out_of( slave ) slave->requests 12.50 + 12.51 +//inline void * 12.52 +//PR_PI__take_lang_reqst_from( PRReqst *req ); 12.53 +#define PR_PI__take_lang_reqst_from( req ) req->langReqData 12.54 + 12.55 +//================================================ 12.56 +#endif /* _PR__PI_H */ 12.57 +
13.1 --- a/PR__SS.c Sun Nov 04 18:39:28 2012 -0800 13.2 +++ b/PR__SS.c Mon Jan 14 15:31:23 2013 -0800 13.3 @@ -1,5 +1,5 @@ 13.4 /* 13.5 - * Copyright 2010 OpenSourceStewardshipFoundation 13.6 + * Copyright 2010 OpenSourceResearchInstitute 13.7 * 13.8 * Licensed under BSD 13.9 */ 13.10 @@ -32,7 +32,7 @@ 13.11 create_anim_slots( int32 coreSlotsAreOn ); 13.12 13.13 void 13.14 -create_masterEnv(); 13.15 +create_topEnv(); 13.16 13.17 void 13.18 create_the_coreCtlr_OS_threads(); 13.19 @@ -70,251 +70,307 @@ 13.20 * the requestHandler and slaveAssigner plug-in functions 13.21 */ 13.22 13.23 -/*This allocates PR data structures, populates the master PRProc, 13.24 - * and master environment, and returns the master environment to the semantic 13.25 - * layer. 13.26 +//Check the comments above -- likely out of sync 13.27 + 13.28 +/*This allocates PR data structures, populates the top environments. After 13.29 + * this call, processes can be started. 13.30 */ 13.31 void 13.32 PR__start() 13.33 { 13.34 - #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE 13.35 - create_masterEnv(); 13.36 - printf( "\n\n Running in SEQUENTIAL mode \n\n" ); 13.37 - #else 13.38 - create_masterEnv(); 13.39 - DEBUG__printf1(dbgInfra,"Offset of lock in masterEnv: %d ", (int32)offsetof(MasterEnv,masterLock) ); 13.40 - create_the_coreCtlr_OS_threads(); 13.41 - #endif 13.42 + create_topEnv(); 13.43 + 13.44 + #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE 13.45 + printf( "\n\n Running in SEQUENTIAL mode \n\n" ); 13.46 + #else 13.47 + DEBUG__printf1(dbgInfra,"Offset of lock in masterEnv: %d ", (int32)offsetof(TopEnv,masterLock) ); 13.48 + create_the_coreCtlr_OS_threads(); 13.49 + 13.50 + #endif 13.51 } 13.52 13.53 13.54 -/*A process is represented by a structure that holds all the process-specific 13.55 +/*This creates a new process and sets the mode to single lang for it 13.56 + *It creates a seed slave, from the top-level fn and initial data passed into 13.57 + * this fn. 13.58 + *The only langlet in the created process is the default PRServ. The rest 13.59 + * must b e started up via calls made by the seed VP's top-level fn (passed in 13.60 + * to this call). 13.61 + * 13.62 + *A process is represented by a structure that holds all the process-specific 13.63 * information: 13.64 - *-] The hash-array containing the semantic environs of any langlets started 13.65 + *-] The hash-array containing the language environs of any langlets started 13.66 * inside the process. 13.67 - *-] Flags used to detect the end of activity in the process 13.68 *-] Counter of num live slaves and num live tasks in the process 13.69 * 13.70 - *PR automatically generates the seedVP when it creates the process, and 13.71 - * inserts the processID of the newly created process into it. 13.72 */ 13.73 PRProcess * 13.74 -PR__create_process( TopLevelFnPtr seed_Fn, void *seedData ) 13.75 +PR__create_process__SL( TopLevelFnPtr seed_Fn, void *seedData ) 13.76 { SlaveVP *seedSlv; 13.77 PRProcess *process; 13.78 - PRMetaTask *metaTask; 13.79 - PRSemEnv *semEnvs; 13.80 - int32 idx; 13.81 + PRLangEnv **langEnvs, **langEnvsList; 13.82 + 13.83 + _PRTopEnv->mode = SingleLang; 13.84 + 13.85 13.86 process = malloc( sizeof(PRProcess) ); 13.87 - process->numSemEnvs = 0; 13.88 - semEnvs = process->semEnvs; 13.89 - for( idx = 0; idx < NUM_SEM_ENVS_IN_PROCESS; idx++ ) 13.90 - { semEnvs[idx].langSemEnv = NULL; 13.91 - semEnvs[idx].chainedSemEnv = NULL; 13.92 + _PRTopEnv->processes[_PRTopEnv->numProcesses] = process; 13.93 + _PRTopEnv->numProcesses += 1; 13.94 + 13.95 + langEnvs = malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRCollElem *) ); 13.96 + ((int32 *)langEnvs)[0] = NUM_IN_COLLECTION; 13.97 + langEnvsList = malloc( NUM_IN_COLLECTION * sizeof(PRCollElem *) ); 13.98 + process->langEnvs = langEnvs; 13.99 + process->langEnvsList = langEnvsList; 13.100 + process->numLangEnvs = 0; 13.101 + 13.102 + //A Process starts with one slave, the seed slave 13.103 + seedSlv = PR_int__create_slaveVP__ML( seed_Fn, seedData, process ); 13.104 + seedSlv->typeOfVP = SeedSlv; 13.105 + seedSlv->processSlaveIsIn = process; 13.106 + process->numLiveGenericSlvs = 1; //count the seed 13.107 + process->numLiveTasks = 0; 13.108 + 13.109 + PRServLangEnv * 13.110 + servicesLangEnv = 13.111 + PR_int__create_lang_env_in_process( sizeof(PRServLangEnv), process, PRServ_MAGIC_NUMBER ); 13.112 + 13.113 + servicesLangEnv->slavesReadyToResumeQ = makePrivQ(); 13.114 + servicesLangEnv->taskReadyQ = makePrivQ(); 13.115 + 13.116 + //resume seedVP into PR's built-in services language's language env 13.117 + process->numEnvsWithWork = 0; //Seed is in PRServ lang env.. resume incrs this 13.118 + PRServ__resume_slaveVP( seedSlv, servicesLangEnv ); 13.119 + 13.120 + 13.121 + //The first process created has to unblock the core controllers. 13.122 + if( _PRTopEnv->numProcesses == 1 ) 13.123 + { 13.124 + #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE 13.125 + //Only difference between version with an OS thread pinned to each core and 13.126 + // the sequential version of PR is PR__init_Seq, this, and coreCtlr_Seq. 13.127 + 13.128 + // call the one and only core ctlr (sequential version), in the main thread. 13.129 + coreCtlr_Seq( NULL ); 13.130 + flushRegisters(); //Not sure why here, but leaving to be safe 13.131 + #else 13.132 + //tell the core controller threads that a process is ready to be animated 13.133 + //get lock, to lock out any threads still starting up -- they'll see 13.134 + // that firstProcessReady is true before entering while loop, and so never 13.135 + // wait on the condition 13.136 + pthread_mutex_lock( &suspendLock ); 13.137 + _PRTopEnv->firstProcessReady = 1; 13.138 + pthread_mutex_unlock( &suspendLock ); 13.139 + pthread_cond_broadcast( &suspendCond ); 13.140 + #endif 13.141 } 13.142 - 13.143 - //A Process starts with one slave, the seed slave 13.144 - seedSlv = PR_int__create_slaveVP( seed_Fn, seedData ); 13.145 - 13.146 - seedSlv->processSlaveIsIn = process; 13.147 - 13.148 - //seed slave is a generic slave, so make a generic slave meta task for it 13.149 - metaTask = PR_int__create_generic_slave_meta_task( seedData ); 13.150 - seedSlv->metaTask = metaTask; 13.151 - 13.152 - process->numLiveGenericSlvs = 1; //count the seed 13.153 - process->numLiveTasks = 0; 13.154 - 13.155 - PRServSemEnv * 13.156 - servicesSemEnv = PR_SS__malloc( sizeof(PRServSemEnv) ); 13.157 - PR_SS__register_langlets_semEnv( servicesSemEnv, seedSlv, PRSERV_MAGIC_NUMBER ); 13.158 - 13.159 - //resume seedVP into PR's built-in services language's semantic env 13.160 - PRServ__resume_slaveVP( seedSlv, servicesSemEnv ); 13.161 + pthread_mutex_init( process->doneLock, NULL ); 13.162 + pthread_cond_init( process->doneCond, NULL ); 13.163 + process->executionIsComplete = FALSE; 13.164 13.165 return process; 13.166 } 13.167 13.168 +/*This is only called in multi-lang mode. 13.169 + *It creates a seed slave, from the top-level fn and initial data passed into 13.170 + * this fn. 13.171 + *The only langlet in the created process is the default PRServ. The rest 13.172 + * must b e started up via calls made by the seed VP's top-level fn (passed in 13.173 + * to this call). 13.174 + * 13.175 + *A process is represented by a structure that holds all the process-specific 13.176 + * information: 13.177 + *-] The hash-array containing the language environs of any langlets started 13.178 + * inside the process. 13.179 + *-] Counter of num live slaves and num live tasks in the process 13.180 + * 13.181 + */ 13.182 +PRProcess * 13.183 +PR__create_process__ML( TopLevelFnPtr seed_Fn, void *seedData ) 13.184 + { SlaveVP *seedSlv; 13.185 + PRProcess *process; 13.186 + PRLangEnv **langEnvs, **langEnvsList; 13.187 + 13.188 + _PRTopEnv->mode = MultiLang; 13.189 + 13.190 + 13.191 + process = malloc( sizeof(PRProcess) ); 13.192 + _PRTopEnv->processes[_PRTopEnv->numProcesses] = process; 13.193 + _PRTopEnv->numProcesses += 1; 13.194 + 13.195 + langEnvs = malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRCollElem *) ); 13.196 + ((int32 *)langEnvs)[0] = NUM_IN_COLLECTION; 13.197 + langEnvsList = malloc( NUM_IN_COLLECTION * sizeof(PRCollElem *) ); 13.198 + process->langEnvs = langEnvs; 13.199 + process->langEnvsList = langEnvsList; 13.200 + process->numLangEnvs = 0; 13.201 + 13.202 + //A Process starts with one slave, the seed slave 13.203 + seedSlv = PR_int__create_slaveVP__ML( seed_Fn, seedData, process ); 13.204 + seedSlv->typeOfVP = SeedSlv; 13.205 + seedSlv->processSlaveIsIn = process; 13.206 + process->numLiveGenericSlvs = 1; //count the seed 13.207 + process->numLiveTasks = 0; 13.208 + 13.209 + PRServLangEnv * 13.210 + servicesLangEnv = 13.211 + PR_int__create_lang_env_in_process( sizeof(PRServLangEnv), process, PRServ_MAGIC_NUMBER ); 13.212 13.213 -/*This gets the process struct out of the seedVP, then gets the semEnv-holding 13.214 - * struct out of that, then inserts the semantic env into that struct, using 13.215 - * the magic number as the key to the sem env placement. The master will 13.216 - * use the magic number from a request to retrieve the semantic env appropriate 13.217 - * for the construct that made the request. 13.218 + servicesLangEnv->slavesReadyToResumeQ = makePrivQ(); 13.219 + servicesLangEnv->taskReadyQ = makePrivQ(); 13.220 + 13.221 + //resume seedVP into PR's built-in services language's language env 13.222 + process->numEnvsWithWork = 0; //Seed is in PRServ lang env.. resume incrs this 13.223 + PRServ__resume_slaveVP( seedSlv, servicesLangEnv ); 13.224 + 13.225 + 13.226 + //The first process created has to unblock the core controllers. 13.227 + if( _PRTopEnv->numProcesses == 1 ) 13.228 + { 13.229 + #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE 13.230 + //Only difference between version with an OS thread pinned to each core and 13.231 + // the sequential version of PR is PR__init_Seq, this, and coreCtlr_Seq. 13.232 + 13.233 + // call the one and only core ctlr (sequential version), in the main thread. 13.234 + coreCtlr_Seq( NULL ); 13.235 + flushRegisters(); //Not sure why here, but leaving to be safe 13.236 + #else 13.237 + //tell the core controller threads that a process is ready to be animated 13.238 + //get lock, to lock out any threads still starting up -- they'll see 13.239 + // that firstProcessReady is true before entering while loop, and so never 13.240 + // wait on the condition 13.241 + pthread_mutex_lock( &suspendLock ); 13.242 + _PRTopEnv->firstProcessReady = 1; 13.243 + pthread_mutex_unlock( &suspendLock ); 13.244 + pthread_cond_broadcast( &suspendCond ); 13.245 + #endif 13.246 + } 13.247 + pthread_mutex_init( process->doneLock, NULL ); 13.248 + pthread_cond_init( process->doneCond, NULL ); 13.249 + process->executionIsComplete = FALSE; 13.250 + 13.251 + return process; 13.252 + } 13.253 + 13.254 + 13.255 +/*are already in Master when detect, inside end-task or dissipate, so call "PR_SS__shutdown_process" 13.256 */ 13.257 void 13.258 -PR_SS__register_langlets_semEnv( void *_semEnv, SlaveVP *seedVP, int32 magicNum ) 13.259 - { PRSemEnv *protoSemEnv; 13.260 - PRProcess *process; 13.261 - PRServSemEnv *semEnv = (PRServSemEnv *)_semEnv; 13.262 +PR_SS__shutdown_process__ML( PRProcess *process ) 13.263 + { int32 i, processIdx; 13.264 + PRProcess **processes; 13.265 + 13.266 + //remove process from PR's list of processes.. 13.267 + processes = _PRTopEnv->processes; 13.268 + for( i = 0; i < _PRTopEnv->numProcesses; i++ ) 13.269 + { if( processes[i] == process ) 13.270 + { processIdx = i; 13.271 + break; 13.272 + } 13.273 + } 13.274 + for( i = processIdx +1; i < _PRTopEnv->numProcesses; i++ ) 13.275 + { processes[i-1] = process[i]; 13.276 + } 13.277 + _PRTopEnv->numProcesses -= 1; 13.278 + 13.279 + //remove process from the process-to-slot chooser 13.280 + _PRTopEnv->currProcessIdx = 0; //start choosing starting at process 0 13.281 + 13.282 + //call shutdown on each langlet started in process (which frees any 13.283 + // langlet-allocd data in langEnv); 13.284 + //Then free the lang env 13.285 + PRLangEnv *langEnv; 13.286 + for( i = 0; i < process->numLangEnvs; i++ ) 13.287 + { langEnv = PR_int__give_proto_lang_env(process->langEnvsList[i]); 13.288 + //The lang shutdowns should free any slaves or tasks in the langEnv 13.289 + (*langEnv->shutdownHdlr)(&(langEnv[1])); 13.290 + PR_int__free( langEnv ); 13.291 + } 13.292 + PR_int__free( process->langEnvsList ); //list array 13.293 + PR_int__free( &(((int32 *)process->langEnvs)[-1]) ); //the collection array 13.294 + 13.295 + //any slaves from this process still in slots will finish executing, but 13.296 + // have no lang env for the request handlers to use! 13.297 + //So, have to mark each slave, so the request handling isn't done 13.298 + AnimSlot *slot, **animSlots; 13.299 + int32 core; 13.300 + for( core = 0; core < NUM_CORES; core++ ) 13.301 + { animSlots = _PRTopEnv->allAnimSlots[core]; 13.302 + for( i = 0; i < NUM_ANIM_SLOTS; i++ ) 13.303 + { slot = animSlots[i]; 13.304 + if( slot->slaveAssignedToSlot->processSlaveIsIn == process ) 13.305 + { //turn off req handling by disallowing slave from chging slot flag 13.306 + slot->slaveAssignedToSlot->animSlotAssignedTo = NULL; 13.307 + slot->workIsDone = FALSE; //just in case, make sure req hdling off 13.308 + slot->needsWorkAssigned = TRUE; //make new slave be assigned 13.309 + } 13.310 + } 13.311 + } 13.312 + 13.313 + //cause resume of "PR__wait_for_process_to_end()" call 13.314 + pthread_mutex_lock( process->doneLock ); 13.315 + process->executionIsComplete = TRUE; 13.316 + pthread_mutex_unlock( process->doneLock ); 13.317 + pthread_cond_broadcast( process->doneCond ); 13.318 + //BUG: process struct can be freed and re-allocated before waiter sees 13.319 + // executionIsComplete 13.320 13.321 - process = seedVP->processSlaveIsIn; 13.322 - 13.323 - protoSemEnv = PR_int__create_proto_sem_env_in_process( process, magicNum ); 13.324 - protoSemEnv->langSemEnv = semEnv; 13.325 - protoSemEnv->langMagicNumber = magicNum; 13.326 - protoSemEnv->hasWork = FALSE; 13.327 - 13.328 - semEnv->protoSemEnv = protoSemEnv; 13.329 + //if last process, cause resume of "PR__wait_for_all_activity_to_end" 13.330 + if( _PRTopEnv->numProcesses == 1 ) 13.331 + { implement_me(); //have to ensure that PRServ has no activity -- do later 13.332 + pthread_mutex_lock( _PRTopEnv->activityDoneLock ); 13.333 + _PRTopEnv->allActivityIsDone = TRUE; 13.334 + pthread_mutex_unlock( _PRTopEnv->activityDoneLock ); 13.335 + pthread_cond_broadcast( _PRTopEnv->activityDoneCond ); 13.336 + } 13.337 + 13.338 + //lastly, free the PRProcess struct itself 13.339 + PR_int__free(process); 13.340 } 13.341 13.342 -/*These store the pointer to handler into the semantic env -- semantic env 13.343 - * found by using magic num to look it up in the process that the seedVP 13.344 - * is inside of. 13.345 +/*This waits for the OS threads in the PR system to end. Causing them to end 13.346 + * has to be done separately (haven't worked out details as of this comment) 13.347 */ 13.348 void 13.349 -PR_SS__register_create_task_handler( RequestHandler createTaskHandler, SlaveVP *seedVP, int32 magicNum ) 13.350 - { PRSemEnv *semEnv; 13.351 - 13.352 - semEnv = PR_SS__give_proto_sem_env_for_slave( seedVP, magicNum ); 13.353 - semEnv->createTaskHdlr = createTaskHandler; 13.354 - } 13.355 -void 13.356 -PR_SS__register_end_task_handler( RequestHandler endTaskHandler, SlaveVP *seedVP, int32 magicNum ) 13.357 - { PRSemEnv *semEnv; 13.358 - 13.359 - semEnv = PR_SS__give_proto_sem_env_for_slave( seedVP, magicNum ); 13.360 - semEnv->endTaskHdlr = endTaskHandler; 13.361 - } 13.362 -void 13.363 -PR_SS__register_create_slave_handler( RequestHandler createSlvHandler, SlaveVP *seedVP, int32 magicNum ) 13.364 - { PRSemEnv *semEnv; 13.365 - 13.366 - semEnv = PR_SS__give_proto_sem_env_for_slave( seedVP, magicNum ); 13.367 - semEnv->createSlaveHdlr = createSlvHandler; 13.368 - } 13.369 -void 13.370 -PR_SS__register_dissipate_slave_handler( RequestHandler dissipateHandler, SlaveVP *seedVP, int32 magicNum ) 13.371 - { PRSemEnv *semEnv; 13.372 - 13.373 - semEnv = PR_SS__give_proto_sem_env_for_slave( seedVP, magicNum ); 13.374 - semEnv->dissipateSlaveHdlr = dissipateHandler; 13.375 - } 13.376 -void 13.377 -PR_SS__register_request_handler( RequestHandler reqHandler, SlaveVP *seedVP, int32 magicNum ) 13.378 - { PRSemEnv *semEnv; 13.379 - 13.380 - semEnv = PR_SS__give_proto_sem_env_for_slave( seedVP, magicNum ); 13.381 - semEnv->requestHdlr = reqHandler; 13.382 - } 13.383 -void 13.384 -PR_SS__register_assigner( SlaveAssigner assigner, SlaveVP *seedVP, int32 magicNum ) 13.385 - { PRSemEnv *semEnv; 13.386 - 13.387 - semEnv = PR_SS__give_proto_sem_env_for_slave( seedVP, magicNum ); 13.388 - semEnv->slaveAssigner = assigner; 13.389 - } 13.390 -void 13.391 -PR_SS__register_sem_data_creator( SemDataCreator semDataCreator, 13.392 - SlaveVP *seedVP, int32 magicNum ) 13.393 - { PRSemEnv *semEnv; 13.394 - 13.395 - semEnv = PR_SS__give_proto_sem_env_for_slave( seedVP, magicNum ); 13.396 - semEnv->semDataCreator = semDataCreator; 13.397 - } 13.398 -void 13.399 -PR_SS__register_sem_data_initializer( SemDataInitializer semDataInitializer, 13.400 - SlaveVP *seedVP, int32 magicNum ) 13.401 - { PRSemEnv *semEnv; 13.402 - 13.403 - semEnv = PR_SS__give_proto_sem_env_for_slave( seedVP, magicNum ); 13.404 - semEnv->semDataInitializer = semDataInitializer; 13.405 +PR_SS__wait_for_PR_to_shutdown() 13.406 + { 13.407 + //wait for all to complete 13.408 + int coreIdx; 13.409 + for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) 13.410 + { 13.411 + pthread_join( coreCtlrThdHandles[coreIdx], NULL ); 13.412 + } 13.413 } 13.414 13.415 - 13.416 - 13.417 - 13.418 -/*TODO: finish implementing 13.419 - *This function returns information about the version of PR, the language 13.420 - * the program is being run in, its version, and information on the 13.421 - * hardware. 13.422 - */ 13.423 -/* 13.424 -char * 13.425 -PRServ___give_environment_string() 13.426 - { 13.427 - //-------------------------- 13.428 - fprintf(output, "#\n# >> Build information <<\n"); 13.429 - fprintf(output, "# GCC VERSION: %d.%d.%d\n",__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__); 13.430 - fprintf(output, "# Build Date: %s %s\n", __DATE__, __TIME__); 13.431 - 13.432 - fprintf(output, "#\n# >> Hardware information <<\n"); 13.433 - fprintf(output, "# Hardware Architecture: "); 13.434 - #ifdef __x86_64 13.435 - fprintf(output, "x86_64"); 13.436 - #endif //__x86_64 13.437 - #ifdef __i386 13.438 - fprintf(output, "x86"); 13.439 - #endif //__i386 13.440 - fprintf(output, "\n"); 13.441 - fprintf(output, "# Number of Cores: %d\n", NUM_CORES); 13.442 - //-------------------------- 13.443 - 13.444 - //PR Plugins 13.445 - fprintf(output, "#\n# >> PR Plugins <<\n"); 13.446 - fprintf(output, "# Language : "); 13.447 - fprintf(output, _LANG_NAME_); 13.448 - fprintf(output, "\n"); 13.449 - //Meta info gets set by calls from the language during its init, 13.450 - // and info registered by calls from inside the application 13.451 - fprintf(output, "# Assigner: %s\n", _PRTopEnv->metaInfo->assignerInfo); 13.452 - 13.453 - //-------------------------- 13.454 - //Application 13.455 - fprintf(output, "#\n# >> Application <<\n"); 13.456 - fprintf(output, "# Name: %s\n", _PRTopEnv->metaInfo->appInfo); 13.457 - fprintf(output, "# Data Set:\n%s\n",_PRTopEnv->metaInfo->inputSet); 13.458 - 13.459 - //-------------------------- 13.460 +void 13.461 +PR__wait_for_all_activity_to_end() 13.462 + { 13.463 + pthread_mutex_lock( _PRTopEnv->activityDoneLock ); 13.464 + while( !(_PRTopEnv->allActivityIsDone) ) 13.465 + { 13.466 + pthread_cond_wait( _PRTopEnv->activityDoneCond, 13.467 + _PRTopEnv->activityDoneLock ); 13.468 + } 13.469 + pthread_mutex_unlock( _PRTopEnv->activityDoneLock ); 13.470 } 13.471 - */ 13.472 13.473 void 13.474 -PR_SS__shutdown_process( PRProcess *process ) 13.475 - { 13.476 - 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); 13.477 +PR__wait_for_process_to_end() 13.478 + { 13.479 + pthread_mutex_lock( _PRTopEnv->activityDoneLock ); 13.480 + while( !(_PRTopEnv->allActivityIsDone) ) 13.481 + { 13.482 + pthread_cond_wait( _PRTopEnv->activityDoneCond, 13.483 + _PRTopEnv->activityDoneLock ); 13.484 + } 13.485 + pthread_mutex_unlock( _PRTopEnv->activityDoneLock ); 13.486 } 13.487 13.488 -/*A pointer to the startup-function for the language is given as the last 13.489 - * argument to the call. Use this to initialize a program in the language. 13.490 - * This creates a data structure that encapsulates the bookkeeping info 13.491 - * PR uses to track and schedule a program run. 13.492 - */ 13.493 -/*PRProcess * 13.494 -PR__spawn_program_on_data_in_Lang( TopLevelFnPtr seed_fn, void *data ) 13.495 - { PRProcess *newProcess; 13.496 - newProcess = malloc( sizeof(PRProcess) ); 13.497 - 13.498 - newProcess->doneLock = PTHREAD_MUTEX_INITIALIZER; 13.499 - newProcess->doneCond = PTHREAD_COND_INITIALIZER; 13.500 - newProcess->executionIsComplete = FALSE; 13.501 - newProcess->numSlavesLive = 0; 13.502 - 13.503 - newProcess->dataForSeed = data; 13.504 - newProcess->seedFnPtr = prog_seed_fn; 13.505 - 13.506 - //The language's spawn-process function fills in the plugin function-ptrs in 13.507 - // the PRProcess struct, gives the struct to PR, which then makes and 13.508 - // queues the seed SlaveVP, which starts processors made from the code being 13.509 - // animated. 13.510 - 13.511 - (*langInitFnPtr)( newProcess ); 13.512 - 13.513 - return newProcess; 13.514 - } 13.515 -*/ 13.516 - 13.517 - 13.518 -/*When all SlaveVPs owned by the program-run associated to the process have 13.519 - * dissipated, then return from this call. There is no language to cleanup, 13.520 - * and PR does not shutdown.. but the process bookkeeping structure, 13.521 - * which is used by PR to track and schedule the program, is freed. 13.522 - *The PRProcess structure is kept until this call collects the results from it, 13.523 - * then freed. If the process is not done yet when PR gets this 13.524 - * call, then this call waits.. the challenge here is that this call comes from 13.525 - * a live OS thread that's outside PR.. so, inside here, it waits on a 13.526 - * condition.. then it's a PR thread that signals this to wake up.. 13.527 +/*When all work in the process has completed, then return from this call. 13.528 + * The seedVP of the process may still exist, but it has no work, nor do any 13.529 + * other VPs.. 13.530 + *The process must be shutdown via a separate call. That shutdown frees the 13.531 + * process struct and bookkeeping structs. 13.532 *First checks whether the process is done, if yes, calls the clean-up fn then 13.533 * returns the result extracted from the PRProcess struct. 13.534 *If process not done yet, then performs a wait (in a loop to be sure the 13.535 @@ -322,9 +378,8 @@ 13.536 * the process ending (last SlaveVP owned by it dissipates), then PR signals 13.537 * this to wakeup. This then calls the cleanup fn and returns the result. 13.538 */ 13.539 -/* 13.540 void * 13.541 -PR_App__give_results_when_done_for( PRProcess *process ) 13.542 +PR__give_results_from_process_when_ready( PRProcess *process ) 13.543 { void *result; 13.544 13.545 pthread_mutex_lock( process->doneLock ); 13.546 @@ -333,109 +388,273 @@ 13.547 pthread_cond_wait( process->doneCond, 13.548 process->doneLock ); 13.549 } 13.550 + result = process->resultToReturn; 13.551 pthread_mutex_unlock( process->doneLock ); 13.552 - 13.553 - result = process->resultToReturn; 13.554 - 13.555 - PR_int__cleanup_process_after_done( process ); 13.556 - free( process ); //was malloc'd above, so free it here 13.557 - 13.558 + 13.559 return result; 13.560 } 13.561 + 13.562 + 13.563 +inline 13.564 +void * 13.565 +PR_SS__create_lang_env( int32 size, SlaveVP *slave, int32 magicNum ) 13.566 + { 13.567 + return PR_int__create_lang_env_in_process( size, slave->processSlaveIsIn, magicNum ); 13.568 + } 13.569 + 13.570 + 13.571 +/*These store the pointer to handler into the language env -- language env 13.572 + * found by using magic num to look it up in the process that the seedVP 13.573 + * is inside of. 13.574 + */ 13.575 +void 13.576 +PR_SS__register_create_task_handler( RequestHandler createTaskHandler, SlaveVP *seedVP, int32 magicNum ) 13.577 + { PRLangEnv *langEnv; 13.578 + 13.579 + langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum ); 13.580 + langEnv->createTaskHdlr = createTaskHandler; 13.581 + } 13.582 +void 13.583 +PR_SS__register_end_task_handler( RequestHandler endTaskHandler, SlaveVP *seedVP, int32 magicNum ) 13.584 + { PRLangEnv *langEnv; 13.585 + 13.586 + langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum ); 13.587 + langEnv->endTaskHdlr = endTaskHandler; 13.588 + } 13.589 +void 13.590 +PR_SS__register_create_slave_handler( RequestHandler createSlvHandler, SlaveVP *seedVP, int32 magicNum ) 13.591 + { PRLangEnv *langEnv; 13.592 + 13.593 + langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum ); 13.594 + langEnv->createSlaveHdlr = createSlvHandler; 13.595 + } 13.596 +void 13.597 +PR_SS__register_dissipate_slave_handler( RequestHandler dissipateHandler, SlaveVP *seedVP, int32 magicNum ) 13.598 + { PRLangEnv *langEnv; 13.599 + 13.600 + langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum ); 13.601 + langEnv->dissipateSlaveHdlr = dissipateHandler; 13.602 + } 13.603 +void 13.604 +PR_SS__register_request_handler( RequestHandler reqHandler, SlaveVP *seedVP, int32 magicNum ) 13.605 + { PRLangEnv *langEnv; 13.606 + 13.607 + langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum ); 13.608 + langEnv->requestHdlr = reqHandler; 13.609 + } 13.610 +void 13.611 +PR_SS__register_assigner( SlaveAssigner assigner, SlaveVP *seedVP, int32 magicNum ) 13.612 + { PRLangEnv *langEnv; 13.613 + 13.614 + langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum ); 13.615 + langEnv->slaveAssigner = assigner; 13.616 + } 13.617 +void 13.618 +PR_SS__register_shutdown_handler( RequestHandler shutdownHdlr, SlaveVP *seedVP, int32 magicNum ) 13.619 + { PRLangEnv *langEnv; 13.620 + 13.621 + langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum ); 13.622 + langEnv->shutdownHdlr = shutdownHdlr; 13.623 + } 13.624 +/* 13.625 +void 13.626 +PR_SS__register_lang_data_creator( LangDataCreator langDataCreator, 13.627 + SlaveVP *seedVP, int32 magicNum ) 13.628 + { PRLangEnv *langEnv; 13.629 + 13.630 + langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum ); 13.631 + langEnv->langDataCreator = langDataCreator; 13.632 + } 13.633 +void 13.634 +PR_SS__register_lang_data_initializer( LangDataInitializer langDataInitializer, 13.635 + SlaveVP *seedVP, int32 magicNum ) 13.636 + { PRLangEnv *langEnv; 13.637 + 13.638 + langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum ); 13.639 + langEnv->langDataInitializer = langDataInitializer; 13.640 + } 13.641 */ 13.642 13.643 13.644 + 13.645 + 13.646 +/* 13.647 + *This function returns information about the version of PR, the language 13.648 + * the program is being run in, its version, and information on the 13.649 + * hardware. 13.650 + */ 13.651 +char * 13.652 +PRServ___give_environment_string() 13.653 + { char buffer[10000]; 13.654 + int32 j; 13.655 + 13.656 + j = sizeof(int32); //put total num chars here when done 13.657 + //-------------------------- 13.658 + j += sprintf(buffer+j, "#\n# >> Build information <<\n"); 13.659 + j += sprintf(buffer+j, "# GCC VERSION: %d.%d.%d\n",__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__); 13.660 + j += sprintf(buffer+j, "# Build Date: %s %s\n", __DATE__, __TIME__); 13.661 + 13.662 + j += sprintf(buffer+j, "#\n# >> Hardware information <<\n"); 13.663 + j += sprintf(buffer+j, "# Hardware Architecture: "); 13.664 + #ifdef __x86_64 13.665 + j += sprintf(buffer+j, "x86_64"); 13.666 + #endif //__x86_64 13.667 + #ifdef __i386 13.668 + j += sprintf(buffer+j, "x86"); 13.669 + #endif //__i386 13.670 + j += sprintf(buffer+j, "\n"); 13.671 + j += sprintf(buffer+j, "# Number of Cores: %d\n", NUM_CORES); 13.672 + //-------------------------- 13.673 + 13.674 + //PR Plugins 13.675 + j += sprintf(buffer+j, "#\n# >> PR Plugins <<\n"); 13.676 + j += sprintf(buffer+j, "# Language : "); 13.677 + j += sprintf(buffer+j, _LANG_NAME_); 13.678 + j += sprintf(buffer+j, "\n"); 13.679 + //Meta info gets set by calls from the language during its init, 13.680 + // and info registered by calls from inside the application 13.681 + j += sprintf(buffer+j, "# Assigner: %s\n", _PRTopEnv->metaInfo->assignerInfo); 13.682 + 13.683 + //-------------------------- 13.684 + //Application 13.685 + j += sprintf(buffer+j, "#\n# >> Application <<\n"); 13.686 + j += sprintf(buffer+j, "# Name: %s\n", _PRTopEnv->metaInfo->appInfo); 13.687 + j += sprintf(buffer+j, "# Data Set:\n%s\n",_PRTopEnv->metaInfo->inputInfo); 13.688 + 13.689 + ((int32 *)buffer)[0] = j - sizeof(int32); //insert the number of chars 13.690 + //-------------------------- 13.691 + return (char *) &(((int32 *)buffer)[1]); //return pointer to first char 13.692 + } 13.693 + 13.694 void 13.695 -create_masterEnv() 13.696 - { MasterEnv *masterEnv; 13.697 +PR__set_app_info( char *info ) 13.698 + { int32 len; 13.699 + char *copy; 13.700 + len = strlen(info) +1; 13.701 + copy = PR_int__malloc(len); 13.702 + strcpy(copy, info); 13.703 + _PRTopEnv->metaInfo->appInfo = copy; 13.704 + } 13.705 +void 13.706 +PR__set_input_info( char *info ) 13.707 + { int32 len; 13.708 + char *copy; 13.709 + len = strlen(info) +1; 13.710 + copy = PR_int__malloc(len); 13.711 + strcpy(copy, info); 13.712 + _PRTopEnv->metaInfo->inputInfo = copy; 13.713 + } 13.714 + 13.715 + 13.716 + 13.717 + 13.718 + 13.719 + 13.720 +void 13.721 +create_topEnv() 13.722 + { TopEnv *masterEnv; 13.723 PRQueueStruc **readyToAnimateQs; 13.724 - int coreIdx; 13.725 + int32 coreIdx; 13.726 SlaveVP **masterVPs; 13.727 AnimSlot ***allAnimSlots; //ptr to array of ptrs 13.728 13.729 + //Make the top env, which holds everything else 13.730 + _PRTopEnv = malloc( sizeof(TopEnv) ); 13.731 13.732 - //Make the master env, which holds everything else 13.733 - _PRTopEnv = malloc( sizeof(MasterEnv) ); 13.734 - 13.735 - //Very first thing put into the master env is the free-list, seeded 13.736 + //Very first thing put into the top env is the free-list, seeded 13.737 // with a massive initial chunk of memory. 13.738 //After this, all other mallocs are PR__malloc. 13.739 - _PRTopEnv->freeLists = PR_ext__create_free_list(); 13.740 + _PRTopEnv->freeLists = PR_ext__create_free_list(); 13.741 + _PRTopEnv->amtOfOutstandingMem = 0; 13.742 + 13.743 + //===================== Only PR__malloc after this ===================== 13.744 + // 13.745 13.746 + //=================== Both single and multi lang vars ================== 13.747 + // 13.748 + // 13.749 + _PRTopEnv->metaInfo = PR_int__malloc( sizeof(PRSysMetaInfo) ); 13.750 + memset( _PRTopEnv->metaInfo, 0, sizeof(PRSysMetaInfo) ); 13.751 + 13.752 + masterVPs = PR_int__malloc( NUM_CORES * sizeof(SlaveVP *) ); 13.753 + _PRTopEnv->masterVPs = masterVPs; 13.754 13.755 - //===================== Only PR__malloc after this ==================== 13.756 - masterEnv = (MasterEnv*)_PRTopEnv; 13.757 - 13.758 - //Make a readyToAnimateQ for each core controller 13.759 - readyToAnimateQs = PR_int__malloc( NUM_CORES * sizeof(PRQueueStruc *) ); 13.760 - masterVPs = PR_int__malloc( NUM_CORES * sizeof(SlaveVP *) ); 13.761 + allAnimSlots = PR_int__malloc( NUM_CORES * sizeof(AnimSlot *) ); 13.762 + _PRTopEnv->allAnimSlots = allAnimSlots; 13.763 13.764 - //One array for each core, several in array, core's masterVP scheds all 13.765 - allAnimSlots = PR_int__malloc( NUM_CORES * sizeof(AnimSlot *) ); 13.766 - 13.767 - _PRTopEnv->numSlavesAlive = 0; //used to detect shut-down condition 13.768 - 13.769 -//======================================== 13.770 - 13.771 - Copied__fixThis; 13.772 - 13.773 - semEnv->freeExtraTaskSlvQ = makePRQ(); 13.774 - semEnv->numLiveExtraTaskSlvs = 0; //must be last 13.775 - semEnv->numLiveThreadSlvs = 1; //must be last, counts the seed 13.776 - 13.777 - semEnv->shutdownInitiated = FALSE; 13.778 -// semEnv->coreIsDone = PR_int__malloc( NUM_CORES * sizeof( bool32 ) ); 13.779 - 13.780 + //Make the master VPs 13.781 + for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 13.782 + { 13.783 + readyToAnimateQs[ coreIdx ] = makePRQ(); 13.784 + 13.785 + //Q: should give masterVP core-specific info as its init data? 13.786 + masterVPs[ coreIdx ] = PR_int__create_slave( (TopLevelFnPtr)&animationMaster, (void*)_PRTopEnv ); 13.787 + masterVPs[ coreIdx ]->coreAnimatedBy = coreIdx; 13.788 + masterVPs[ coreIdx ]->typeOfVP = Master; 13.789 + allAnimSlots[ coreIdx ] = create_anim_slots( coreIdx ); //makes for one core 13.790 + } 13.791 + 13.792 //For each animation slot, there is an idle slave, and an initial 13.793 // slave assigned as the current-task-slave. Create them here. 13.794 int32 coreNum, slotNum; 13.795 SlaveVP *idleSlv, *slotTaskSlv; 13.796 + 13.797 for( coreNum = 0; coreNum < NUM_CORES; coreNum++ ) 13.798 - { //semEnv->coreIsDone[coreNum] = FALSE; //use during shutdown 13.799 + { //langEnv->coreIsDone[coreNum] = FALSE; //use during shutdown 13.800 13.801 for( slotNum = 0; slotNum < NUM_ANIM_SLOTS; ++slotNum ) 13.802 - { idleSlv = PR__create_slave_helper( &idle_fn, NULL, semEnv, 0); 13.803 + { idleSlv = PR_int__create_slaveVP( &idle_fn, NULL ); 13.804 idleSlv->coreAnimatedBy = coreNum; 13.805 idleSlv->animSlotAssignedTo = 13.806 _PRTopEnv->allAnimSlots[coreNum][slotNum]; 13.807 _PRTopEnv->idleSlv[coreNum][slotNum] = idleSlv; 13.808 13.809 + 13.810 slotTaskSlv = PR_int__create_slot_slave( ); 13.811 slotTaskSlv->coreAnimatedBy = coreNum; 13.812 slotTaskSlv->animSlotAssignedTo = 13.813 _PRTopEnv->allAnimSlots[coreNum][slotNum]; 13.814 13.815 -// slotTaskSlv->needsTaskAssigned = TRUE; 13.816 - slotTaskSlv->slaveType = SlotTaskSlv; 13.817 + slotTaskSlv->typeOfVP = SlotTaskSlv; 13.818 _PRTopEnv->slotTaskSlvs[coreNum][slotNum] = slotTaskSlv; 13.819 } 13.820 } 13.821 13.822 - //create the recycle queue where free task slaves are put after their task ends 13.823 - semEnv->freeTaskSlvRecycleQ = makePRQ(); 13.824 + _PRTopEnv->slaveRecycleQ = makePRQ(); 13.825 13.826 - 13.827 - semEnv->numLiveFreeTaskSlvs = 0; 13.828 - semEnv->numLiveGenericSlvs = 0; //none existent yet.. "create process" creates the seeds 13.829 -//================================================================== 13.830 - 13.831 - _PRTopEnv->numSlavesCreated = 0; //used by create slave to set slave ID 13.832 - for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 13.833 - { 13.834 - readyToAnimateQs[ coreIdx ] = makePRQ(); 13.835 - 13.836 - //Q: should give masterVP core-specific info as its init data? 13.837 - masterVPs[ coreIdx ] = PR_int__create_slaveVP( (TopLevelFnPtr)&animationMaster, (void*)masterEnv ); 13.838 - masterVPs[ coreIdx ]->coreAnimatedBy = coreIdx; 13.839 - masterVPs[ coreIdx ]->typeOfVP = Master; 13.840 - allAnimSlots[ coreIdx ] = create_anim_slots( coreIdx ); //makes for one core 13.841 - } 13.842 - _PRTopEnv->masterVPs = masterVPs; 13.843 _PRTopEnv->masterLock = UNLOCKED; 13.844 _PRTopEnv->seed1 = rand()%1000; // init random number generator 13.845 _PRTopEnv->seed2 = rand()%1000; // init random number generator 13.846 - _PRTopEnv->allAnimSlots = allAnimSlots; 13.847 - _PRTopEnv->measHistsInfo = NULL; 13.848 + 13.849 + _PRTopEnv->measHistsInfo = NULL; 13.850 + 13.851 + _PRTopEnv->numSlavesCreated = 0; //used by create slave to set slave ID 13.852 + 13.853 + //=================== single lang only vars ================== 13.854 + // 13.855 + // 13.856 + _PRTopEnv->numSlavesCreated = 0; //used to give unique ID to processor 13.857 + _PRTopEnv->numTasksCreated = 0; //to give unique ID to a task 13.858 + _PRTopEnv->numSlavesAlive = 0; 13.859 + 13.860 + _PRTopEnv->shutdownInitiated = FALSE; 13.861 + _PRTopEnv->coreIsDone = PR_int__malloc( NUM_CORES * sizeof( bool32 ) ); 13.862 + memset( _PRTopEnv->coreIsDone, 0, NUM_CORES * sizeof( bool32 ) ); 13.863 + 13.864 + //=================== multi lang only vars ================== 13.865 + // 13.866 + // 13.867 + readyToAnimateQs = PR_int__malloc( NUM_CORES * sizeof(PRQueueStruc *) ); 13.868 + 13.869 + _PRTopEnv->processes = PR_int__malloc( NUM_IN_COLLECTION * sizeof(PRProcess *) ); 13.870 + _PRTopEnv->numProcesses = 0; 13.871 + _PRTopEnv->currProcessIdx = 0; 13.872 + _PRTopEnv->firstProcessReady = FALSE; //use while starting up coreCtlr 13.873 + 13.874 + //initialize flags for waiting for activity within PR to complete 13.875 + pthread_mutex_init( _PRTopEnv->activityDoneLock, NULL ); 13.876 + pthread_cond_init( _PRTopEnv->activityDoneCond, NULL ); 13.877 + _PRTopEnv->allActivityIsDone = FALSE; 13.878 13.879 //============================= MEASUREMENT STUFF ======================== 13.880 13.881 @@ -484,6 +703,13 @@ 13.882 } 13.883 13.884 13.885 +/*This is called during PR startup.. It simple creates the OS threads, with the 13.886 + * core controller code as the top level function. 13.887 + *However, there's nothing for these threads to do until a process is created, 13.888 + * so, the core controller has a cond-var and flag in the top env they all 13.889 + * "wait" on. The process creation call includes a singleton that releases 13.890 + * all the core controller threads when the first process is created. 13.891 + */ 13.892 void 13.893 create_the_coreCtlr_OS_threads() 13.894 { 13.895 @@ -494,7 +720,7 @@ 13.896 //Need the threads to be created suspended, and wait for a signal 13.897 // before proceeding -- gives time after creating to initialize other 13.898 // stuff before the coreCtlrs set off. 13.899 - _PRTopEnv->setupComplete = 0; 13.900 + _PRTopEnv->firstProcessReady = 0; 13.901 13.902 //initialize the cond used to make the new threads wait and sync up 13.903 //must do this before *creating* the threads.. 13.904 @@ -516,94 +742,50 @@ 13.905 } 13.906 13.907 13.908 -/*This is what causes the PR system to initialize.. then waits for it to 13.909 - * exit. 13.910 +//========================== SHUT DOWN =========================== 13.911 + 13.912 +/*This is called from the main thread, and causes PR's OS threads to stop 13.913 + * then cleans up any memory allocated by PR from the OS. 13.914 * 13.915 - *Wrapper lib layer calls this when it wants the system to start running.. 13.916 + *The main thread has a separate call it can use to wait for all work to 13.917 + * finish, so when this is called, it just shuts down, whether there's 13.918 + * unfinished work or not. 13.919 + * 13.920 + *However, cores that are performing work won't see this shutdown until 13.921 + * they finish their current work-unit. 13.922 */ 13.923 -/* 13.924 -void 13.925 -PR_SS__start_the_work_then_wait_until_done() 13.926 - { 13.927 -#ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE 13.928 - //Only difference between version with an OS thread pinned to each core and 13.929 - // the sequential version of PR is PR__init_Seq, this, and coreCtlr_Seq. 13.930 - // 13.931 - //Instead of un-suspending threads, just call the one and only 13.932 - // core ctlr (sequential version), in the main thread. 13.933 - coreCtlr_Seq( NULL ); 13.934 - flushRegisters(); 13.935 -#else 13.936 - int coreIdx; 13.937 - //Start the core controllers running 13.938 +PR__shutdown() 13.939 + { int32 coreIdx; 13.940 13.941 - //tell the core controller threads that setup is complete 13.942 - //get lock, to lock out any threads still starting up -- they'll see 13.943 - // that setupComplete is true before entering while loop, and so never 13.944 - // wait on the condition 13.945 - pthread_mutex_lock( &suspendLock ); 13.946 - _PRTopEnv->setupComplete = 1; 13.947 - pthread_mutex_unlock( &suspendLock ); 13.948 - pthread_cond_broadcast( &suspendCond ); 13.949 + PR_SS__shutdown_OS_threads(); 13.950 13.951 - 13.952 - //wait for all to complete 13.953 + //wait for the OS threads to exit 13.954 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) 13.955 { 13.956 pthread_join( coreCtlrThdHandles[coreIdx], NULL ); 13.957 } 13.958 - 13.959 - //NOTE: do not clean up PR env here -- semantic layer has to have 13.960 - // a chance to clean up its environment first, then do a call to free 13.961 - // the Master env and rest of PR locations 13.962 -#endif 13.963 - } 13.964 -*/ 13.965 13.966 -SlaveVP* PR_SS__create_shutdown_slave() 13.967 - { 13.968 - SlaveVP* shutdownVP; 13.969 - 13.970 - shutdownVP = PR_int__create_slaveVP( &endOSThreadFn, NULL ); 13.971 - shutdownVP->typeOfVP = Shutdown; 13.972 - 13.973 - return shutdownVP; 13.974 + //Before getting rid of everything, print out any measurements made 13.975 + PR_SS__print_out_measurements(); 13.976 + 13.977 + //free all memory allocated from the OS 13.978 + PR_SS__cleanup_at_end_of_shutdown(); 13.979 } 13.980 13.981 -//TODO: look at architecting cleanest separation between request handler 13.982 -// and animation master, for dissipate, create, shutdown, and other non-semantic 13.983 -// requests. Issue is chain: one removes requests from AppSlv, one dispatches 13.984 -// on type of request, and one handles each type.. but some types require 13.985 -// action from both request handler and animation master -- maybe just give the 13.986 -// request handler calls like: PR__handle_X_request_type 13.987 13.988 - 13.989 -/*This is called by the semantic layer's request handler when it decides its 13.990 - * time to shut down the PR system. Calling this causes the core controller OS 13.991 - * threads to exit, which unblocks the entry-point function that started up 13.992 - * PR, and allows it to grab the result and return to the original single- 13.993 - * threaded application. 13.994 +/*Calling this causes the core controller OS threads to exit, 13.995 * 13.996 - *The _PRTopEnv is needed by this shut down function, so the create-seed- 13.997 - * and-wait function has to free a bunch of stuff after it detects the 13.998 - * threads have all died: the masterEnv, the thread-related locations, 13.999 - * masterVP any AppSlvs that might still be allocated and sitting in the 13.1000 - * semantic environment, or have been orphaned in the _PRWorkQ. 13.1001 + *The _PRTopEnv is used inside this shut down function, so it wait until 13.1002 + * the OS thread shutdown is done before freeing it. 13.1003 + * 13.1004 + *In here,create one core-loop shut-down slave for each core controller 13.1005 + * and put them all directly into the animation slots. 13.1006 * 13.1007 - *NOTE: the semantic plug-in is expected to use PR__malloc to get all the 13.1008 - * locations it needs, and give ownership to masterVP. Then, they will be 13.1009 - * automatically freed. 13.1010 - * 13.1011 - *In here,create one core-loop shut-down processor for each core controller and put 13.1012 - * them all directly into the readyToAnimateQ. 13.1013 - *Note, this function can ONLY be called after the semantic environment no 13.1014 - * longer cares if AppSlvs get animated after the point this is called. In 13.1015 - * other words, this can be used as an abort, or else it should only be 13.1016 - * called when all AppSlvs have finished dissipate requests -- only at that 13.1017 - * point is it sure that all results have completed. 13.1018 + *Note, this function should ONLY be called after all processes have ended, 13.1019 + * because it doesn't pay attention to whether unfinished work exists.. 13.1020 */ 13.1021 void 13.1022 -PR_SS__shutdown() 13.1023 +PR_SS__shutdown_OS_threads() 13.1024 { int32 coreIdx; 13.1025 SlaveVP *shutDownSlv; 13.1026 AnimSlot **animSlots; 13.1027 @@ -623,6 +805,48 @@ 13.1028 } 13.1029 13.1030 13.1031 +SlaveVP* PR_SS__create_shutdown_slave() 13.1032 + { 13.1033 + SlaveVP* shutdownVP; 13.1034 + 13.1035 + shutdownVP = PR_int__create_slave( &endOSThreadFn, NULL ); 13.1036 + shutdownVP->typeOfVP = Shutdown; 13.1037 + 13.1038 + return shutdownVP; 13.1039 + } 13.1040 + 13.1041 + 13.1042 + 13.1043 +void 13.1044 +PR_SS__print_out_measurements() 13.1045 + { 13.1046 + if( _PRTopEnv->measHistsInfo != NULL ) 13.1047 + { forAllInDynArrayDo( _PRTopEnv->measHistsInfo, (DynArrayFnPtr)&printHist ); 13.1048 + forAllInDynArrayDo( _PRTopEnv->measHistsInfo, (DynArrayFnPtr)&saveHistToFile); 13.1049 + forAllInDynArrayDo( _PRTopEnv->measHistsInfo, (DynArrayFnPtr)&freeHist ); 13.1050 + } 13.1051 + 13.1052 + MEAS__Print_Hists_for_Susp_Meas; 13.1053 + MEAS__Print_Hists_for_Master_Meas; 13.1054 + MEAS__Print_Hists_for_Master_Lock_Meas; 13.1055 + MEAS__Print_Hists_for_Malloc_Meas; 13.1056 + MEAS__Print_Hists_for_Plugin_Meas; 13.1057 + } 13.1058 + 13.1059 +/*This is run in the main thread, as part of the PR__shutdown() call 13.1060 + * It frees any memory allocated from the OS 13.1061 + */ 13.1062 +void 13.1063 +PR_SS__cleanup_at_end_of_shutdown() 13.1064 + { 13.1065 + //All the environment data has been allocated with PR__malloc, so just 13.1066 + // free the memory obtained by PR__malloc, then free the top env. 13.1067 + //These are the only two that use system free 13.1068 + PR_ext__free_free_list( _PRTopEnv->freeLists ); 13.1069 + free( (void *)_PRTopEnv ); 13.1070 + } 13.1071 + 13.1072 + 13.1073 /*Am trying to be cute, avoiding IF statement in coreCtlr that checks for 13.1074 * a special shutdown slaveVP. Ended up with extra-complex shutdown sequence. 13.1075 *This function has the sole purpose of setting the stack and framePtr 13.1076 @@ -646,58 +870,6 @@ 13.1077 #endif 13.1078 } 13.1079 13.1080 - 13.1081 -/*This is called from the startup & shutdown 13.1082 - */ 13.1083 -void 13.1084 -PR_SS__cleanup_at_end_of_shutdown() 13.1085 - { 13.1086 - //Before getting rid of everything, print out any measurements made 13.1087 - if( _PRTopEnv->measHistsInfo != NULL ) 13.1088 - { forAllInDynArrayDo( _PRTopEnv->measHistsInfo, (DynArrayFnPtr)&printHist ); 13.1089 - forAllInDynArrayDo( _PRTopEnv->measHistsInfo, (DynArrayFnPtr)&saveHistToFile); 13.1090 - forAllInDynArrayDo( _PRTopEnv->measHistsInfo, (DynArrayFnPtr)&freeHist ); 13.1091 - } 13.1092 - 13.1093 - MEAS__Print_Hists_for_Susp_Meas; 13.1094 - MEAS__Print_Hists_for_Master_Meas; 13.1095 - MEAS__Print_Hists_for_Master_Lock_Meas; 13.1096 - MEAS__Print_Hists_for_Malloc_Meas; 13.1097 - MEAS__Print_Hists_for_Plugin_Meas; 13.1098 - 13.1099 - 13.1100 - //All the environment data has been allocated with PR__malloc, so just 13.1101 - // free its internal big-chunk and all inside it disappear. 13.1102 -/* 13.1103 - readyToAnimateQs = _PRTopEnv->readyToAnimateQs; 13.1104 - masterVPs = _PRTopEnv->masterVPs; 13.1105 - allAnimSlots = _PRTopEnv->allAnimSlots; 13.1106 - 13.1107 - for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 13.1108 - { 13.1109 - freePRQ( readyToAnimateQs[ coreIdx ] ); 13.1110 - //master Slvs were created external to PR, so use external free 13.1111 - PR_int__dissipate_slaveVP( masterVPs[ coreIdx ] ); 13.1112 - 13.1113 - freeAnimSlots( allAnimSlots[ coreIdx ] ); 13.1114 - } 13.1115 - 13.1116 - PR_int__free( _PRTopEnv->readyToAnimateQs ); 13.1117 - PR_int__free( _PRTopEnv->masterVPs ); 13.1118 - PR_int__free( _PRTopEnv->allAnimSlots ); 13.1119 - 13.1120 - //============================= MEASUREMENT STUFF ======================== 13.1121 - #ifdef PROBES__TURN_ON_STATS_PROBES 13.1122 - freeDynArrayDeep( _PRTopEnv->dynIntervalProbesInfo, &PR_WL__free_probe); 13.1123 - #endif 13.1124 - //======================================================================== 13.1125 -*/ 13.1126 - //These are the only two that use system free 13.1127 - PR_ext__free_free_list( _PRTopEnv->freeLists ); 13.1128 - free( (void *)_PRTopEnv ); 13.1129 - } 13.1130 - 13.1131 - 13.1132 //================================ 13.1133 13.1134
14.1 --- a/PR__WL.c Sun Nov 04 18:39:28 2012 -0800 14.2 +++ b/PR__WL.c Mon Jan 14 15:31:23 2013 -0800 14.3 @@ -1,5 +1,5 @@ 14.4 /* 14.5 - * Copyright 2010 OpenSourceStewardshipFoundation 14.6 + * Copyright 2010 OpenSourceResearchInstitute 14.7 * 14.8 * Licensed under BSD 14.9 */ 14.10 @@ -25,17 +25,27 @@ 14.11 14.12 14.13 14.14 -inline int32 * 14.15 -PR__give_task_ID( SlaveVP *animSlv, int32 magicNumber ) 14.16 +inline 14.17 +int32 * 14.18 +PR__give_ID_from_slave( SlaveVP *animSlv, int32 magicNumber ) 14.19 { 14.20 - return animSlv->metaTask->taskID; 14.21 + return animSlv->ID; 14.22 + } 14.23 + 14.24 +inline 14.25 +int32 * 14.26 +PR__give_ID_from_task( void *_task ) 14.27 + { PRMetaTask task; 14.28 + task = ((PRMetaTask *)_task)[-1]; 14.29 + return task->ID; 14.30 } 14.31 14.32 SlaveVP * 14.33 -PR__give_slave_of_task_ID( int32 *taskID, SlaveVP *animSlv ) 14.34 +PR__give_owner_of_ID( int32 *taskID, SlaveVP *animSlv ) 14.35 { 14.36 - metaTask = lookup( taskID ); 14.37 - return metaTask->slaveAssignedTo; 14.38 + implement_me(); 14.39 + //metaTask = lookup( taskID ); 14.40 + //return metaTask->slaveAssignedTo; 14.41 } 14.42 14.43 /*For this implementation of PR, it may not make much sense to have the 14.44 @@ -52,15 +62,15 @@ 14.45 * to the plugin. 14.46 */ 14.47 void 14.48 -PR_WL__send_create_slaveVP_req( void *semReq, int32 *slvID, SlaveVP *reqstingSlv, 14.49 - int32 magicNum ) 14.50 +PR_WL__send_create_slaveVP_req( void *langReq, CreateHandler handler, 14.51 + int32 *slvID, SlaveVP *reqstingSlv, int32 magicNum ) 14.52 { PRReqst req; 14.53 14.54 req.reqType = SlvCreate; 14.55 req.ID = slvID; 14.56 req.langMagicNumber = magicNum; 14.57 - req.semReq = semReq; 14.58 -// req.nextReqst = reqstingSlv->request; 14.59 + req.langReq = langReq; 14.60 + req.createHdlr = handler; 14.61 reqstingSlv->request = &req; 14.62 14.63 PR_WL__suspend_slaveVP_and_send_req( reqstingSlv ); 14.64 @@ -71,7 +81,7 @@ 14.65 *This adds a request to dissipate, then suspends the processor so that the 14.66 * request handler will receive the request. The request handler is what 14.67 * does the work of freeing memory and removing the processor from the 14.68 - * semantic environment's data structures. 14.69 + * language environment's data structures. 14.70 *The request handler also is what figures out when to shutdown the PR 14.71 * system -- which causes all the core controller threads to die, and returns from 14.72 * the call that started up PR to perform the work. 14.73 @@ -89,10 +99,13 @@ 14.74 * pears -- making that suspend the last thing in the Slv's trace. 14.75 */ 14.76 void 14.77 -PR_WL__send_dissipate_req( SlaveVP *slaveToDissipate ) 14.78 +PR_WL__send_end_slave_req( RequestHandler handler, SlaveVP *slaveToDissipate, 14.79 + int32 magicNum ) 14.80 { PRReqst req; 14.81 14.82 req.reqType = SlvDissipate; 14.83 + req.langMagicNumber = magicNum; 14.84 + req.handler = handler; 14.85 // req.nextReqst = slaveToDissipate->request; 14.86 slaveToDissipate->request = &req; 14.87 14.88 @@ -101,16 +114,16 @@ 14.89 14.90 inline 14.91 void 14.92 -PR_WL__send_create_task_req( TopLevelFn fn, void *initData, void *semReq, 14.93 - int32 *taskID, RequestHandler handler, SlaveVP *animSlv, int32 magicNumber) 14.94 +PR_WL__send_create_task_req( TopLevelFn fn, void *initData, void *langReq, 14.95 + int32 *taskID, CreateHandler handler, SlaveVP *animSlv, int32 magicNumber) 14.96 { PRReqst req; 14.97 14.98 req.reqType = TaskCreate; 14.99 req.topLevelFn = fn; 14.100 req.initData = initData; 14.101 req.ID = taskID; 14.102 - req.semReq = semReq; 14.103 - req.handler = handler; 14.104 + req.langReq = langReq; 14.105 + req.createHdlr = handler; 14.106 req.langMagicNumber = magicNumber; 14.107 animSlv->request = &req; 14.108 14.109 @@ -119,12 +132,12 @@ 14.110 14.111 inline 14.112 void 14.113 -PR_WL__send_end_task_request( void *semReq, RequestHandler handler, 14.114 +PR_WL__send_end_task_request( void *langReq, RequestHandler handler, 14.115 SlaveVP *animSlv, int32 magicNum ) 14.116 { PRReqst req; 14.117 14.118 req.reqType = TaskEnd; 14.119 - req.semReq = semReq; 14.120 + req.langReq = langReq; 14.121 req.handler = handler; 14.122 req.langMagicNumber = magicNum; 14.123 animSlv->request = &req; 14.124 @@ -137,20 +150,20 @@ 14.125 * has to free any extra requests tacked on before a send, using this. 14.126 * 14.127 * This inserts the semantic-layer's request data into standard PR carrier 14.128 - * request data-struct that is mallocd. The sem request doesn't need to 14.129 + * request data-struct that is mallocd. The lang request doesn't need to 14.130 * be malloc'd if this is called inside the same call chain before the 14.131 * send of the last request is called. 14.132 * 14.133 *The request handler has to call PR_int__free_PRReq for any of these 14.134 */ 14.135 inline void 14.136 -PR_WL__add_sem_request_in_mallocd_PRReqst( void *semReqData, 14.137 +PR_WL__add_lang_request_in_mallocd_PRReqst( void *langReqData, 14.138 SlaveVP *callingSlv ) 14.139 { PRReqst *req; 14.140 - 14.141 +//WARNING: not update.. may be buggy 14.142 req = PR_int__malloc( sizeof(PRReqst) ); 14.143 req->reqType = Language; 14.144 - req->semReq = semReqData; 14.145 + req->langReq = langReqData; 14.146 req->nextReqst = callingSlv->request; 14.147 callingSlv->request = req; 14.148 } 14.149 @@ -170,13 +183,14 @@ 14.150 *Then it does suspend, to cause request to be sent. 14.151 */ 14.152 inline void 14.153 -PR_WL__send_sem_request( void *semReqData, SlaveVP *callingSlv, int32 magicNum ) 14.154 +PR_WL__send_lang_request( void *langReqData, RequestHandler handler, 14.155 + SlaveVP *callingSlv, int32 magicNum ) 14.156 { PRReqst req; 14.157 14.158 req.reqType = Language; 14.159 req.langMagicNumber = magicNum; 14.160 - req. 14.161 - req.semReq = semReqData; 14.162 + req.langReq = langReqData; 14.163 + req.handler = handler; 14.164 req.nextReqst = callingSlv->request; 14.165 callingSlv->request = &req; 14.166 14.167 @@ -188,12 +202,12 @@ 14.168 * 14.169 */ 14.170 inline void 14.171 -PR_WL__send_service_request( void *semReqData, SlaveVP *callingSlv ) 14.172 +PR_WL__send_service_request( void *langReqData, SlaveVP *callingSlv ) 14.173 { PRReqst req; 14.174 14.175 - req.reqType = PRLang; 14.176 - req.langMagicNumber = PRLang_MAGIC_NUMBER; 14.177 - req.semReq = semReqData; 14.178 + req.reqType = Service; 14.179 + req.langMagicNumber = PRServ_MAGIC_NUMBER; 14.180 + req.langReq = langReqData; 14.181 req.nextReqst = callingSlv->request; //grab any other preceeding 14.182 callingSlv->request = &req; 14.183 14.184 @@ -207,15 +221,15 @@ 14.185 void 14.186 PR_WL__throw_exception( char *msgStr, SlaveVP *reqstSlv, PRExcp *excpData ) 14.187 { PRReqst req; 14.188 - PRServReq semReq; 14.189 + PRServReq langReq; 14.190 14.191 - req.reqType = PRSemantic; 14.192 - req.semReq = &semReq; 14.193 + req.reqType = Language; 14.194 + req.langReq = &langReq; 14.195 req.nextReqst = reqstSlv->request; //gab any other preceeding 14.196 reqstSlv->request = &req; 14.197 14.198 - semReq.msgStr = msgStr; 14.199 - semReq.exceptionData = excpData; 14.200 + langReq.msgStr = msgStr; 14.201 + langReq.exceptionData = excpData; 14.202 14.203 PR_WL__suspend_slaveVP_and_send_req( reqstSlv ); 14.204 }
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/PR__WL.h Mon Jan 14 15:31:23 2013 -0800 15.3 @@ -0,0 +1,122 @@ 15.4 +/* 15.5 + * Copyright 2009 OpenSourceResearchInstitute.org 15.6 + * Licensed under GNU General Public License version 2 15.7 + * 15.8 + * Author: seanhalle@yahoo.com 15.9 + * 15.10 + */ 15.11 + 15.12 +#ifndef _PR__WL_H 15.13 +#define _PR__WL_H 15.14 +#define _GNU_SOURCE 15.15 + 15.16 +#include "PR_primitive_data_types.h" 15.17 +#include "PR__structs.h" 15.18 +//========================= Function Prototypes =========================== 15.19 +/* MEANING OF WL PI SS int PROS 15.20 + * These indicate which places the function is safe to use. They stand for: 15.21 + * 15.22 + * WL Wrapper Library -- wrapper lib code should only use these 15.23 + * PI Plugin -- plugin code should only use these 15.24 + * SS Startup and Shutdown -- designates these relate to startup & shutdown 15.25 + * int32internal to PR -- should not be used in wrapper lib or plugin 15.26 + * PROS means "OS functions for applications to use" 15.27 + * 15.28 + * PR_int__ functions touch internal PR data structs and are only safe 15.29 + * to be used inside the master lock. However, occasionally, they appear 15.30 + * in wrapper-lib or plugin code. In those cases, very careful analysis 15.31 + * has been done to be sure no concurrency issues could arise. 15.32 + * 15.33 + * PR_WL__ functions are all safe for use outside the master lock. 15.34 + * 15.35 + * PROS are only safe for applications to use -- they're like a second 15.36 + * language mixed in -- but they can't be used inside plugin code, and 15.37 + * aren't meant for use in wrapper libraries, because they are themselves 15.38 + * wrapper-library calls! 15.39 + */ 15.40 +//========== Startup and shutdown ========== 15.41 +void 15.42 +PR__start(); 15.43 + 15.44 +SlaveVP* 15.45 +PR_SS__create_shutdown_slave(); 15.46 + 15.47 +void 15.48 +PR_SS__shutdown(); 15.49 + 15.50 +void 15.51 +PR_SS__cleanup_at_end_of_shutdown(); 15.52 + 15.53 +void 15.54 +PR_SS__register_langlets_langEnv( PRLangEnv *langEnv, SlaveVP *seedVP, int32 VSs_MAGIC_NUMBER ); 15.55 + 15.56 +//============== include internally used fn prototypes ================ 15.57 +#include "PR__int.h" 15.58 + 15.59 +//============== =============== 15.60 + 15.61 +inline 15.62 +SlaveVP * 15.63 +PR_PI__give_slave_lang_meta_task_assigned_to( void *langMetaTask ); 15.64 + 15.65 +//============== Request Related =============== 15.66 + 15.67 +void 15.68 +PR_WL__suspend_slaveVP_and_send_req( SlaveVP *callingSlv ); 15.69 + 15.70 +inline void 15.71 +PR_WL__add_lang_request_in_mallocd_PRReqst( void *langReqData, 15.72 + SlaveVP *callingSlv ); 15.73 + 15.74 +inline void 15.75 +PR_WL__send_lang_request( void *langReq, SlaveVP *callingSlv, int32 magicNum ); 15.76 + 15.77 +void 15.78 +PR_WL__send_create_slaveVP_req( void *langReq, CreateHandler handler, 15.79 + int32 *slvID, SlaveVP *reqstingSlv, int32 magicNum ); 15.80 + 15.81 +void inline 15.82 +PR_WL__send_end_slave_req( SlaveVP *prToDissipate, int32 magicNum ); 15.83 + 15.84 +inline void 15.85 +PR_WL__send_service_request( void *langReqData, SlaveVP *callingSlv ); 15.86 + 15.87 +PRReqst * 15.88 +PR_PI__take_next_request_out_of( SlaveVP *slaveWithReq ); 15.89 +//#define PR_PI__take_next_request_out_of( slave ) slave->requests 15.90 + 15.91 +//inline void * 15.92 +//PR_PI__take_lang_reqst_from( PRReqst *req ); 15.93 +#define PR_PI__take_lang_reqst_from( req ) req->langReqData 15.94 + 15.95 +//======================== MEASUREMENT ====================== 15.96 +uint64 15.97 +PR_WL__give_num_plugin_cycles(); 15.98 +uint32 15.99 +PR_WL__give_num_plugin_animations(); 15.100 + 15.101 + 15.102 +//========================= Utilities ======================= 15.103 +void 15.104 +PR_WL__throw_exception( char *msgStr, SlaveVP *reqstSlv, PRExcp *excpData ); 15.105 +#define PR_App__throw_exception PR_WL__throw_exception 15.106 + 15.107 +#define implement_me printf("Unimpl Fn: \n%s \n%s : %s\n", __FILE__, __FUNCTION__, __LINE__) 15.108 +//#define fix_me printf("Fix me at: \n%s \n%s : %s\n", __FILE__, __FUNCTION__, __LINE__) 15.109 + 15.110 +//========================= PR request handlers ======================== 15.111 +void inline 15.112 +handleMakeProbe( PRServReq *langReq, void *langEnv ); 15.113 + 15.114 +void inline 15.115 +handleThrowException( PRServReq *langReq, void *langEnv ); 15.116 +//======================================================================= 15.117 + 15.118 +//========================= Services ======================= 15.119 +//#include "Services_Offered_by_PR/Measurement_and_Stats/probes.h" 15.120 +//#include "Services_Offered_by_PR/Services_Language/PRServ.h" 15.121 +//#include "Services_Offered_by_PR/Services_Language/libPRServ.h" 15.122 + 15.123 +//================================================ 15.124 +#endif /* _PR_H */ 15.125 +
16.1 --- a/PR__int.c Sun Nov 04 18:39:28 2012 -0800 16.2 +++ b/PR__int.c Mon Jan 14 15:31:23 2013 -0800 16.3 @@ -1,5 +1,5 @@ 16.4 /* 16.5 - * Copyright 2010 OpenSourceStewardshipFoundation 16.6 + * Copyright 2010 OpenSourceResearchInstitute 16.7 * 16.8 * Licensed under BSD 16.9 */ 16.10 @@ -25,48 +25,26 @@ 16.11 //=========================================================================== 16.12 // 16.13 //=========================================================================== 16.14 - 16.15 -inline SlaveVP * 16.16 -PR_int__create_slaveVP( TopLevelFnPtr fnPtr, void *dataParam, PRProcess *process ) 16.17 +inline 16.18 +SlaveVP * 16.19 +PR_int__create_slaveVP( TopLevelFnPtr fnPtr, void *dataParam ) 16.20 { SlaveVP *newSlv; 16.21 void *stackLocs; 16.22 - 16.23 - PR_int__create_slaveVP_helper( fnPtr, dataParam ); 16.24 - 16.25 - process->numLiveGenericSlvs += 1; 16.26 - 16.27 -// newSlv->needsTaskAssigned = TRUE; 16.28 - newSlv->metaTask = NULL; 16.29 - newSlv->typeOfVP = GenericSlave; 16.30 16.31 - return newSlv; 16.32 - } 16.33 - 16.34 - 16.35 -inline SlaveVP * 16.36 -PR_int__create_slaveVP_helper( TopLevelFnPtr fnPtr, void *dataParam ) 16.37 - { SlaveVP *newSlv; 16.38 - void *stackLocs; 16.39 - 16.40 newSlv = PR_int__malloc( sizeof(SlaveVP) ); 16.41 stackLocs = PR_int__malloc( VIRT_PROCR_STACK_SIZE ); 16.42 if( stackLocs == 0 ) 16.43 { perror("PR_int__malloc stack"); exit(1); } 16.44 16.45 newSlv->startOfStack = stackLocs; 16.46 - newSlv->slaveID = _PRTopEnv->numSlavesCreated++; 16.47 + newSlv->slaveNum = _PRTopEnv->numSlavesCreated++; 16.48 newSlv->request = NULL; 16.49 newSlv->animSlotAssignedTo = NULL; 16.50 16.51 newSlv->numTimesAssignedToASlot = 0; 16.52 16.53 - #ifdef MODE__MULTI_LANG 16.54 - PRSemDataHolder * 16.55 - semDataHolder = PR_int__malloc( sizeof(PRSemDataHolder) ); 16.56 - newSlv->semanticData = semDataHolder; 16.57 - #else 16.58 - newSlv->semanticData = NULL; 16.59 - #endif 16.60 + newSlv->langData = NULL; 16.61 + newSlv->metaTask = NULL; 16.62 16.63 PR_int__reset_slaveVP_to_TopLvlFn( newSlv, fnPtr, dataParam ); 16.64 16.65 @@ -80,13 +58,138 @@ 16.66 #endif 16.67 //======================================================================== 16.68 16.69 + newSlv->typeOfVP = GenericSlave; 16.70 + 16.71 return newSlv; 16.72 } 16.73 16.74 +inline 16.75 SlaveVP * 16.76 -PR_int__create_slot_slave() 16.77 - { 16.78 - fixme; 16.79 +PR_int__create_slaveVP__ML( TopLevelFnPtr fnPtr, void *dataParam, PRProcess *process ) 16.80 + { SlaveVP *newSlv; 16.81 + 16.82 + newSlv = PR_int__create_slaveVP( fnPtr, dataParam ); 16.83 + 16.84 + int32 * 16.85 + langDatas = PR_int__malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRLangData *) ); 16.86 + langDatas[0] = NUM_IN_COLLECTION; //size held in prolog 16.87 + newSlv->langData = &(langDatas[1]); //skip over the size 16.88 + 16.89 + int32 * 16.90 + metaTasks = PR_int__malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRMetaTask *) ); 16.91 + metaTasks[0] = NUM_IN_COLLECTION; //size held in prolog 16.92 + newSlv->metaTask = &(metaTasks[1]); 16.93 + 16.94 + process->numLiveGenericSlvs += 1; 16.95 + } 16.96 + 16.97 + 16.98 +/* 16.99 + */ 16.100 +/* 16.101 +inline 16.102 +SlaveVP * 16.103 +PR_int__create_seed_slave__ML( TopLevelFnPtr fnPtr, void *dataParam, PRProcess *process ) 16.104 + { SlaveVP *newSlv; 16.105 + 16.106 + newSlv = PR_int__create_slaveVP( fnPtr, dataParam ); 16.107 + 16.108 + int32 * 16.109 + langDatas = PR_int__malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRLangData *) ); 16.110 + langDatas[0] = NUM_IN_COLLECTION; //size held in prolog 16.111 + newSlv->langData = &(langDatas[1]); //skip over the size 16.112 + 16.113 + int32 * 16.114 + metaTasks = PR_int__malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRMetaTask *) ); 16.115 + metaTasks[0] = NUM_IN_COLLECTION; //size held in prolog 16.116 + newSlv->metaTask = &(metaTasks[1]); //make slave point to array 16.117 + 16.118 + newSlv->typeOfVP = SeedSlv; 16.119 + process->numLiveGenericSlvs = 1; 16.120 + } 16.121 +*/ 16.122 + 16.123 + 16.124 +/*Called when a new slot slave is needed.. takes from recycle pool, and 16.125 + * sets the slave up to be a slot slave -- no lang data array, no meta task 16.126 + * array. 16.127 + */ 16.128 +SlaveVP * 16.129 +PR_int__get_recycled_slot_slave( ) 16.130 + { SlaveVP *retSlv; 16.131 + 16.132 + //take slave from recycle Q 16.133 + retSlv = readPrivQ( _PRTopEnv->slaveRecycleQ ); 16.134 + 16.135 + if( retSlv != NULL ) 16.136 + { 16.137 + //set slave up with slot-slave's initial values. 16.138 + retSlv->typeOfVP = SlotTaskSlv; 16.139 + retSlv->slaveNum = _PRTopEnv->numSlavesCreated++; 16.140 + retSlv->numTimesAssignedToASlot = 0; 16.141 + retSlv->request = NULL; 16.142 + } 16.143 + else //if none to recycle, create a new one 16.144 + { retSlv = PR_int__create_slaveVP_helper( &idle_fn, NULL ); 16.145 + retSlv->typeOfVP = SlotTaskSlv; 16.146 + } 16.147 + 16.148 + return retSlv; 16.149 + } 16.150 + 16.151 +/*A slot slave has no array for lang data nor meta tasks -- it only ever has 16.152 + * one meta task.. 16.153 + */ 16.154 +SlaveVP * 16.155 +PR_int__create_slot_slave( ) 16.156 + { SlaveVP *retSlv; 16.157 + 16.158 + retSlv = PR_int__create_slaveVP_helper( &idle_fn, NULL ); 16.159 + retSlv->typeOfVP = SlotTaskSlv; 16.160 + 16.161 + return retSlv; 16.162 + } 16.163 + 16.164 +//========================================================================== 16.165 +/*When a task in a slot slave suspends, the slot slave has to be changed to 16.166 + * a free task slave, then the slot slave replaced. The replacement can be 16.167 + * either a recycled free task slave that finished it's task and has been 16.168 + * idle in the recycle queue, or else create a new slave to be the slot slave. 16.169 + *The master only calls this with a slot slave that needs to be replaced. 16.170 + */ 16.171 +inline void 16.172 +PR_int__replace_with_new_slot_slv( SlaveVP *requestingSlv, PRProcess *process ) 16.173 + { SlaveVP *newSlotSlv; 16.174 + 16.175 + //get a new slave to be the slot slave 16.176 + newSlotSlv = PR_int__get_recycled_slot_slave( process ); 16.177 + 16.178 + //a slot slave is pinned to a particular slot on a particular core 16.179 + //Note, this happens before the request is seen by handler, so nothing 16.180 + // has had a chance to change the coreAnimatedBy or anything else.. 16.181 + newSlotSlv->animSlotAssignedTo = requestingSlv->animSlotAssignedTo; 16.182 + newSlotSlv->coreAnimatedBy = requestingSlv->coreAnimatedBy; 16.183 + 16.184 + //put it into the slot slave matrix 16.185 + int32 slotNum = requestingSlv->animSlotAssignedTo->slotIdx; 16.186 + int32 coreNum = requestingSlv->coreAnimatedBy; 16.187 + _PRTopEnv->slotTaskSlvs[coreNum][slotNum] = newSlotSlv; 16.188 + 16.189 + //Fix up requester, to be an extra slave now (but not an ended one) 16.190 + // because it's active, doesn't go into freeTaskSlvRecycleQ 16.191 + requestingSlv->typeOfVP = FreeTaskSlv; 16.192 + requestingSlv->processSlaveIsIn = process; 16.193 + 16.194 + 16.195 + int32 * 16.196 + langDatas = PR_int__malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRLangData *) ); 16.197 + langDatas[0] = NUM_IN_COLLECTION; //size held in prolog 16.198 + newSlotSlv->langData = &(langDatas[1]); //skip over the size 16.199 + 16.200 + int32 * 16.201 + metaTasks = PR_int__malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRMetaTask *) ); 16.202 + metaTasks[0] = NUM_IN_COLLECTION; //size held in prolog 16.203 + newSlotSlv->metaTask = &(metaTasks[1]); 16.204 } 16.205 16.206 void idle_fn(void* data, SlaveVP *animatingSlv) 16.207 @@ -97,47 +200,6 @@ 16.208 } 16.209 16.210 16.211 -PRMetaTask * 16.212 -PR_int__create_generic_slave_meta_task( void *initData ) 16.213 - { PRMetaTask *newStub; 16.214 - 16.215 - newStub = PR_PI__malloc( sizeof(PRMetaTask) ); 16.216 - newStub->slaveAssignedTo = NULL; //set later 16.217 - newStub->taskType = IS_A_GENERIC_SLV; 16.218 - newStub->taskID = NULL; 16.219 - 16.220 - return newStub; 16.221 - } 16.222 - 16.223 -/*This calls recycle handler registered for each langlet's sem data and meta 16.224 - * task. It also recycles the slave struct. 16.225 - * 16.226 - *This assumes that each slave has an array of 16.227 - */ 16.228 -void 16.229 -PR_int__recycle_slave_multilang( SlaveVP *slave ) 16.230 - { int32 semDataIdx, numSemDatas; 16.231 - PRSemDataHolder *semDataHolder; 16.232 - PRSemData *protoSemData, **semDatas; 16.233 - 16.234 - semDataHolder = (PRSemDataHolder *)slave->semanticData; 16.235 - semDatas = semDataHolder->semDatasIter; 16.236 - 16.237 - for( semDataIdx = 0; semDataIdx < numSemDatas; semDataIdx++ ) 16.238 - { protoSemData = semDatas[ semDataIdx ]; 16.239 - //instead of looking up the semEnv, just put ptr to recycler in protoSemData 16.240 - //To get by without, must iter through hash table.. 16.241 - (*protoSemData->recycler)(protoSemData->langSemData); 16.242 - } 16.243 - for( metaTaskIdx = 0; metaTaskIdx < numMetaTasks; metaTaskIdx++ ) 16.244 - { protoMetaTask = metaTasks[ metaTaskIdx ]; 16.245 - //instead of looking up the semEnv, just put ptr to recycler in protoSemData 16.246 - (*protoMetaTask->recycler)(protoMetaTask->langMetaTask); 16.247 - } 16.248 - 16.249 - writePrivQ( slave, slave->processSlaveIsIn->freeTaskSlvRecycleQ ); 16.250 - } 16.251 - 16.252 16.253 /* This is for OS requests and PR infrastructure requests, such as to create 16.254 * a probe -- a probe is inside the heart of PR-core, it's not part of any 16.255 @@ -145,26 +207,27 @@ 16.256 * in the application.. so it crosses abstractions.. so, need some special 16.257 * pattern here for handling such requests. 16.258 * Doing this just like it were a second language sharing PR-core. 16.259 - * 16.260 - * This is called from the language's request handler when it sees a request 16.261 - * of type PRSemReq 16.262 - * 16.263 - * TODO: Later change this, to give probes their own separate plugin & have 16.264 - * PR-core steer the request to appropriate plugin 16.265 - * Do the same for OS calls -- look later at it.. 16.266 */ 16.267 void inline 16.268 -PR_int__handle_PRServiceReq( PRReqst *req, SlaveVP *requestingSlv, void *semEnv, 16.269 - ResumeSlvFnPtr resumeFn ) 16.270 - { PRServReq *semReq; 16.271 +PR_int__handle_PRServiceReq( SlaveVP *requestingSlv ) 16.272 + { PRReqst *req; 16.273 + PRServReq *langReq; 16.274 + void *langEnv; 16.275 + int32 magicNumber; 16.276 + 16.277 + 16.278 + req = requestingSlv->request; 16.279 + 16.280 + magicNumber = req->langMagicNumber; 16.281 + langEnv = PR_PI__give_lang_env_for( slave, magicNumber ); 16.282 16.283 - semReq = PR_PI__take_sem_reqst_from(req); 16.284 - if( semReq == NULL ) return; 16.285 - switch( semReq->reqType ) //sem handlers are all in other file 16.286 + langReq = PR_PI__take_lang_reqst_from(req); 16.287 + if( langReq == NULL ) return; 16.288 + switch( langReq->reqType ) //lang handlers are all in other file 16.289 { 16.290 - case make_probe: handleMakeProbe( semReq, semEnv, resumeFn); 16.291 + case make_probe: handleMakeProbe( langReq, langEnv ); 16.292 break; 16.293 - case throw_excp: handleThrowException( semReq, semEnv, resumeFn); 16.294 + case throw_excp: handleThrowException( langReq, langEnv ); 16.295 break; 16.296 } 16.297 } 16.298 @@ -189,7 +252,7 @@ 16.299 //return ownership of the Slv and anim slot to Master virt pr 16.300 animatingSlv->animSlotAssignedTo->workIsDone = TRUE; 16.301 16.302 - HOLISTIC__Record_HwResponderInvocation_start; 16.303 + HOLISTIC__Record_HwResponderInvocation_start; 16.304 MEAS__Capture_Pre_Susp_Point; 16.305 //This assembly function is a PR primitive that first saves the 16.306 // stack and frame pointer, plus an addr inside this assembly code. 16.307 @@ -226,9 +289,9 @@ 16.308 * of dis-owning it. 16.309 */ 16.310 void 16.311 -PR_int__dissipate_slaveVP( SlaveVP *animatingSlv ) 16.312 +PR_int__dissipate_slaveVP__SL( SlaveVP *animatingSlv ) 16.313 { 16.314 - DEBUG__printf2(dbgRqstHdlr, "PR int dissipate slaveID: %d, alive: %d",animatingSlv->slaveID, _PRTopEnv->numSlavesAlive-1); 16.315 + DEBUG__printf2(dbgRqstHdlr, "PR int dissipate slaveNum: %d, alive: %d",animatingSlv->slaveNum, _PRTopEnv->numSlavesAlive-1); 16.316 //dis-own all locations owned by this processor, causing to be freed 16.317 // any locations that it is (was) sole owner of 16.318 _PRTopEnv->numSlavesAlive -= 1; 16.319 @@ -247,116 +310,466 @@ 16.320 PR_int__free( animatingSlv ); 16.321 } 16.322 16.323 -/*In multi-lang mode, there are multiple semData in the slave.. 16.324 + 16.325 +/*In multi-lang mode, there are multiple langData in the slave.. 16.326 * 16.327 *At some point want to recycle rather than free.. 16.328 * 16.329 - *For now, iterate through semData, call registered free-er on each, then 16.330 + *For now, iterate through langData, call registered free-er on each, then 16.331 * free the basic slave 16.332 */ 16.333 void 16.334 -PR_int__dissipate_slaveVP_multilang( SlaveVP *slave ) 16.335 - { PRSemDataHolder *semDataHolder; 16.336 - PRSemDataTemplate *semData; 16.337 - int32 idx; 16.338 +PR_int__free_slaveVP__ML( SlaveVP *slave ) 16.339 + { 16.340 + PR_int__apply_Fn_to_all_in_collection( &recycleLangDataAsElem, 16.341 + (PRCollElem**) slave->langData ); 16.342 + PR_int__apply_Fn_to_all_in_collection( &recycleMetaTaskAsElem, 16.343 + (PRCollElem**) slave->metaTask ); 16.344 16.345 - semDataHolder = (PRSemDataHolder *)slave->semanticData; 16.346 - for(idx = 0; idx < semDataHolder->numSemDatas; idx++) 16.347 - { 16.348 - semData = semDataHolder->semDatas[idx]; 16.349 - (*(semData->freeFn))(semData); //this Fn is lang-spec 16.350 - } 16.351 - 16.352 + PR_int__free( &(((int32*)(slave->langData))[-1]) ); 16.353 + PR_int__free( &(((int32*)(slave->metaTask))[-1]) ); 16.354 PR_int__free( slave->startOfStack ); 16.355 PR_int__free( slave ); 16.356 } 16.357 16.358 -inline 16.359 -void * 16.360 -PR_int__give_sem_env_of_req( PRReqst *req, SlaveVP *requestingSlv ) 16.361 - { 16.362 - return PR_int__give_sem_env_for_process( requestingSlv->processSlaveIsIn, 16.363 - req->langMagicNumber ); 16.364 +/*This calls recycle handler registered for each langlet's lang data and meta 16.365 + * task. It also recycles the slave struct. 16.366 + * 16.367 + *This assumes that each slave has an array of 16.368 + */ 16.369 +void 16.370 +PR_int__recycle_slave__ML( SlaveVP *slave ) 16.371 + { 16.372 + PR_int__apply_Fn_to_all_in_collection( &recycleLangDataAsElem, 16.373 + (PRCollElem**) slave->langData ); 16.374 + PR_int__apply_Fn_to_all_in_collection( &recycleMetaTaskAsElem, 16.375 + (PRCollElem**) slave->metaTask ); 16.376 + 16.377 + writePrivQ( slave, _PRTopEnv->slaveRecycleQ ); 16.378 } 16.379 16.380 -/*Anticipating multi-tasking 16.381 - */ 16.382 -inline 16.383 +void 16.384 +recycleLangDataAsElem( void *elem ) 16.385 + { PRLangData *langData; 16.386 + 16.387 + langData = (PRLangData *)elem; //recycler receives the prolog, and must call 16.388 + //a PR Fn to convert prolog to lang-specific version. 16.389 + 16.390 + //apply the recycle fn that's stored in the lang data prolog 16.391 + (*(langData->recycler))(langData); //lang registered the recycler 16.392 + } 16.393 + 16.394 +void 16.395 +recycleMetaTaskAsElem( void *elem ) 16.396 + { PRMetaTask *metaTask; 16.397 + 16.398 + metaTask = (PRMetaTask *)elem; //recycler receives the prolog, and must call 16.399 + //a PR Fn to convert prolog to lang-specific version. 16.400 + 16.401 + //apply the recycle fn that's stored in the lang data prolog 16.402 + (*(metaTask->recycler))(metaTask); //lang registered the recycler 16.403 + } 16.404 + 16.405 + 16.406 + 16.407 +//====================================== 16.408 +inline 16.409 void * 16.410 -PR_int__give_sem_env_for_slave( SlaveVP *slave, int32 magicNum ) 16.411 - { 16.412 - return PR_int__give_sem_env_for_process( slave->processSlaveIsIn, magicNum ); 16.413 +PR_int__give_lang_env( PRLangEnv *protoLangEnv ) 16.414 + { 16.415 + return (void *) &(protoLangEnv[1]); 16.416 } 16.417 -inline 16.418 -PRSemEnv * 16.419 -PR_int__give_proto_sem_env_for_slave( SlaveVP *slave, int32 magicNum ) 16.420 - { 16.421 - return PR_int__give_proto_sem_env_for_process( slave->processSlaveIsIn, magicNum ); 16.422 +inline 16.423 +PRLangEnv * 16.424 +PR_int__give_proto_lang_env( void *langEnv ) 16.425 + { 16.426 + return (PRLangEnv *) &(((PRLangEnv *)langEnv)[-1]); 16.427 } 16.428 16.429 inline 16.430 void * 16.431 -PR_int__give_sem_env_for_process( PRProcess *process, int32 magicNum ) 16.432 - { PRSemEnv *protoSemEnv; 16.433 - 16.434 - protoSemEnv = lookup_proto_sem_env_in_array( process->semEnvs, magicNum ); 16.435 - return protoSemEnv->langSemEnv; 16.436 - } 16.437 -inline 16.438 -PRSemEnv * 16.439 -PR_int__give_proto_sem_env_for_process( PRProcess *process, int32 magicNum ) 16.440 - { 16.441 - return lookup_proto_sem_env_in_array( process->semEnvs, magicNum ); 16.442 +PR_int__create_lang_env_in_process( int32 size, PRProcess process, int32 magicNum ) 16.443 + { PRLangEnv *retEnv; 16.444 + PRCollElem **langEnvs; 16.445 + 16.446 + //make the new lang env, with room for the prolog 16.447 + retEnv = PR_int__malloc( sizeof(PRLangEnv) + size ); 16.448 + 16.449 + //process has a PR Collection of lang envs -- get it and insert into it 16.450 + langEnvs = (PRCollElem **)process->langEnvs; 16.451 + PR_int__insert_elem_into_collection( (PRCollElem *)retEnv, langEnvs, magicNum); 16.452 + int32 idxInProcess = process->numLangEnvs; 16.453 + process->langEnvsList[idxInProcess] = retEnv; 16.454 + retEnv->idxInProcess = idxInProcess; 16.455 + process->numLangEnvs += 1; 16.456 + 16.457 + return &(retEnv[1]); //skip over prolog 16.458 } 16.459 16.460 inline 16.461 -PRSemEnv * 16.462 -lookup_proto_sem_env_in_array( PRSemEnv *semEnvs, int32 magicNum ) 16.463 - { PRSemEnv *retEnv; 16.464 - int32 idx; 16.465 +void * 16.466 +PR_int__free_lang_env( void *langEnv ) 16.467 + { PRLangEnv *protoLangEnv = PR_int__give_proto_lang_env( langEnv ); 16.468 + PRCollElem **langEnvs; 16.469 + PRLangEnv **langEnvsList; 16.470 + 16.471 + //process has a PR Collection of lang envs -- get it and remove env 16.472 + PRProcess *process = protoLangEnv->processEnvIsIn; 16.473 + langEnvs = (PRCollElem **)process->langEnvs; 16.474 + PR_int__remove_elem_from_collection( (PRCollElem *)protoLangEnv, langEnvs ); 16.475 + int32 count, idx; 16.476 + idx = protoLangEnv->idxInProcess; 16.477 + count = (process->numLangEnvs - idx - 1) * sizeof(PRLangEnv *); 16.478 + memmove( langEnvsList[idx], langEnvsList[idx+1], count); 16.479 + 16.480 + PR_int__free( protoLangEnv ); 16.481 + } 16.482 + 16.483 +inline 16.484 +void * 16.485 +PR_int__give_lang_env_of_req__ML( PRReqst *req, SlaveVP *requestingSlv ) 16.486 + { 16.487 + return PR_int__give_lang_env_from_process( requestingSlv->processSlaveIsIn, 16.488 + req->langMagicNumber ); 16.489 + } 16.490 + 16.491 +inline 16.492 +void * 16.493 +PR_int__give_lang_env_for_slave__ML( SlaveVP *slave, int32 magicNum ) 16.494 + { 16.495 + return PR_int__give_lang_env_from_process( slave->processSlaveIsIn, magicNum ); 16.496 + } 16.497 +inline 16.498 +PRLangEnv * 16.499 +PR_int__give_proto_lang_env_for_slave__ML( SlaveVP *slave, int32 magicNum ) 16.500 + { 16.501 + return PR_int__give_proto_lang_env_for_process( slave->processSlaveIsIn, magicNum ); 16.502 + } 16.503 + 16.504 +inline 16.505 +void * 16.506 +PR_int__give_lang_env_from_process( PRProcess *process, int32 magicNum ) 16.507 + { PRLangEnv *retLangEnv; 16.508 + PRCollElem **langEnvs; 16.509 + 16.510 + langEnvs = (PRCollElem **)process->langEnvs; 16.511 + retLangEnv = PR_int__lookup_elem_in_collection( magicNum, langEnvs ); 16.512 + if( retLangEnv != NULL ) 16.513 + return &(retLangEnv[1]); //skip over prolog 16.514 + else 16.515 + return NULL; 16.516 + } 16.517 +inline 16.518 +PRLangEnv * 16.519 +PR_int__give_proto_lang_env_for_process( PRProcess *process, int32 magicNum ) 16.520 + { PRLangEnv *retLangEnv; 16.521 + PRCollElem **langEnvs; 16.522 + 16.523 + langEnvs = (PRCollElem **)process->langEnvs; 16.524 + retLangEnv = PR_int__lookup_elem_in_collection( magicNum, langEnvs ); 16.525 + return retLangEnv; //return prolog 16.526 + } 16.527 + 16.528 +inline 16.529 +void 16.530 +PR_int__set_work_in_lang_env( void *_langEnv ) 16.531 + { PRLangEnv *protoLangEnv = &(((PRLangEnv *)_langEnv)[-1]); //go to the prolog 16.532 + if( protoLangEnv->hasWork != TRUE ) 16.533 + { protoLangEnv->hasWork = TRUE; 16.534 + protoLangEnv->processEnvIsIn->numEnvsWithWork += 1; 16.535 + } 16.536 + } 16.537 +inline 16.538 +void 16.539 +PR_int__clear_work_in_lang_env( void *_langEnv ) 16.540 + { PRLangEnv *prototLangEnv = &(((PRLangEnv *)_langEnv)[-1]); //back up addr to the prolog 16.541 + 16.542 + if( prototLangEnv->hasWork != FALSE ) 16.543 + { prototLangEnv->hasWork = FALSE; 16.544 + prototLangEnv->processEnvIsIn->numEnvsWithWork -= 1; 16.545 + } 16.546 + } 16.547 + 16.548 +/*This is to be called by langlet's assigner. 16.549 + */ 16.550 +inline 16.551 +void 16.552 +PR_int__put_slave_into_slot( SlaveVP *slave, AnimSlot *slot ) 16.553 + { 16.554 + slave->coreAnimatedBy = slot->coreSlotIsOn; 16.555 + //if work found, put into slot, and adjust flags and state 16.556 + slot->slaveAssignedToSlot = slave; 16.557 + slave->animSlotAssignedTo = slot; 16.558 + slot->needsWorkAssigned = FALSE; 16.559 + 16.560 + #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 16.561 + //have a slave to be assigned to the slot 16.562 + //assignSlv->numTimesAssigned++; 16.563 + //get previous occupant of the slot 16.564 + PRProcess *process = slave->processSlaveIsIn; 16.565 + int32 coreNum = slot->coreSlotIsOn; 16.566 + int32 slotNum = slot->slotIdx; 16.567 + Unit prev_in_slot = 16.568 + process->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum]; 16.569 + if(prev_in_slot.vp != 0) //if not first slave in slot, make dependency 16.570 + { Dependency newD; // is a hardware dependency 16.571 + newD.from_vp = prev_in_slot.vp; 16.572 + newD.from_task = prev_in_slot.task; 16.573 + newD.to_vp = slave->slaveNum; 16.574 + newD.to_task = slave->numTimesAssignedToASlot; 16.575 + addToListOfArrays(Dependency,newD,process->hwArcs); 16.576 + } 16.577 + prev_in_slot.vp = slave->slaveNum; //make new slave the new previous 16.578 + prev_in_slot.task = slave->numTimesAssignedToASlot; 16.579 + process->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum] = 16.580 + prev_in_slot; 16.581 + 16.582 + #endif 16.583 + } 16.584 + 16.585 + 16.586 +/*This is to be called by langlet's assigner 16.587 + */ 16.588 +inline 16.589 +void 16.590 +PR_int__put_task_into_slot( PRMetaTask *task, PRProcess *process, AnimSlot *slot ) 16.591 + { int32 slotNum, coreNum; 16.592 + SlaveVP *slotSlv; 16.593 16.594 - idx = magicNum & 63; //mask off, leaving lowest 6 bits 16.595 - retEnv = &(semEnvs[idx]); //is array of structs, so take addr 16.596 - while( retEnv->langMagicNumber != magicNum ) //assume magicNums unique 16.597 - { retEnv = retEnv->chainedSemEnv; 16.598 - if( retEnv == NULL ) goto NotFound; 16.599 + //get the slot slave to assign the task to.. 16.600 + slotNum = slot->slotIdx; 16.601 + coreNum = slot->coreSlotIsOn; 16.602 + slotSlv = _PRTopEnv->slotTaskSlvs[coreNum][slotNum]; 16.603 + 16.604 + //point slave to task's function 16.605 + PR_int__reset_slaveVP_to_TopLvlFn( slotSlv, task->topLevelFn, task->initData ); 16.606 + PR_int__insert_meta_task_into_slave__ML( task, slotSlv ); 16.607 + PR_int__put_slave_into_slot( slotSlv, slot ); 16.608 + } 16.609 + 16.610 +//========================== 16.611 +inline 16.612 +PRMetaTask * 16.613 +PR_int__give_prolog_of_task( void *task ) 16.614 + { 16.615 + return (PRMetaTask *) &(((PRMetaTask *)task)[-1]); 16.616 + } 16.617 + 16.618 +inline 16.619 +void * 16.620 +PR_int__give_lang_meta_task_of_prolog( PRMetaTask *metaTask) 16.621 + { 16.622 + return (void *)&(metaTask[1]); 16.623 + } 16.624 + 16.625 + 16.626 +inline 16.627 +void * 16.628 +PR_int__create_lang_meta_task__ML( int32 size, int32 magicNum ) 16.629 + { PRMetaTask *retMetaTask; 16.630 + 16.631 + //make the new meta task 16.632 + retMetaTask = PR_int__malloc( sizeof(PRMetaTask) + size ); 16.633 + retMetaTask->chainedMetaTask = NULL; 16.634 + retMetaTask->langMagicNumber = magicNum; 16.635 + retMetaTask->slaveAssignedTo = NULL; 16.636 + retMetaTask->taskType = SlotTask; 16.637 + retMetaTask->ID = NULL; 16.638 + 16.639 + return &(retMetaTask[1]); //skip over prolog 16.640 + } 16.641 + 16.642 +/*allocates space for a new lang-meta-task, and inserts it into the slave, 16.643 + * under the given magic number. 16.644 + */ 16.645 +inline 16.646 +void * 16.647 +PR_int__create_lang_meta_task_in_slave__ML( int32 size, SlaveVP *slave, int32 magicNum ) 16.648 + { PRMetaTask *retMetaTask; 16.649 + PRCollElem **metaTasks; 16.650 + 16.651 + //make the new meta task 16.652 + retMetaTask = PR_int__malloc( sizeof(PRMetaTask) + size ); 16.653 + retMetaTask->chainedMetaTask = NULL; 16.654 + retMetaTask->langMagicNumber = magicNum; 16.655 + retMetaTask->slaveAssignedTo = slave; 16.656 + retMetaTask->taskType = GenericSlave; 16.657 + retMetaTask->ID = NULL; 16.658 + 16.659 + //multilang has a "collection" of meta tasks inside the slave 16.660 + metaTasks = (PRCollElem **)slave->metaTask; 16.661 + PR_int__insert_elem_into_collection( (PRCollElem *)retMetaTask, 16.662 + metaTasks, magicNum ); 16.663 + 16.664 + return &(retMetaTask[1]); //skip over prolog 16.665 + } 16.666 + 16.667 +inline 16.668 +void 16.669 +PR_int__insert_meta_task_into_slave__ML( PRMetaTask *task, SlaveVP *slave ) 16.670 + { 16.671 + task->slaveAssignedTo = slave; 16.672 + PR_int__insert_elem_into_collection( (PRCollElem *)task, 16.673 + (PRCollElem **)slave->metaTask, task->langMagicNumber ); 16.674 + } 16.675 +inline 16.676 +void 16.677 +PR_int__insert_lang_meta_task_into_slave__ML( void *langMetaTask, SlaveVP *slave ) 16.678 + { PRMetaTask *metaTask = &(((PRMetaTask*)langMetaTask)[-1]); 16.679 + metaTask->slaveAssignedTo = slave; 16.680 + PR_int__insert_elem_into_collection( (PRCollElem *)metaTask, 16.681 + (PRCollElem **)slave->metaTask, metaTask->langMagicNumber ); 16.682 + } 16.683 + 16.684 +inline 16.685 +void * 16.686 +PR_int__give_lang_meta_task_from_slave__ML( SlaveVP *slave, int32 magicNum ) 16.687 + { PRMetaTask *retMetaTask; 16.688 + PRCollElem **metaTasks; 16.689 + 16.690 + metaTasks = (PRCollElem **)slave->metaTask; 16.691 + retMetaTask = PR_int__lookup_elem_in_collection( magicNum, metaTasks ); 16.692 + if( retMetaTask != NULL ) 16.693 + return &(retMetaTask[1]); //skip over prolog 16.694 + else 16.695 + return NULL; 16.696 + } 16.697 + 16.698 +inline 16.699 +SlaveVP * 16.700 +PR_PI__give_slave_lang_meta_task_assigned_to( void *langMetaTask ) 16.701 + { PRMetaTask *metaTask = &(((PRMetaTask*)langMetaTask)[-1]); 16.702 + return metaTask->slaveAssignedTo; 16.703 + } 16.704 + 16.705 +//=============================================== 16.706 +/*Allocates space for a new lang-lang-data, and inserts it into the slave, 16.707 + * under the given magic number. Also returns it. 16.708 + */ 16.709 +inline 16.710 +void * 16.711 +PR_int__create_lang_data_in_slave__ML( int32 size, SlaveVP *slave, int32 magicNum ) 16.712 + { PRLangData *retLangData; 16.713 + PRCollElem **langDatas; 16.714 + 16.715 + //make the new lang Data 16.716 + retLangData = PR_int__malloc( sizeof(PRLangData) + size ); 16.717 + retLangData->chainedLangData = NULL; 16.718 + retLangData->langMagicNumber = magicNum; 16.719 + 16.720 + //multilang has a "collection" of lang datas inside the slave 16.721 + langDatas = (PRCollElem **)slave->langData; 16.722 + PR_int__insert_elem_into_collection( (PRCollElem *)retLangData, langDatas, magicNum ); 16.723 + 16.724 + return &(retLangData[1]); //skip over prolog 16.725 + } 16.726 + 16.727 +inline 16.728 +void * 16.729 +PR_int__give_lang_data_from_slave__ML( SlaveVP *slave, int32 magicNum ) 16.730 + { PRLangData *retLangData; 16.731 + PRCollElem **langDatas; 16.732 + 16.733 + langDatas = (PRCollElem **)slave->langData; 16.734 + retLangData = PR_int__lookup_elem_in_collection( magicNum, langDatas ); 16.735 + if( retLangData != NULL ) 16.736 + return &(retLangData[1]); //skip over prolog 16.737 + else 16.738 + return NULL; 16.739 + } 16.740 + 16.741 + 16.742 +//=============================================== 16.743 +inline 16.744 +void 16.745 +PR_int__insert_elem_into_collection( PRCollElem *elem, PRCollElem **coll, int32 hash ) 16.746 + { int32 idx, numIdxsInColl; 16.747 + PRCollElem *test; 16.748 + 16.749 + numIdxsInColl = ((int32 *)coll)[-1]; //prolog holds number of idexes in array 16.750 + 16.751 + //figure out where to link in 16.752 + idx = hash & (numIdxsInColl - 1); //mask off, leaving lowest bits 16.753 + test = coll[idx]; 16.754 + elem->chained = NULL; //elem goes at end of any chain, so just being sure here 16.755 + if( test == NULL ) //spot empty, so add there 16.756 + { //add to the array 16.757 + coll[idx] = elem; 16.758 } 16.759 - return retEnv; 16.760 + else //collision -- look for last in chain, then add there 16.761 + { while( test->chained != NULL ) 16.762 + { test = test->chained; 16.763 + } 16.764 + //add new to the end of chain 16.765 + test->chained = elem; 16.766 + } 16.767 + } 16.768 + 16.769 +inline 16.770 +void * 16.771 +PR_int__lookup_elem_in_collection( int32 hash, PRCollElem **coll ) 16.772 + { int32 idx, numIdxsInColl; 16.773 + PRCollElem *test; 16.774 + 16.775 + numIdxsInColl = ((int32 *)coll)[-1]; //prolog holds number of indexes in array 16.776 + 16.777 + idx = hash & (numIdxsInColl - 1); //mask off, leaving lowest bits 16.778 + test = coll[idx]; 16.779 + if( test == NULL ) goto NotFound; 16.780 + while( test->hash != hash ) 16.781 + { test = test->chained; 16.782 + if( test == NULL ) goto NotFound; 16.783 + } 16.784 + return test; 16.785 16.786 NotFound: 16.787 return NULL; 16.788 } 16.789 16.790 inline 16.791 -PRSemEnv * 16.792 -PR_int__create_proto_sem_env_in_process( PRProcess process, int32 magicNum ) 16.793 - { PRSemEnv *semEnvs; 16.794 - PRSemEnv *retEnv, *newEnv; 16.795 - int32 idx; 16.796 - 16.797 - semEnvs = process->semEnvs; 16.798 - 16.799 - idx = magicNum & 63; //mask upper bits off, leaving lowest 6 bits 16.800 - retEnv = &(semEnvs[idx]); //is array of structs, so take addr 16.801 - if( retEnv->langSemEnv == NULL ) 16.802 - { //if env that's in array is empty, do nothing, drop down to return sequence 16.803 +void 16.804 +PR_int__remove_elem_from_collection( int32 hash, PRCollElem **coll ) 16.805 + { int32 idx, numIdxsInColl; 16.806 + PRCollElem *test, *prev; 16.807 + 16.808 + numIdxsInColl = ((int32 *)coll)[-1]; //num indexes in prolog -- power of 2 16.809 + 16.810 + idx = hash & (numIdxsInColl - 1); //mask off, leaving lowest bits (power of 2) 16.811 + test = coll[idx]; 16.812 + if( test == NULL ) return; //not found, nothing to remove 16.813 + prev = NULL; 16.814 + while( test->hash != hash ) 16.815 + { prev = test; 16.816 + test = test->chained; 16.817 + if( test == NULL ) return; //not found, nothing to remove 16.818 } 16.819 - else //look for last environment in chain 16.820 - { while( retEnv->chainedSemEnv != NULL ) 16.821 - { retEnv = retEnv->chainedSemEnv; 16.822 - } 16.823 - //add a new proto sem env to the end of chain 16.824 - newEnv = PR_int__malloc( sizeof(PRSemEnv) ); 16.825 - newEnv->chainedSemEnv = NULL; 16.826 - retEnv->chainedSemEnv = newEnv; 16.827 - retEnv = newEnv; 16.828 + if( prev == NULL) 16.829 + { coll[idx] = coll[idx]->chained; 16.830 + return; 16.831 } 16.832 - 16.833 - process->semEnvList[process->numSemEnvs] = retEnv; 16.834 - process->numSemEnvs += 1; 16.835 - return retEnv; 16.836 + else 16.837 + { prev->chained = test->chained; 16.838 + return; 16.839 + } 16.840 } 16.841 16.842 +inline 16.843 +void 16.844 +PR_int__apply_Fn_to_all_in_collection( void (*Fn)(void *), PRCollElem *coll ) 16.845 + { int32 idx, numIdxsInColl; 16.846 + PRCollElem *test; 16.847 + 16.848 + numIdxsInColl = ((int32 *)coll)[-1]; //prolog is num idxs 16.849 + for( idx = 0; idx < ; idx++ ) 16.850 + { test = coll[idx]; 16.851 + while( test != NULL ) 16.852 + { (*Fn)((void *)test); 16.853 + test = test->chained; 16.854 + } 16.855 + } 16.856 + } 16.857 + 16.858 +//========================================== 16.859 16.860 /*Later, improve this -- for now, just exits the application after printing 16.861 * the error message. 16.862 @@ -370,7 +783,8 @@ 16.863 } 16.864 16.865 16.866 -inline char * 16.867 +inline 16.868 +char * 16.869 PR_int__strDup( char *str ) 16.870 { char *retStr; 16.871
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/PR__int.h Mon Jan 14 15:31:23 2013 -0800 17.3 @@ -0,0 +1,245 @@ 17.4 +/* 17.5 + * Copyright 2009 OpenSourceResearchInstitute.org 17.6 + * Licensed under GNU General Public License version 2 17.7 + * 17.8 + * Author: seanhalle@yahoo.com 17.9 + * 17.10 + */ 17.11 + 17.12 +#ifndef _PR_INT_H 17.13 +#define _PR_INT_H 17.14 +#define _GNU_SOURCE 17.15 + 17.16 + 17.17 +/* MEANING OF WL PI SS int 17.18 + * These indicate which places the function is safe to use. They stand for: 17.19 + * WL: Wrapper Library 17.20 + * PI: Plugin 17.21 + * SS: Startup and Shutdown 17.22 + * int: internal to the PR implementation 17.23 + */ 17.24 + 17.25 + 17.26 +inline SlaveVP * 17.27 +PR_int__create_slave( TopLevelFnPtr fnPtr, void *dataParam ); 17.28 +#define PR_PI__create_slaveVP PR_int__create_slave 17.29 +#define PR_WL__create_slaveVP PR_int__create_slave 17.30 + 17.31 +inline 17.32 +SlaveVP * 17.33 +PR_int__create_slaveVP_helper( SlaveVP *newSlv, TopLevelFnPtr fnPtr, 17.34 + void *dataParam, void *stackLocs ); 17.35 + 17.36 +inline 17.37 +PRMetaTask * 17.38 +PR_int__create_generic_slave_meta_task( void *initData ); 17.39 + 17.40 +inline 17.41 +void 17.42 +PR_int__reset_slaveVP_to_TopLvlFn( SlaveVP *slaveVP, TopLevelFnPtr fnPtr, 17.43 + void *dataParam); 17.44 + 17.45 +inline 17.46 +void 17.47 +PR_int__point_slaveVP_to_OneParamFn( SlaveVP *slaveVP, void *fnPtr, 17.48 + void *param); 17.49 + 17.50 +inline 17.51 +void 17.52 +PR_int__point_slaveVP_to_TwoParamFn( SlaveVP *slaveVP, void *fnPtr, 17.53 + void *param1, void *param2); 17.54 + 17.55 +//=========================================================================== 17.56 +// 17.57 +//=========================================================================== 17.58 +inline 17.59 +SlaveVP * 17.60 +PR_int__create_slaveVP( TopLevelFnPtr fnPtr, void *dataParam ); 17.61 + 17.62 +inline 17.63 +SlaveVP * 17.64 +PR_int__create_slaveVP__ML( TopLevelFnPtr fnPtr, void *dataParam, PRProcess *process ); 17.65 + 17.66 +SlaveVP * 17.67 +PR_int__get_recycled_slot_slave( ); 17.68 + 17.69 +SlaveVP * 17.70 +PR_int__create_slot_slave( ); 17.71 + 17.72 +inline 17.73 +void 17.74 +PR_int__replace_with_new_slot_slv( SlaveVP *slave ); 17.75 + 17.76 +void 17.77 +idle_fn(void* data, SlaveVP *animatingSlv); 17.78 + 17.79 +inline 17.80 +void 17.81 +PR_int__put_task_into_slot( PRMetaTask *task, PRProcess *process, AnimSlot *slot ); 17.82 + 17.83 +inline 17.84 +void 17.85 +PR_int__put_slave_into_slot( SlaveVP *slave, AnimSlot *slot ); 17.86 + 17.87 +void inline 17.88 +PR_int__handle_PRServiceReq( SlaveVP *requestingSlv ); 17.89 + 17.90 +void 17.91 +PR_WL__suspend_slaveVP_and_send_req( SlaveVP *animatingSlv ); 17.92 + 17.93 +void 17.94 +PR_int__dissipate_slaveVP__SL( SlaveVP *animatingSlv ); 17.95 + 17.96 +void 17.97 +PR_int__free_slaveVP__ML( SlaveVP *slave ); 17.98 + 17.99 +void 17.100 +PR_int__recycle_slave__ML( SlaveVP *slave ); 17.101 + 17.102 +void 17.103 +recycleLangDataAsElem( void *elem ); 17.104 + 17.105 +void 17.106 +recycleMetaTaskAsElem( void *elem ); 17.107 + 17.108 +inline 17.109 +void * 17.110 +PR_int__give_lang_env( PRLangEnv *protoLangEnv ); 17.111 + 17.112 +inline 17.113 +PRLangEnv * 17.114 +PR_int__give_proto_lang_env( void *langEnv ); 17.115 + 17.116 +inline 17.117 +void * 17.118 +PR_int__create_lang_env_in_process( int32 size, PRProcess process, int32 magicNum ); 17.119 + 17.120 +inline 17.121 +void * 17.122 +PR_int__free_lang_env( void *langEnv ); 17.123 + 17.124 +inline 17.125 +void * 17.126 +PR_int__give_lang_env_of_req__ML( PRReqst *req, SlaveVP *requestingSlv ); 17.127 + 17.128 +inline 17.129 +void * 17.130 +PR_int__give_lang_env_for_slave__ML( SlaveVP *slave, int32 magicNum ); 17.131 +#define PR_PI__give_lang_env_for PR_int__give_lang_env_for_slave__ML 17.132 +#define PR_SS__give_lang_env_for_slave PR_int__give_lang_env_for_slave__ML 17.133 +//No WL version -- not safe! if use env in WL, be sure data rd & wr is stable 17.134 + 17.135 +inline 17.136 +PRLangEnv * 17.137 +PR_int__give_proto_lang_env_for_slave__ML( SlaveVP *slave, int32 magicNumber ); 17.138 +#define PR_PI__give_proto_lang_env_for PR_int__give_proto_lang_env_for_slave__ML 17.139 +#define PR_SS__give_proto_lang_env_for_slave PR_int__give_proto_lang_env_for_slave__ML 17.140 +//No WL version -- not safe! if use env in WL, be sure data rd & wr is stable 17.141 + 17.142 +inline 17.143 +void * 17.144 +PR_int__give_lang_env_from_process( PRProcess *process, int32 magicNum ); 17.145 +#define PR_PI__give_lang_env_from_process PR_int__give_lang_env_from_process 17.146 +#define PR_SS__give_lang_env_from_process PR_int__give_lang_env_from_process 17.147 +//#define PR_WL__give_lang_env_from_process PR_int__give_lang_env_from_process 17.148 +//No WL version -- not safe! if use env in WL, be sure data rd & wr is stable 17.149 + 17.150 +inline 17.151 +PRLangEnv * 17.152 +PR_int__give_proto_lang_env_for_process( PRProcess *process, int32 magicNum ); 17.153 + 17.154 +inline 17.155 +void 17.156 +PR_int__set_work_in_lang_env( void *_langEnv ); 17.157 + 17.158 +inline 17.159 +void 17.160 +PR_int__clear_work_in_lang_env( void *_langEnv ); 17.161 + 17.162 +inline 17.163 +PRMetaTask * 17.164 +PR_int__give_prolog_of_task( void *task ); 17.165 + 17.166 +inline 17.167 +void * 17.168 +PR_int__give_lang_meta_task_of_prolog( PRMetaTask *metaTask); 17.169 + 17.170 +inline 17.171 +void * 17.172 +PR_int__create_lang_meta_task__ML( int32 size, int32 magicNum ); 17.173 + 17.174 +inline 17.175 +void * 17.176 +PR_int__create_lang_meta_task_in_slave__ML( int32 size, SlaveVP *slave, int32 magicNum ); 17.177 + 17.178 +inline 17.179 +void 17.180 +PR_int__insert_meta_task_into_slave__ML( PRMetaTask *task, SlaveVP *slave ); 17.181 + 17.182 +inline 17.183 +void 17.184 +PR_int__insert_lang_meta_task_into_slave__ML( void *langMetaTask, SlaveVP *slave ); 17.185 + 17.186 +inline 17.187 +void * 17.188 +PR_int__give_lang_meta_task_from_slave__ML( SlaveVP *slave, int32 magicNumer ); 17.189 +//#define PR_int__give_lang_meta_task_from_slave__ML( slave, magicNumber )\ 17.190 + slave->metaTask->langMetaTask; 17.191 +#define PR_PI__give_lang_meta_task_from_slave__ML PR_int__give_lang_meta_task_from_slave__ML 17.192 +#define PR_SS__give_lang_meta_task_from_slave__ML PR_int__give_lang_meta_task_from_slave__ML 17.193 +#define PR_WL__give_lang_meta_task_from_slave__ML PR_int__give_lang_meta_task_from_slave__ML 17.194 + 17.195 +inline 17.196 +SlaveVP * 17.197 +PR_PI__give_slave_lang_meta_task_assigned_to( void *langMetaTask ); 17.198 + 17.199 +inline 17.200 +void * 17.201 +PR_int__create_lang_data_in_slave__ML( int32 size, SlaveVP *slave, int32 magicNum ); 17.202 + 17.203 +inline 17.204 +void * 17.205 +PR_int__give_lang_data_from_slave__ML( SlaveVP *slave, int32 magicNumer ); 17.206 +#define PR_PI__give_lang_data PR_int__give_lang_data_from_slave__ML 17.207 +#define PR_SS__give_lang_data PR_int__give_lang_data_from_slave__ML 17.208 +#define PR_WL__give_lang_data PR_int__give_lang_data_from_slave__ML 17.209 + 17.210 +inline 17.211 +void 17.212 +PR_int__insert_elem_into_collection( PRCollElem *elem, PRCollElem **coll, int32 hash ); 17.213 + 17.214 +inline 17.215 +void * 17.216 +PR_int__lookup_elem_in_collection( int32 hash, PRCollElem **coll ); 17.217 + 17.218 +inline 17.219 +void 17.220 +PR_int__remove_elem_from_collection( int32 hash, PRCollElem **coll ); 17.221 + 17.222 +inline 17.223 +void 17.224 +PR_int__apply_Fn_to_all_in_collection( void (*Fn)(void *), PRCollElem *coll ); 17.225 + 17.226 +void 17.227 +PR_int__throw_exception( char *msgStr, SlaveVP *reqstSlv, PRExcp *excpData ); 17.228 +#define PR_PI__throw_exception PR_int__throw_exception 17.229 + 17.230 +inline char * 17.231 +PR_int__strDup( char *str ); 17.232 + 17.233 +inline void 17.234 +PR_int__backoff_for_TooLongToGetLock( int32 numTriesToGetLock ); 17.235 + 17.236 +inline void 17.237 +PR_int__get_master_lock(); 17.238 + 17.239 +#define PR_int__release_master_lock() _PRTopEnv->masterLock = UNLOCKED 17.240 + 17.241 +inline uint32_t 17.242 +PR_int__randomNumber(); 17.243 + 17.244 +inline void 17.245 +PR_int__backoff_for_TooLongToGetLock( int32 numTriesToGetLock ); 17.246 + 17.247 +#endif /* _PR_INT_H */ 17.248 +
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/PR__structs.h Mon Jan 14 15:31:23 2013 -0800 18.3 @@ -0,0 +1,418 @@ 18.4 +/* 18.5 + * Copyright 2009 OpenSourceResearchInstitute.org 18.6 + * Licensed under GNU General Public License version 2 18.7 + * 18.8 + * Author: seanhalle@yahoo.com 18.9 + * 18.10 + */ 18.11 + 18.12 +#ifndef _PR__structs_H 18.13 +#define _PR__structs_H 18.14 +#define _GNU_SOURCE 18.15 + 18.16 +#include "PR_primitive_data_types.h" 18.17 + 18.18 +#include <pthread.h> 18.19 +#include <sys/time.h> 18.20 + 18.21 + 18.22 +//================================ Typedefs ================================= 18.23 +// 18.24 +typedef unsigned long long TSCount; 18.25 + 18.26 +typedef struct _AnimSlot AnimSlot; 18.27 +typedef struct _PRReqst PRReqst; 18.28 +typedef struct _SlaveVP SlaveVP; 18.29 +typedef struct _MasterVP MasterVP; 18.30 +typedef struct _IntervalProbe IntervalProbe; 18.31 +typedef struct _PRLangEnv PRLangEnv; //a prolog 18.32 +typedef struct _PRMetaTask PRMetaTask; //a prolog 18.33 +typedef struct _PRLangData PRLangData; //a prolog 18.34 +typedef struct _PRCollElem PRCollElem; //generic form of the prologs 18.35 + 18.36 +typedef SlaveVP *(*SlaveAssigner) ( void *, AnimSlot* ); //langEnv, slot for HW info 18.37 +typedef void (*RequestHandler) ( void *, SlaveVP *, void * ); //req, slv, langEnv 18.38 +typedef void *(*CreateHandler) ( void *, SlaveVP *, void * ); //req, slv, langEnv 18.39 +typedef void (*TopLevelFnPtr) ( void *, SlaveVP * ); //initData, animSlv 18.40 +typedef void TopLevelFn ( void *, SlaveVP * ); //initData, animSlv 18.41 +typedef void (*ResumeSlvFnPtr) ( SlaveVP *, void * ); 18.42 + //=========== MEASUREMENT STUFF ========== 18.43 + MEAS__Insert_Counter_Handler 18.44 + //======================================== 18.45 + 18.46 +//============================ HW Dependent Fns ================================ 18.47 + 18.48 +#include "HW_Dependent_Primitives/PR__HW_measurement.h" 18.49 +#include "HW_Dependent_Primitives/PR__primitives.h" 18.50 + 18.51 + 18.52 +typedef struct 18.53 + { //These are set by the plugin during startup and the application 18.54 + char *assignerInfo; 18.55 + char *appInfo; 18.56 + char *inputInfo; 18.57 + } 18.58 +PRSysMetaInfo; 18.59 + 18.60 +//===================== Process Data Struct ====================== 18.61 + 18.62 +/*This structure holds all the information PR needs to manage a program. PR 18.63 + * stores information about what percent of CPU time the program is getting, 18.64 + * 18.65 + */ 18.66 +typedef struct 18.67 + { 18.68 + int32 numEnvsWithWork; 18.69 + void *resultToReturn; 18.70 + 18.71 + PRLangEnv *langEnvs[NUM_IN_COLLECTION]; //used as a hash table 18.72 + PRLangEnv *langEnvsList[NUM_IN_COLLECTION]; //for fast linear scan of envs 18.73 + int32 numLangEnvs; //for fast linear scan of envs 18.74 + 18.75 + SlaveVP *seedSlv; 18.76 + 18.77 + int32 numLiveGenericSlvs; 18.78 + int32 numLiveTasks; 18.79 + 18.80 + SlaveAssigner overrideAssigner; 18.81 + 18.82 + 18.83 + 18.84 + //These are used to coord with an OS thread waiting for process to end 18.85 + bool32 executionIsComplete; 18.86 + pthread_mutex_t doneLock; 18.87 + pthread_cond_t doneCond; 18.88 + 18.89 + //=========== MEASUREMENT STUFF ============= 18.90 + IntervalProbe **intervalProbes; 18.91 + PrivDynArrayInfo *dynIntervalProbesInfo; 18.92 + HashTable *probeNameHashTbl; 18.93 + int32 masterCreateProbeID; 18.94 + float64 createPtInSecs; //real-clock time PR initialized 18.95 + Histogram **measHists; 18.96 + PrivDynArrayInfo *measHistsInfo; 18.97 + MEAS__Insert_Susp_Meas_Fields_into_MasterEnv; 18.98 + MEAS__Insert_Master_Meas_Fields_into_MasterEnv; 18.99 + MEAS__Insert_Master_Lock_Meas_Fields_into_MasterEnv; 18.100 + MEAS__Insert_Malloc_Meas_Fields_into_MasterEnv; 18.101 + MEAS__Insert_Plugin_Meas_Fields_into_MasterEnv; 18.102 + MEAS__Insert_System_Meas_Fields_into_MasterEnv; 18.103 + MEAS__Insert_Counter_Meas_Fields_into_MasterEnv; 18.104 + //========================================== 18.105 + } 18.106 +PRProcess; 18.107 + 18.108 + 18.109 +//============= Request Related =========== 18.110 +// 18.111 + 18.112 +enum PRReqstType //avoid starting enums at 0, for debug reasons 18.113 + { 18.114 + TaskCreate = 1, 18.115 + TaskEnd, 18.116 + SlvCreate, 18.117 + SlvDissipate, 18.118 + Language, 18.119 + Service, //To invoke a PR provided equivalent of a language request (ex: probe) 18.120 + Hardware, 18.121 + IO, 18.122 + OSCall 18.123 + }; 18.124 + 18.125 +struct _PRReqst 18.126 + { 18.127 + enum PRReqstType reqType;//used for special forms that have PR behavior 18.128 + void *langReq; 18.129 + PRProcess *processReqIsIn; 18.130 + int32 langMagicNumber; 18.131 + TopLevelFnPtr topLevelFn; 18.132 + void *initData; 18.133 + int32 *ID; 18.134 + 18.135 + //The request handling structure is a bit messy.. for special forms, 18.136 + // such as create and dissipate, the language inserts pointer to handler 18.137 + // fn directly into the request.. might change to this for all requests 18.138 + RequestHandler handler; //pointer to handler fn 18.139 + CreateHandler createHdlr; //special because returns something 18.140 + 18.141 + PRReqst *nextReqst; 18.142 + }; 18.143 +//PRReqst 18.144 + 18.145 +enum PRServReqType //These are equivalent to lang requests, but for 18.146 + { // PR's services available directly to app, like OS 18.147 + make_probe = 1, // and probe services -- like a PR-wide built-in lang 18.148 + throw_excp, 18.149 + openFile, 18.150 + otherIO 18.151 + }; 18.152 + 18.153 +typedef struct 18.154 + { enum PRServReqType reqType; 18.155 + SlaveVP *requestingSlv; 18.156 + char *nameStr; //for create probe 18.157 + char *msgStr; //for exception 18.158 + void *exceptionData; 18.159 + } 18.160 +PRServReq; 18.161 + 18.162 + 18.163 +//==================== Core data structures =================== 18.164 + 18.165 +typedef struct 18.166 + { 18.167 + //for future expansion 18.168 + } 18.169 +SlotPerfInfo; 18.170 + 18.171 +struct _AnimSlot 18.172 + { 18.173 + int32 workIsDone; 18.174 + int32 needsWorkAssigned; 18.175 + SlaveVP *slaveAssignedToSlot; 18.176 + 18.177 + int32 slotIdx; //needed by Holistic Model's data gathering 18.178 + int32 coreSlotIsOn; 18.179 + SlotPerfInfo *perfInfo; //used by assigner to pick best slave for core 18.180 + }; 18.181 +//AnimSlot 18.182 + 18.183 +enum VPtype 18.184 + { SlotTaskSlv = 1,//Slave tied to an anim slot, only animates tasks 18.185 + FreeTaskSlv, //When a suspended task ends, the slave becomes this 18.186 + GenericSlv, //the VP is explicitly seen in the app code, or task suspends 18.187 + SeedSlv, 18.188 + Master, 18.189 + Shutdown, 18.190 + Idle 18.191 + }; 18.192 + 18.193 +/*This structure embodies the state of a slaveVP. It is reused for masterVP 18.194 + * and shutdownVPs. 18.195 + */ 18.196 +struct _SlaveVP 18.197 + { //The offsets of these fields are hard-coded into assembly 18.198 + void *stackPtr; //save the core's stack ptr when suspend 18.199 + void *framePtr; //save core's frame ptr when suspend 18.200 + void *resumeInstrPtr; //save core's program-counter when suspend 18.201 + void *coreCtlrFramePtr; //restore before jmp back to core controller 18.202 + void *coreCtlrStackPtr; //restore before jmp back to core controller 18.203 + 18.204 + //============ below this, no fields are used in asm ============= 18.205 + 18.206 + void *startOfStack; //used to free, and to point slave to Fn 18.207 + PRProcess *processSlaveIsIn; 18.208 + enum VPtype typeOfVP; //Slave vs Master vs Shutdown.. 18.209 + int32 slaveNum; //each slave given it's seq in creation 18.210 + int32 *ID; //App defines meaning of each int in array 18.211 + int32 coreAnimatedBy; 18.212 + int32 numTimesAssignedToASlot; //Each assign is for one work-unit, so is an ID 18.213 + //note, a scheduling decision is uniquely identified by the triple: 18.214 + // <slaveNum, coreAnimatedBy, numTimesAssignedToASlot> -- used in record & replay 18.215 + 18.216 + //for comm -- between master and coreCtlr & btwn wrapper lib and plugin 18.217 + AnimSlot *animSlotAssignedTo; 18.218 + PRReqst *request; //wrapper lib puts in requests, plugin takes out 18.219 + void *dataRetFromReq;//Return vals from plugin to Wrapper Lib 18.220 + 18.221 + //For language specific data that needs to be in the slave 18.222 + //These are accessed directly for single-lang, but multi-lang places 18.223 + // a holder here instead, then uses magic num to get lang's version 18.224 + void *langData; //Lang saves lang-specific things in slave here 18.225 + void *metaTask; 18.226 + 18.227 + //=========== MEASUREMENT STUFF ========== 18.228 + MEAS__Insert_Meas_Fields_into_Slave; 18.229 + float64 createPtInSecs; //time VP created, in seconds 18.230 + //======================================== 18.231 + 18.232 +// int8 cacheLinePad[512 - sizeof(contents)]; //for false sharing 18.233 + }; 18.234 +//SlaveVP 18.235 + 18.236 + 18.237 +enum PRMode 18.238 + { SingleLang = 1, 18.239 + StandaloneWTasks, 18.240 + MultiLang 18.241 + }; 18.242 + 18.243 +/* The one and only global variable, holds many odds and ends 18.244 + */ 18.245 +typedef struct 18.246 + { //The offsets of these fields are hard-coded into assembly 18.247 + void *coreCtlrReturnPt; //offset to this field used in asm 18.248 + int8 falseSharePad1[256 - sizeof(void*)]; 18.249 + int32 masterLock; //offset to this field used in asm 18.250 + int8 falseSharePad2[256 - sizeof(int32)]; 18.251 + //============ below this, no fields are used in asm ============= 18.252 + 18.253 + //Basic PR infrastructure 18.254 + enum PRMode mode; 18.255 + SlaveVP **masterVPs; 18.256 + AnimSlot ***allAnimSlots; 18.257 + PrivQueueStruc *slaveRecycleQ; 18.258 + SlaveVP *slotTaskSlvs[NUM_CORES][NUM_ANIM_SLOTS]; 18.259 + SlaveVP *idleSlv[NUM_CORES][NUM_ANIM_SLOTS]; 18.260 + 18.261 + //Memory management related 18.262 + MallocArrays *freeLists; 18.263 + int32 amtOfOutstandingMem;//total currently allocated 18.264 + 18.265 + //Random number seeds -- random nums used in various places 18.266 + uint32_t seed1; 18.267 + uint32_t seed2; 18.268 + 18.269 + PRSysMetaInfo *metaInfo; //info about this PR system -- vers, build, etc 18.270 + 18.271 + //============== This only used by multi-lang mode ============ 18.272 + PRProcess **processes; 18.273 + int32 numProcesses; 18.274 + int32 currProcessIdx; //used to choose which process gets slot 18.275 + int32 firstProcessReady; //use while starting up coreCtlr 18.276 + RequestHandler free_lang_data; //lang data persists after langlet stops 18.277 + //so need freer when end slaves 18.278 + 18.279 + //initialize flags for waiting for activity within PR to complete 18.280 + bool32 allActivityIsDone; 18.281 + pthread_mutex_t activityDoneLock; 18.282 + pthread_cond_t activityDoneCond; 18.283 + 18.284 + 18.285 + //============== Below this is only used by single-lang mode ============== 18.286 + void *protoLangEnv; 18.287 + //Slave creation -- global count of slaves existing, across langs and processes 18.288 + int32 numSlavesCreated; //used to give unique ID to processor 18.289 + int32 numTasksCreated; //to give unique ID to a task 18.290 + int32 numSlavesAlive; 18.291 + 18.292 + bool32 *coreIsDone; 18.293 + int32 numCoresDone; 18.294 + int32 shutdownInitiated; 18.295 + 18.296 + 18.297 + //=========== MEASUREMENT STUFF ============= 18.298 + IntervalProbe **intervalProbes; 18.299 + PrivDynArrayInfo *dynIntervalProbesInfo; 18.300 + HashTable *probeNameHashTbl; 18.301 + int32 masterCreateProbeID; 18.302 + float64 createPtInSecs; //real-clock time PR initialized 18.303 + Histogram **measHists; 18.304 + PrivDynArrayInfo *measHistsInfo; 18.305 + MEAS__Insert_Susp_Meas_Fields_into_MasterEnv; 18.306 + MEAS__Insert_Master_Meas_Fields_into_MasterEnv; 18.307 + MEAS__Insert_Master_Lock_Meas_Fields_into_MasterEnv; 18.308 + MEAS__Insert_Malloc_Meas_Fields_into_MasterEnv; 18.309 + MEAS__Insert_Plugin_Meas_Fields_into_MasterEnv; 18.310 + MEAS__Insert_System_Meas_Fields_into_MasterEnv; 18.311 + MEAS__Insert_Counter_Meas_Fields_into_MasterEnv; 18.312 + //========================================== 18.313 + } 18.314 +TopEnv; 18.315 + 18.316 + 18.317 +//===================== These are prologs ==================== 18.318 +//===A prolog is data immediately before pointer returned by a create function. 18.319 +//= 18.320 +struct _PRLangEnv 18.321 + { //============== First two must match PRCollElem ============== 18.322 + int32 langMagicNumber; //indexes into hash array of langEnvs in PRProcess 18.323 + PRLangEnv *chainedLangEnv; //chains to langEnvs with same hash 18.324 + //============================================================= 18.325 + 18.326 + SlaveAssigner slaveAssigner; 18.327 + RequestHandler requestHdlr; 18.328 + RequestHandler shutdownHdlr; //called when lang ended or process shutdown 18.329 + 18.330 +/* 18.331 + CreateTaskHdlr createTaskHdlr; 18.332 + RequestHandler endTaskHdlr; 18.333 + CreateSlvHdlr createSlaveHdlr; 18.334 + RequestHandler dissipateSlaveHdlr; 18.335 + */ 18.336 + RequestHandler langDataCreator; 18.337 + RequestHandler langDataInitializer; 18.338 + 18.339 + //when multi-lang, master polls lang env's to find one with work in it.. 18.340 + // in single-lang case, flag ignored, master always asks lang for work 18.341 + int32 hasWork; 18.342 + PRProcess *processEnvIsIn; 18.343 + 18.344 + int32 idxInProcess; //index into array of langEnvs in the process 18.345 + }; 18.346 +//PRLangEnv -- this is the prolog of every lang's lang env 18.347 + 18.348 +enum PRTaskType 18.349 + { GenericSlave = 1, 18.350 + SlotTask, 18.351 + FreeTask 18.352 + }; 18.353 + 18.354 +struct _PRMetaTask 18.355 + { //============== First two must match PRCollElem ============== 18.356 + int32 langMagicNumber; 18.357 + PRMetaTask *chainedMetaTask; 18.358 + //============================================================= 18.359 + enum PRTaskType taskType; 18.360 + int32 *ID; //is standard PR ID 18.361 + SlaveVP *slaveAssignedTo; //no valid until task animated 18.362 + TopLevelFnPtr topLevelFn; //This is the Fn executes as the task 18.363 + void *initData; //The data taken by the function 18.364 + void (*recycler)(void *); 18.365 + 18.366 + //NOTE: info needed for "wait" functionality is inside lang's metaTask 18.367 + }; 18.368 +//PRMetaTask -- prolog of every lang's meta task 18.369 + 18.370 +struct _PRLangData 18.371 + { //============== First two must match PRCollElem ============== 18.372 + int32 langMagicNumber; 18.373 + PRLangData *chainedLangData; 18.374 + //============================================================= 18.375 + void (*recycler)(void *); 18.376 + void *langLangData; 18.377 + }; 18.378 +//PRLangData -- this is the prolog of each lang's lang data 18.379 + 18.380 +struct _PRCollElem 18.381 + { 18.382 + int32 hash; 18.383 + PRCollElem *chained; 18.384 + }; 18.385 +//PRCollElem -- this is generic form of all the prologs 18.386 + 18.387 + 18.388 + 18.389 +//The language env of PR's services langlet 18.390 +typedef struct 18.391 + { 18.392 + PrivQueueStruc *slavesReadyToResumeQ; //Shared (slaves not pinned) 18.393 + PrivQueueStruc *taskReadyQ; //Shared (tasks not pinned) 18.394 + } 18.395 +PRServLangEnv; 18.396 + 18.397 + 18.398 + 18.399 +//========================= Extra Stuff Data Strucs ======================= 18.400 +typedef struct 18.401 + { 18.402 + 18.403 + } 18.404 +PRExcp; //exception 18.405 + 18.406 +//======================= OS Thread related =============================== 18.407 + 18.408 +void * coreController( void *paramsIn ); //standard PThreads fn prototype 18.409 +void * coreCtlr_Seq( void *paramsIn ); //standard PThreads fn prototype 18.410 +void animationMaster( void *initData, SlaveVP *masterVP ); 18.411 + 18.412 + 18.413 +typedef struct 18.414 + { 18.415 + void *endThdPt; 18.416 + unsigned int coreNum; 18.417 + } 18.418 +ThdParams; 18.419 + 18.420 +#endif /* _PR__structs_H */ 18.421 +
19.1 --- a/PR_primitive_data_types.h Sun Nov 04 18:39:28 2012 -0800 19.2 +++ b/PR_primitive_data_types.h Mon Jan 14 15:31:23 2013 -0800 19.3 @@ -1,5 +1,5 @@ 19.4 /* 19.5 - * Copyright 2009 OpenSourceStewardshipFoundation.org 19.6 + * Copyright 2009 OpenSourceResearchInstitute.org 19.7 * Licensed under GNU General Public License version 2 19.8 * 19.9 * Author: seanhalle@yahoo.com
20.1 --- a/Services_Offered_by_PR/Measurement_and_Stats/MEAS__macros.h Sun Nov 04 18:39:28 2012 -0800 20.2 +++ b/Services_Offered_by_PR/Measurement_and_Stats/MEAS__macros.h Mon Jan 14 15:31:23 2013 -0800 20.3 @@ -1,5 +1,5 @@ 20.4 /* 20.5 - * Copyright 2009 OpenSourceStewardshipFoundation.org 20.6 + * Copyright 2009 OpenSourceResearchInstitute.org 20.7 * Licensed under GNU General Public License version 2 20.8 * 20.9 * Author: seanhalle@yahoo.com 20.10 @@ -368,7 +368,7 @@ 20.11 20.12 #define HOLISTIC__Insert_Master_Global_Vars \ 20.13 int vpid,task; \ 20.14 - CounterHandler counterHandler = masterEnv->counterHandler; 20.15 + CounterHandler counterHandler = _PRTopEnv->counterHandler; 20.16 20.17 #define HOLISTIC__Record_last_work lastVPBeforeMaster = currVP; 20.18 20.19 @@ -376,7 +376,7 @@ 20.20 uint64 cycles,instrs,cachem; \ 20.21 saveCyclesAndInstrs(thisCoresIdx,cycles, instrs,cachem); \ 20.22 if(lastVPBeforeMaster){ \ 20.23 - (*counterHandler)(AppResponderInvocation_start,lastVPBeforeMaster->slaveID,lastVPBeforeMaster->numTimesAssignedToASlot,lastVPBeforeMaster,cycles,instrs,cachem); \ 20.24 + (*counterHandler)(AppResponderInvocation_start,lastVPBeforeMaster->slaveNum,lastVPBeforeMaster->numTimesAssignedToASlot,lastVPBeforeMaster,cycles,instrs,cachem); \ 20.25 lastVPBeforeMaster = NULL; \ 20.26 } else { \ 20.27 _PRTopEnv->start_master_lock[thisCoresIdx][0] = cycles; \ 20.28 @@ -395,7 +395,7 @@ 20.29 * would be erroneously counted as invocation time. 20.30 */ 20.31 #define HOLISTIC__Record_AppResponder_start \ 20.32 - vpid = currSlot->slaveAssignedToSlot->slaveID; \ 20.33 + vpid = currSlot->slaveAssignedToSlot->slaveNum; \ 20.34 task = currSlot->slaveAssignedToSlot->numTimesAssignedToASlot; \ 20.35 uint64 cycles, instrs, cachem; \ 20.36 saveCyclesAndInstrs(thisCoresIdx,cycles, instrs,cachem); \ 20.37 @@ -429,30 +429,30 @@ 20.38 uint64 cycles,instrs,cachem; \ 20.39 saveCyclesAndInstrs(thisCoresIdx,cycles,instrs,cachem); \ 20.40 if(empty){ \ 20.41 - (*counterHandler)(AssignerInvocation_start,assignedSlaveVP->slaveID,assignedSlaveVP->numTimesAssignedToASlot,assignedSlaveVP,masterEnv->start_master_lock[thisCoresIdx][0],masterEnv->start_master_lock[thisCoresIdx][1],masterEnv->start_master_lock[thisCoresIdx][2]); \ 20.42 + (*counterHandler)(AssignerInvocation_start,assignedSlaveVP->slaveNum,assignedSlaveVP->numTimesAssignedToASlot,assignedSlaveVP,_PRTopEnv->start_master_lock[thisCoresIdx][0],_PRTopEnv->start_master_lock[thisCoresIdx][1],masterEnv->start_master_lock[thisCoresIdx][2]); \ 20.43 } \ 20.44 - (*counterHandler)(Timestamp_start,assignedSlaveVP->slaveID,assignedSlaveVP->numTimesAssignedToASlot,assignedSlaveVP,tsc,0,0); \ 20.45 - (*counterHandler)(Assigner_start,assignedSlaveVP->slaveID,assignedSlaveVP->numTimesAssignedToASlot,assignedSlaveVP,tmp_cycles,tmp_instrs,tmp_cachem); \ 20.46 - (*counterHandler)(Assigner_end,assignedSlaveVP->slaveID,assignedSlaveVP->numTimesAssignedToASlot,assignedSlaveVP,cycles,instrs,tmp_cachem); 20.47 + (*counterHandler)(Timestamp_start,assignedSlaveVP->slaveNum,assignedSlaveVP->numTimesAssignedToASlot,assignedSlaveVP,tsc,0,0); \ 20.48 + (*counterHandler)(Assigner_start,assignedSlaveVP->slaveNum,assignedSlaveVP->numTimesAssignedToASlot,assignedSlaveVP,tmp_cycles,tmp_instrs,tmp_cachem); \ 20.49 + (*counterHandler)(Assigner_end,assignedSlaveVP->slaveNum,assignedSlaveVP->numTimesAssignedToASlot,assignedSlaveVP,cycles,instrs,tmp_cachem); 20.50 20.51 #define HOLISTIC__Record_Work_start \ 20.52 if(currVP){ \ 20.53 uint64 cycles,instrs,cachem; \ 20.54 saveCyclesAndInstrs(thisCoresIdx,cycles, instrs,cachem); \ 20.55 - (*counterHandler)(Work_start,currVP->slaveID,currVP->numTimesAssignedToASlot,currVP,cycles,instrs,cachem); \ 20.56 + (*counterHandler)(Work_start,currVP->slaveNum,currVP->numTimesAssignedToASlot,currVP,cycles,instrs,cachem); \ 20.57 } 20.58 20.59 #define HOLISTIC__Record_Work_end \ 20.60 if(currVP){ \ 20.61 uint64 cycles,instrs,cachem; \ 20.62 saveCyclesAndInstrs(thisCoresIdx,cycles, instrs,cachem); \ 20.63 - (*counterHandler)(Work_end,currVP->slaveID,currVP->numTimesAssignedToASlot,currVP,cycles,instrs,cachem); \ 20.64 + (*counterHandler)(Work_end,currVP->slaveNum,currVP->numTimesAssignedToASlot,currVP,cycles,instrs,cachem); \ 20.65 } 20.66 20.67 #define HOLISTIC__Record_HwResponderInvocation_start \ 20.68 uint64 cycles,instrs,cachem; \ 20.69 saveCyclesAndInstrs(animatingSlv->coreAnimatedBy,cycles, instrs,cachem); \ 20.70 - (*(_PRTopEnv->counterHandler))(HwResponderInvocation_start,animatingSlv->slaveID,animatingSlv->numTimesAssignedToASlot,animatingSlv,cycles,instrs,cachem); 20.71 + (*(_PRTopEnv->counterHandler))(HwResponderInvocation_start,animatingSlv->slaveNum,animatingSlv->numTimesAssignedToASlot,animatingSlv,cycles,instrs,cachem); 20.72 20.73 20.74 #define getReturnAddressBeforeLibraryCall(vp_ptr, res_ptr) do{ \
21.1 --- a/Services_Offered_by_PR/Memory_Handling/vmalloc.c Sun Nov 04 18:39:28 2012 -0800 21.2 +++ b/Services_Offered_by_PR/Memory_Handling/vmalloc.c Mon Jan 14 15:31:23 2013 -0800 21.3 @@ -366,8 +366,7 @@ 21.4 PR_ext__create_free_list() 21.5 { 21.6 //Initialize containers for small chunks and fill with zeros 21.7 - _PRTopEnv->freeLists = (MallocArrays*)malloc( sizeof(MallocArrays) ); 21.8 - MallocArrays *freeLists = _PRTopEnv->freeLists; 21.9 + MallocArrays *freeLists = (MallocArrays*)malloc( sizeof(MallocArrays) ); 21.10 21.11 freeLists->smallChunks = 21.12 (MallocProlog**)malloc(SMALL_CHUNK_COUNT*sizeof(MallocProlog*));