Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
comparison MasterLoop.c @ 209:0c83ea8adefc
Close to compilable version of common_ancestor -- still includes HW dep stuff
| author | Some Random Person <seanhalle@yahoo.com> |
|---|---|
| date | Sun, 04 Mar 2012 14:26:35 -0800 |
| parents | eaf7e4c58c9e |
| children | a18539c0bc37 |
comparison
equal
deleted
inserted
replaced
| 58:9335afc4a64d | 59:fb4f1317b78c |
|---|---|
| 8 | 8 |
| 9 #include <stdio.h> | 9 #include <stdio.h> |
| 10 #include <stddef.h> | 10 #include <stddef.h> |
| 11 | 11 |
| 12 #include "VMS.h" | 12 #include "VMS.h" |
| 13 #include "ProcrContext.h" | |
| 14 | 13 |
| 15 | 14 |
| 16 //=========================================================================== | 15 //=========================================================================== |
| 17 void inline | 16 void inline |
| 18 stealWorkInto( SchedSlot *currSlot, VMSQueueStruc *readyToAnimateQ, | 17 stealWorkInto( SchedSlot *currSlot, VMSQueueStruc *readyToAnimateQ, |
| 19 SlaveVP *masterPr ); | 18 SlaveVP *masterVP ); |
| 20 | 19 |
| 21 //=========================================================================== | 20 //=========================================================================== |
| 22 | 21 |
| 23 | 22 |
| 24 | 23 |
| 25 /*This code is animated by the virtual Master processor. | 24 /*This code is animated by the virtual Master processor. |
| 26 * | 25 * |
| 27 *Polls each sched slot exactly once, hands any requests made by a newly | 26 *Polls each sched slot exactly once, hands any requests made by a newly |
| 28 * done slave to the "request handler" plug-in function | 27 * done slave to the "request handler" plug-in function |
| 29 * | 28 * |
| 30 *Any slots that need a virt procr assigned are given to the "schedule" | 29 *Any slots that need a Slv assigned are given to the "schedule" |
| 31 * plug-in function, which tries to assign a virt procr (slave) to it. | 30 * plug-in function, which tries to assign a Slv (slave) to it. |
| 32 * | 31 * |
| 33 *When all slots needing a processor have been given to the schedule plug-in, | 32 *When all slots needing a processor have been given to the schedule plug-in, |
| 34 * a fraction of the procrs successfully scheduled are put into the | 33 * a fraction of the slaves successfully scheduled are put into the |
| 35 * work queue, then a continuation of this function is put in, then the rest | 34 * work queue, then a continuation of this function is put in, then the rest |
| 36 * of the virt procrs that were successfully scheduled. | 35 * of the Slvs that were successfully scheduled. |
| 37 * | 36 * |
| 38 *The first thing the continuation does is busy-wait until the previous | 37 *The first thing the continuation does is busy-wait until the previous |
| 39 * animation completes. This is because an (unlikely) continuation may | 38 * animation completes. This is because an (unlikely) continuation may |
| 40 * sneak through queue before previous continuation is done putting second | 39 * sneak through queue before previous continuation is done putting second |
| 41 * part of scheduled slaves in, which is the only race condition. | 40 * part of scheduled slaves in, which is the only race condition. |
| 44 | 43 |
| 45 /*May 29, 2010 -- birth a Master during init so that first core loop to | 44 /*May 29, 2010 -- birth a Master during init so that first core loop to |
| 46 * start running gets it and does all the stuff for a newly born -- | 45 * start running gets it and does all the stuff for a newly born -- |
| 47 * from then on, will be doing continuation, but do suspension self | 46 * from then on, will be doing continuation, but do suspension self |
| 48 * directly at end of master loop | 47 * directly at end of master loop |
| 49 *So VMS__init just births the master virtual processor same way it births | 48 *So VMS_WL__init just births the master virtual processor same way it births |
| 50 * all the others -- then does any extra setup needed and puts it into the | 49 * all the others -- then does any extra setup needed and puts it into the |
| 51 * work queue. | 50 * work queue. |
| 52 *However means have to make masterEnv a global static volatile the same way | 51 *However means have to make masterEnv a global static volatile the same way |
| 53 * did with readyToAnimateQ in core loop. -- for performance, put the | 52 * did with readyToAnimateQ in core loop. -- for performance, put the |
| 54 * jump to the core loop directly in here, and have it directly jump back. | 53 * jump to the core loop directly in here, and have it directly jump back. |
| 63 * animates this function has a different one. | 62 * animates this function has a different one. |
| 64 * | 63 * |
| 65 *At this point, the masterLoop does not write itself into the queue anymore, | 64 *At this point, the masterLoop does not write itself into the queue anymore, |
| 66 * instead, the coreLoop acquires the masterLock when it has nothing to | 65 * instead, the coreLoop acquires the masterLock when it has nothing to |
| 67 * animate, and then animates its own masterLoop. However, still try to put | 66 * animate, and then animates its own masterLoop. However, still try to put |
| 68 * several AppVPs into the queue to amortize the startup cost of switching | 67 * several AppSlvs into the queue to amortize the startup cost of switching |
| 69 * to the MasterVP. Note, don't have to worry about latency of requests much | 68 * to the MasterVP. Note, don't have to worry about latency of requests much |
| 70 * because most requests generate work for same core -- only latency issue | 69 * because most requests generate work for same core -- only latency issue |
| 71 * is case when other cores starved and one core's requests generate work | 70 * is case when other cores starved and one core's requests generate work |
| 72 * for them -- so keep max in queue to 3 or 4.. | 71 * for them -- so keep max in queue to 3 or 4.. |
| 73 */ | 72 */ |
| 74 void masterLoop( void *initData, SlaveVP *animatingPr ) | 73 void masterLoop( void *initData, SlaveVP *animatingSlv ) |
| 75 { | 74 { |
| 76 int32 slotIdx, numSlotsFilled; | 75 int32 slotIdx, numSlotsFilled; |
| 77 SlaveVP *schedVirtPr; | 76 SlaveVP *schedSlaveVP; |
| 78 SchedSlot *currSlot, **schedSlots; | 77 SchedSlot *currSlot, **schedSlots; |
| 79 MasterEnv *masterEnv; | 78 MasterEnv *masterEnv; |
| 80 VMSQueueStruc *readyToAnimateQ; | 79 VMSQueueStruc *readyToAnimateQ; |
| 81 | 80 |
| 82 Sched_Assigner slaveScheduler; | 81 Sched_Assigner slaveAssigner; |
| 83 RequestHandler requestHandler; | 82 RequestHandler requestHandler; |
| 84 void *semanticEnv; | 83 void *semanticEnv; |
| 85 | 84 |
| 86 int32 thisCoresIdx; | 85 int32 thisCoresIdx; |
| 87 SlaveVP *masterPr; | 86 SlaveVP *masterVP; |
| 88 volatile SlaveVP *volatileMasterPr; | 87 volatile SlaveVP *volatileMasterVP; |
| 89 | 88 |
| 90 volatileMasterPr = animatingPr; | 89 volatileMasterVP = animatingSlv; |
| 91 masterPr = (SlaveVP*)volatileMasterPr; //used to force re-define after jmp | 90 masterVP = (SlaveVP*)volatileMasterVP; //used to force re-define after jmp |
| 92 | 91 |
| 93 //First animation of each MasterVP will in turn animate this part | 92 //First animation of each MasterVP will in turn animate this part |
| 94 // of setup code.. (VP creator sets up the stack as if this function | 93 // of setup code.. (Slv creator sets up the stack as if this function |
| 95 // was called normally, but actually get here by jmp) | 94 // was called normally, but actually get here by jmp) |
| 96 //So, setup values about stack ptr, jmp pt and all that | 95 //So, setup values about stack ptr, jmp pt and all that |
| 97 //masterPr->resumeInstrPtr = &&masterLoopStartPt; | 96 //masterVP->resumeInstrPtr = &&masterLoopStartPt; |
| 98 | 97 |
| 99 | 98 |
| 100 //Note, got rid of writing the stack and frame ptr up here, because | 99 //Note, got rid of writing the stack and frame ptr up here, because |
| 101 // only one | 100 // only one |
| 102 // core can ever animate a given MasterVP, so don't need to communicate | 101 // core can ever animate a given MasterVP, so don't need to communicate |
| 106 | 105 |
| 107 | 106 |
| 108 //masterLoopStartPt: | 107 //masterLoopStartPt: |
| 109 while(1){ | 108 while(1){ |
| 110 | 109 |
| 111 //============================= MEASUREMENT STUFF ======================== | 110 MEAS__Capture_Pre_Master_Point |
| 112 #ifdef MEAS__TIME_MASTER | |
| 113 //Total Master time includes one coreloop time -- just assume the core | |
| 114 // loop time is same for Master as for AppVPs, even though it may be | |
| 115 // smaller due to higher predictability of the fixed jmp. | |
| 116 saveLowTimeStampCountInto( masterPr->startMasterTSCLow ); | |
| 117 #endif | |
| 118 //======================================================================== | |
| 119 | 111 |
| 120 masterEnv = (MasterEnv*)_VMSMasterEnv; | 112 masterEnv = (MasterEnv*)_VMSMasterEnv; |
| 121 | 113 |
| 122 //GCC may optimize so doesn't always re-define from frame-storage | 114 //GCC may optimize so doesn't always re-define from frame-storage |
| 123 masterPr = (SlaveVP*)volatileMasterPr; //just to make sure after jmp | 115 masterVP = (SlaveVP*)volatileMasterVP; //just to make sure after jmp |
| 124 thisCoresIdx = masterPr->coreAnimatedBy; | 116 thisCoresIdx = masterVP->coreAnimatedBy; |
| 125 readyToAnimateQ = masterEnv->readyToAnimateQs[thisCoresIdx]; | 117 readyToAnimateQ = masterEnv->readyToAnimateQs[thisCoresIdx]; |
| 126 schedSlots = masterEnv->allSchedSlots[thisCoresIdx]; | 118 schedSlots = masterEnv->allSchedSlots[thisCoresIdx]; |
| 127 | 119 |
| 128 requestHandler = masterEnv->requestHandler; | 120 requestHandler = masterEnv->requestHandler; |
| 129 slaveScheduler = masterEnv->slaveSchedAssigner; | 121 slaveAssigner = masterEnv->slaveAssigner; |
| 130 semanticEnv = masterEnv->semanticEnv; | 122 semanticEnv = masterEnv->semanticEnv; |
| 131 | 123 |
| 132 | 124 |
| 133 //Poll each slot's Done flag | 125 //Poll each slot's Done flag |
| 134 numSlotsFilled = 0; | 126 numSlotsFilled = 0; |
| 137 currSlot = schedSlots[ slotIdx ]; | 129 currSlot = schedSlots[ slotIdx ]; |
| 138 | 130 |
| 139 if( currSlot->workIsDone ) | 131 if( currSlot->workIsDone ) |
| 140 { | 132 { |
| 141 currSlot->workIsDone = FALSE; | 133 currSlot->workIsDone = FALSE; |
| 142 currSlot->needsProcrAssigned = TRUE; | 134 currSlot->needsSlaveAssigned = TRUE; |
| 143 | 135 |
| 144 //process requests from slave to master | 136 //process requests from slave to master |
| 145 //====================== MEASUREMENT STUFF =================== | 137 //====================== MEASUREMENT STUFF =================== |
| 146 #ifdef MEAS__TIME_PLUGIN | 138 #ifdef MEAS__TURN_ON_PLUGIN_MEAS |
| 147 int32 startStamp1, endStamp1; | 139 int32 startStamp1, endStamp1; |
| 148 saveLowTimeStampCountInto( startStamp1 ); | 140 saveLowTimeStampCountInto( startStamp1 ); |
| 149 #endif | 141 #endif |
| 150 //============================================================ | 142 //============================================================ |
| 151 (*requestHandler)( currSlot->procrAssignedToSlot, semanticEnv ); | 143 (*requestHandler)( currSlot->slaveAssignedToSlot, semanticEnv ); |
| 152 //====================== MEASUREMENT STUFF =================== | 144 //====================== MEASUREMENT STUFF =================== |
| 153 #ifdef MEAS__TIME_PLUGIN | 145 #ifdef MEAS__TURN_ON_PLUGIN_MEAS |
| 154 saveLowTimeStampCountInto( endStamp1 ); | 146 saveLowTimeStampCountInto( endStamp1 ); |
| 155 addIntervalToHist( startStamp1, endStamp1, | 147 addIntervalToHist( startStamp1, endStamp1, |
| 156 _VMSMasterEnv->reqHdlrLowTimeHist ); | 148 _VMSMasterEnv->reqHdlrLowTimeHist ); |
| 157 addIntervalToHist( startStamp1, endStamp1, | 149 addIntervalToHist( startStamp1, endStamp1, |
| 158 _VMSMasterEnv->reqHdlrHighTimeHist ); | 150 _VMSMasterEnv->reqHdlrHighTimeHist ); |
| 159 #endif | 151 #endif |
| 160 //============================================================ | 152 //============================================================ |
| 161 } | 153 } |
| 162 if( currSlot->needsProcrAssigned ) | 154 if( currSlot->needsSlaveAssigned ) |
| 163 { //give slot a new virt procr | 155 { //give slot a new Slv |
| 164 schedVirtPr = | 156 schedSlaveVP = |
| 165 (*slaveScheduler)( semanticEnv, thisCoresIdx ); | 157 (*slaveAssigner)( semanticEnv, thisCoresIdx ); |
| 166 | 158 |
| 167 if( schedVirtPr != NULL ) | 159 if( schedSlaveVP != NULL ) |
| 168 { currSlot->procrAssignedToSlot = schedVirtPr; | 160 { currSlot->slaveAssignedToSlot = schedSlaveVP; |
| 169 schedVirtPr->schedSlot = currSlot; | 161 schedSlaveVP->schedSlot = currSlot; |
| 170 currSlot->needsProcrAssigned = FALSE; | 162 currSlot->needsSlaveAssigned = FALSE; |
| 171 numSlotsFilled += 1; | 163 numSlotsFilled += 1; |
| 172 | 164 |
| 173 writeVMSQ( schedVirtPr, readyToAnimateQ ); | 165 writeVMSQ( schedSlaveVP, readyToAnimateQ ); |
| 174 } | 166 } |
| 175 } | 167 } |
| 176 } | 168 } |
| 177 | 169 |
| 178 | 170 |
| 179 #ifdef USE_WORK_STEALING | 171 #ifdef USE_WORK_STEALING |
| 180 //If no slots filled, means no more work, look for work to steal. | 172 //If no slots filled, means no more work, look for work to steal. |
| 181 if( numSlotsFilled == 0 ) | 173 if( numSlotsFilled == 0 ) |
| 182 { gateProtected_stealWorkInto( currSlot, readyToAnimateQ, masterPr ); | 174 { gateProtected_stealWorkInto( currSlot, readyToAnimateQ, masterVP ); |
| 183 } | 175 } |
| 184 #endif | 176 #endif |
| 185 | 177 |
| 186 | 178 MEAS__Capture_Post_Master_Point; |
| 187 #ifdef MEAS__TIME_MASTER | 179 |
| 188 saveLowTimeStampCountInto( masterPr->endMasterTSCLow ); | 180 masterSwitchToCoreLoop(animatingSlv); |
| 189 #endif | |
| 190 | |
| 191 masterSwitchToCoreLoop(animatingPr); | |
| 192 flushRegisters(); | 181 flushRegisters(); |
| 193 }//MasterLoop | 182 }//MasterLoop |
| 194 | 183 |
| 195 | 184 |
| 196 } | 185 } |
| 200 /*This has a race condition -- the coreloops are accessing their own queues | 189 /*This has a race condition -- the coreloops are accessing their own queues |
| 201 * at the same time that this work-stealer on a different core is trying to | 190 * at the same time that this work-stealer on a different core is trying to |
| 202 */ | 191 */ |
| 203 void inline | 192 void inline |
| 204 stealWorkInto( SchedSlot *currSlot, VMSQueueStruc *readyToAnimateQ, | 193 stealWorkInto( SchedSlot *currSlot, VMSQueueStruc *readyToAnimateQ, |
| 205 SlaveVP *masterPr ) | 194 SlaveVP *masterVP ) |
| 206 { | 195 { |
| 207 SlaveVP *stolenPr; | 196 SlaveVP *stolenSlv; |
| 208 int32 coreIdx, i; | 197 int32 coreIdx, i; |
| 209 VMSQueueStruc *currQ; | 198 VMSQueueStruc *currQ; |
| 210 | 199 |
| 211 stolenPr = NULL; | 200 stolenSlv = NULL; |
| 212 coreIdx = masterPr->coreAnimatedBy; | 201 coreIdx = masterVP->coreAnimatedBy; |
| 213 for( i = 0; i < NUM_CORES -1; i++ ) | 202 for( i = 0; i < NUM_CORES -1; i++ ) |
| 214 { | 203 { |
| 215 if( coreIdx >= NUM_CORES -1 ) | 204 if( coreIdx >= NUM_CORES -1 ) |
| 216 { coreIdx = 0; | 205 { coreIdx = 0; |
| 217 } | 206 } |
| 218 else | 207 else |
| 219 { coreIdx++; | 208 { coreIdx++; |
| 220 } | 209 } |
| 221 currQ = _VMSMasterEnv->readyToAnimateQs[coreIdx]; | 210 currQ = _VMSMasterEnv->readyToAnimateQs[coreIdx]; |
| 222 if( numInVMSQ( currQ ) > 0 ) | 211 if( numInVMSQ( currQ ) > 0 ) |
| 223 { stolenPr = readVMSQ (currQ ); | 212 { stolenSlv = readVMSQ (currQ ); |
| 224 break; | 213 break; |
| 225 } | 214 } |
| 226 } | 215 } |
| 227 | 216 |
| 228 if( stolenPr != NULL ) | 217 if( stolenSlv != NULL ) |
| 229 { currSlot->procrAssignedToSlot = stolenPr; | 218 { currSlot->slaveAssignedToSlot = stolenSlv; |
| 230 stolenPr->schedSlot = currSlot; | 219 stolenSlv->schedSlot = currSlot; |
| 231 currSlot->needsProcrAssigned = FALSE; | 220 currSlot->needsSlaveAssigned = FALSE; |
| 232 | 221 |
| 233 writeVMSQ( stolenPr, readyToAnimateQ ); | 222 writeVMSQ( stolenSlv, readyToAnimateQ ); |
| 234 } | 223 } |
| 235 } | 224 } |
| 236 | 225 |
| 237 /*This algorithm makes the common case fast. Make the coreloop passive, | 226 /*This algorithm makes the common case fast. Make the coreloop passive, |
| 238 * and show its progress. Make the stealer control a gate that coreloop | 227 * and show its progress. Make the stealer control a gate that coreloop |
| 304 * | 293 * |
| 305 */ | 294 */ |
| 306 void inline | 295 void inline |
| 307 gateProtected_stealWorkInto( SchedSlot *currSlot, | 296 gateProtected_stealWorkInto( SchedSlot *currSlot, |
| 308 VMSQueueStruc *myReadyToAnimateQ, | 297 VMSQueueStruc *myReadyToAnimateQ, |
| 309 SlaveVP *masterPr ) | 298 SlaveVP *masterVP ) |
| 310 { | 299 { |
| 311 SlaveVP *stolenPr; | 300 SlaveVP *stolenSlv; |
| 312 int32 coreIdx, i, haveAVictim, gotLock; | 301 int32 coreIdx, i, haveAVictim, gotLock; |
| 313 VMSQueueStruc *victimsQ; | 302 VMSQueueStruc *victimsQ; |
| 314 | 303 |
| 315 volatile GateStruc *vicGate; | 304 volatile GateStruc *vicGate; |
| 316 int32 coreMightBeInProtected; | 305 int32 coreMightBeInProtected; |
| 317 | 306 |
| 318 | 307 |
| 319 | 308 |
| 320 //see if any other cores have work available to steal | 309 //see if any other cores have work available to steal |
| 321 haveAVictim = FALSE; | 310 haveAVictim = FALSE; |
| 322 coreIdx = masterPr->coreAnimatedBy; | 311 coreIdx = masterVP->coreAnimatedBy; |
| 323 for( i = 0; i < NUM_CORES -1; i++ ) | 312 for( i = 0; i < NUM_CORES -1; i++ ) |
| 324 { | 313 { |
| 325 if( coreIdx >= NUM_CORES -1 ) | 314 if( coreIdx >= NUM_CORES -1 ) |
| 326 { coreIdx = 0; | 315 { coreIdx = 0; |
| 327 } | 316 } |
| 352 coreMightBeInProtected = FALSE; | 341 coreMightBeInProtected = FALSE; |
| 353 if( vicGate->preGateProgress == vicGate->exitProgress ) | 342 if( vicGate->preGateProgress == vicGate->exitProgress ) |
| 354 coreMightBeInProtected = FALSE; | 343 coreMightBeInProtected = FALSE; |
| 355 } | 344 } |
| 356 | 345 |
| 357 stolenPr = readVMSQ ( victimsQ ); | 346 stolenSlv = readVMSQ ( victimsQ ); |
| 358 | 347 |
| 359 vicGate->gateClosed = FALSE; | 348 vicGate->gateClosed = FALSE; |
| 360 //======= End Gate-protection ======= | 349 //======= End Gate-protection ======= |
| 361 | 350 |
| 362 | 351 |
| 363 if( stolenPr != NULL ) //victim could have been in protected and taken | 352 if( stolenSlv != NULL ) //victim could have been in protected and taken |
| 364 { currSlot->procrAssignedToSlot = stolenPr; | 353 { currSlot->slaveAssignedToSlot = stolenSlv; |
| 365 stolenPr->schedSlot = currSlot; | 354 stolenSlv->schedSlot = currSlot; |
| 366 currSlot->needsProcrAssigned = FALSE; | 355 currSlot->needsSlaveAssigned = FALSE; |
| 367 | 356 |
| 368 writeVMSQ( stolenPr, myReadyToAnimateQ ); | 357 writeVMSQ( stolenSlv, myReadyToAnimateQ ); |
| 369 } | 358 } |
| 370 | 359 |
| 371 //unlock the work stealing lock | 360 //unlock the work stealing lock |
| 372 _VMSMasterEnv->workStealingLock = UNLOCKED; | 361 _VMSMasterEnv->workStealingLock = UNLOCKED; |
| 373 } | 362 } |
