Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
comparison MasterLoop.c @ 31:e69579a0e797
Works multi-core.. pinned VP to a core loop
| author | Me |
|---|---|
| date | Wed, 01 Sep 2010 08:23:39 -0700 |
| parents | c8823e0bb2b4 |
| children | 17d20e5cf924 |
comparison
equal
deleted
inserted
replaced
| 8:acd91b87dcdc | 9:73e221819099 |
|---|---|
| 40 * directly at end of master loop | 40 * directly at end of master loop |
| 41 *So VMS__init just births the master virtual processor same way it births | 41 *So VMS__init just births the master virtual processor same way it births |
| 42 * all the others -- then does any extra setup needed and puts it into the | 42 * all the others -- then does any extra setup needed and puts it into the |
| 43 * work queue. | 43 * work queue. |
| 44 *However means have to make masterEnv a global static volatile the same way | 44 *However means have to make masterEnv a global static volatile the same way |
| 45 * did with workQ in core loop. -- for performance, put the | 45 * did with readyToAnimateQ in core loop. -- for performance, put the |
| 46 * jump to the core loop directly in here, and have it directly jump back. | 46 * jump to the core loop directly in here, and have it directly jump back. |
| 47 * | |
| 48 * | |
| 49 *Aug 18, 2010 -- Going to a separate MasterVP for each core, to see if this | |
| 50 * avoids the suspected bug in the system stack that causes bizarre faults | |
| 51 * at random places in the system code. | |
| 52 * | |
| 53 *So, this function is coupled to each of the MasterVPs, -- meaning this | |
| 54 * function can't rely on a particular stack and frame -- each MasterVP that | |
| 55 * animates this function has a different one. | |
| 56 * | |
| 57 *At this point, the masterLoop does not write itself into the queue anymore, | |
| 58 * instead, the coreLoop acquires the masterLock when it has nothing to | |
| 59 * animate, and then animates its own masterLoop. However, still try to put | |
| 60 * several AppVPs into the queue to amortize the startup cost of switching | |
| 61 * to the MasterVP. Note, don't have to worry about latency of requests much | |
| 62 * because most requests generate work for same core -- only latency issue | |
| 63 * is case when other cores starved and one core's requests generate work | |
| 64 * for them -- so keep max in queue to 3 or 4.. | |
| 47 */ | 65 */ |
| 48 void masterLoop( void *initData, VirtProcr *masterPr ) | 66 void masterLoop( void *initData, VirtProcr *animatingPr ) |
| 49 { | 67 { |
| 50 int slotIdx, numFilled, filledSlotIdx, masterHasBeenQueued; | 68 int slotIdx; |
| 51 VirtProcr *schedVirtPr; | 69 VirtProcr *schedVirtPr; |
| 52 SchedSlot *currSlot, **schedSlots, **filledSlots; | 70 SchedSlot *currSlot, **schedSlots; |
| 53 MasterEnv *masterEnv; | 71 MasterEnv *masterEnv; |
| 54 VMSQueueStruc *workQ; | 72 VMSQueueStruc *readyToAnimateQ; |
| 55 void *jmpPt, *stackPtrAddr, *framePtrAddr, *stillRunningAddr; | |
| 56 void *coreLoopFramePtr, *coreLoopStackPtr, *semanticEnv; | |
| 57 | 73 |
| 58 SlaveScheduler slaveScheduler; | 74 SlaveScheduler slaveScheduler; |
| 59 RequestHandler requestHandler; | 75 RequestHandler requestHandler; |
| 76 void *semanticEnv; | |
| 60 | 77 |
| 61 //this will run as the first virt processor in workQ, and will be a | 78 int thisCoresIdx; |
| 62 // new born -- so will do all the GCC-generated allocating space on | 79 VirtProcr *masterPr; |
| 63 // the stack owned by master virt procr -- and will run this last bit | 80 volatile VirtProcr *volatileMasterPr; |
| 64 // of setup code.. | 81 |
| 82 volatileMasterPr = animatingPr; | |
| 83 masterPr = volatileMasterPr; //used to force re-define after jmp | |
| 84 | |
| 85 //First animation of each MasterVP will in turn animate this part | |
| 86 // of setup code.. (VP creator sets up the stack as if this function | |
| 87 // was called normally, but actually get here by jmp) | |
| 88 //So, setup values about stack ptr, jmp pt and all that | |
| 65 masterPr->nextInstrPt = &&masterLoopStartPt; | 89 masterPr->nextInstrPt = &&masterLoopStartPt; |
| 66 | 90 |
| 67 //The second time MasterVP comes out of queue, the first animation of | |
| 68 // it hasn't written the stackPtr and framePtr yet -- but the second | |
| 69 // animation has already had its stackPtr and framePtr set to the old | |
| 70 // value by the coreLoop. Fix this by writing the correct stack and | |
| 71 // frame pointers here, at which point they're correct in the first | |
| 72 // animation of MasterVP. | |
| 73 //TODO: remove writing stackPtr and framePtr at the bottom, for eff | |
| 74 stackPtrAddr = &(masterPr->stackPtr); | |
| 75 framePtrAddr = &(masterPr->framePtr); | |
| 76 | 91 |
| 77 asm volatile("movl %0, %%eax; \ | 92 //Note, got rid of writing the stack and frame ptr up here, because |
| 78 movl %%esp, (%%eax); \ | 93 // only one |
| 79 movl %1, %%eax; \ | 94 // core can ever animate a given MasterVP, so don't need to communicate |
| 80 movl %%ebp, (%%eax); " | 95 // new frame and stack ptr to the MasterVP storage before a second |
| 81 /* outputs */ : "=g" (stackPtrAddr), "=g" (framePtrAddr) \ | 96 // version of that MasterVP can get animated on a different core. |
| 82 /* inputs */ : \ | 97 //Also got rid of the busy-wait. |
| 83 /* clobber */ : "memory", "%eax", "%ebx" \ | 98 |
| 84 ); | 99 |
| 100 masterLoopStartPt: | |
| 101 | |
| 102 masterEnv = _VMSMasterEnv; | |
| 103 | |
| 104 //TODO: check that compiles so that always re-define from frame-storage | |
| 105 masterPr = volatileMasterPr; //just to make sure after jmp | |
| 106 thisCoresIdx = masterPr->coreAnimatedBy; | |
| 107 readyToAnimateQ = masterEnv->readyToAnimateQs[thisCoresIdx]; | |
| 108 schedSlots = masterEnv->allSchedSlots[thisCoresIdx]; | |
| 109 | |
| 110 requestHandler = masterEnv->requestHandler; | |
| 111 slaveScheduler = masterEnv->slaveScheduler; | |
| 112 semanticEnv = masterEnv->semanticEnv; | |
| 85 | 113 |
| 86 | 114 |
| 87 masterLoopStartPt: | 115 //Poll each slot's Done flag |
| 88 | |
| 89 //if another reference to same Master VirtProcr still going, busy-wait | |
| 90 //Could put this lower, but don't want to think about shared stack.. | |
| 91 while( _VMSMasterEnv->stillRunning ) /*busy wait*/ ; | |
| 92 //TODO: want to do busy-wait as assembly, to be sure stack not touched? | |
| 93 | |
| 94 //this is the only master running now, set flag again | |
| 95 _VMSMasterEnv->stillRunning = TRUE; | |
| 96 masterEnv = _VMSMasterEnv; | |
| 97 | |
| 98 //TODO: gdb -- check that a volatile _VMSMasterEnv and _VMSWorkQ means | |
| 99 // all these will be re-filled every time jump here.. | |
| 100 workQ = _VMSWorkQ; | |
| 101 requestHandler = masterEnv->requestHandler; | |
| 102 slaveScheduler = masterEnv->slaveScheduler; | |
| 103 schedSlots = masterEnv->schedSlots; | |
| 104 filledSlots = masterEnv->filledSlots; | |
| 105 masterPr = masterEnv->masterVirtPr; //post-jmp clobbered, re-load | |
| 106 semanticEnv = masterEnv->semanticEnv; | |
| 107 | |
| 108 //prepare for scheduling | |
| 109 numFilled = 0; | |
| 110 masterHasBeenQueued = FALSE; | |
| 111 | |
| 112 //Poll each slot's Done flag -- slot 0 reserved for master, start at 1 | |
| 113 for( slotIdx = 0; slotIdx < NUM_SCHED_SLOTS; slotIdx++) | 116 for( slotIdx = 0; slotIdx < NUM_SCHED_SLOTS; slotIdx++) |
| 114 { | 117 { |
| 115 currSlot = schedSlots[ slotIdx ]; | 118 currSlot = schedSlots[ slotIdx ]; |
| 116 | 119 |
| 117 if( currSlot->workIsDone ) | 120 if( currSlot->workIsDone ) |
| 123 (*requestHandler)( currSlot->procrAssignedToSlot, semanticEnv ); | 126 (*requestHandler)( currSlot->procrAssignedToSlot, semanticEnv ); |
| 124 } | 127 } |
| 125 if( currSlot->needsProcrAssigned ) | 128 if( currSlot->needsProcrAssigned ) |
| 126 { //give slot a new virt procr | 129 { //give slot a new virt procr |
| 127 schedVirtPr = | 130 schedVirtPr = |
| 128 (*slaveScheduler)( semanticEnv ); | 131 (*slaveScheduler)( semanticEnv, thisCoresIdx ); |
| 129 | 132 |
| 130 if( schedVirtPr != NULL ) | 133 if( schedVirtPr != NULL ) |
| 131 { currSlot->procrAssignedToSlot = schedVirtPr; | 134 { currSlot->procrAssignedToSlot = schedVirtPr; |
| 132 schedVirtPr->schedSlot = currSlot; | 135 schedVirtPr->schedSlot = currSlot; |
| 133 currSlot->needsProcrAssigned = FALSE; | 136 currSlot->needsProcrAssigned = FALSE; |
| 134 | 137 |
| 135 filledSlots[ numFilled ] = currSlot; | 138 writeSRSWQ( schedVirtPr, readyToAnimateQ ); |
| 136 | |
| 137 writeVMSQ( schedVirtPr, workQ ); | |
| 138 numFilled += 1; | |
| 139 | |
| 140 if( numFilled == masterEnv->numToPrecede ) | |
| 141 { | |
| 142 writeVMSQ( masterEnv->masterVirtPr, workQ ); | |
| 143 masterHasBeenQueued = TRUE; | |
| 144 } | |
| 145 | |
| 146 } | 139 } |
| 147 } | 140 } |
| 148 } | 141 } |
| 149 | 142 |
| 150 if( !masterHasBeenQueued ) | |
| 151 { | |
| 152 writeVMSQ( masterEnv->masterVirtPr, workQ ); | |
| 153 } | |
| 154 | 143 |
| 155 //Adjust the number to precede, for next round -- assume rate of | 144 //Save stack ptr and frame, restore CoreLoop's stack and frame, |
| 156 // finishing work is stable -- which is a bad assumption! But, just | 145 // and clear the MasterLock |
| 157 // want something working for the moment, look at dynamic behavior | |
| 158 // later | |
| 159 //TODO: look at dynamic behavior -- time-average numToPrecede or something | |
| 160 if( numFilled < NUM_CORES - 1 ) | |
| 161 { | |
| 162 masterEnv->numToPrecede = 1; | |
| 163 } | |
| 164 else | |
| 165 { masterEnv->numToPrecede = numFilled - NUM_CORES + 1; | |
| 166 } | |
| 167 | |
| 168 //Save stack ptr and frame -- don't need to, take out later, but safe | |
| 169 // Also, wait to set stillRunning to FALSE until just before jump, to | |
| 170 // be safe -- although the two simulatneously animated MasterLoops | |
| 171 // are on different cores, so have different stacks, so no worries | |
| 172 // there. | |
| 173 //Restore CoreLoop's stack frame (and stack pointer, to be safe) | |
| 174 //TODO: cafefully verify don't need to force saving anything to stack | 146 //TODO: cafefully verify don't need to force saving anything to stack |
| 175 // before jumping back to core loop. | 147 // before jumping back to core loop. |
| 148 void *stackPtrAddr, *framePtrAddr, *masterLockAddr; | |
| 149 void *jmpPt, *coreLoopFramePtr, *coreLoopStackPtr; | |
| 150 | |
| 176 stackPtrAddr = &(masterPr->stackPtr); | 151 stackPtrAddr = &(masterPr->stackPtr); |
| 177 framePtrAddr = &(masterPr->framePtr); | 152 framePtrAddr = &(masterPr->framePtr); |
| 178 stillRunningAddr = &(_VMSMasterEnv->stillRunning); //when race condition | 153 masterLockAddr = &(_VMSMasterEnv->masterLock); |
| 179 //arises, stillRunning is shared between the two cores both animating | |
| 180 // MasterLoop -- but those two cores have different esp & ebp, so safe | |
| 181 // to change stack and frame pointer here, without one messing up other | |
| 182 // one | |
| 183 | 154 |
| 184 jmpPt = masterPr->coreLoopStartPt; | 155 jmpPt = _VMSMasterEnv->coreLoopStartPt; |
| 185 coreLoopFramePtr = masterPr->coreLoopFramePtr;//need this only | 156 coreLoopFramePtr = masterPr->coreLoopFramePtr;//need this only |
| 186 coreLoopStackPtr = masterPr->coreLoopStackPtr;//shouldn't need -- safety | 157 coreLoopStackPtr = masterPr->coreLoopStackPtr;//shouldn't need -- safety |
| 187 | 158 |
| 188 asm volatile("movl %0, %%eax; \ | 159 asm volatile("movl %0, %%eax; \ |
| 189 movl %%esp, (%%eax); \ | 160 movl %%esp, (%%eax); \ |
| 194 movl %4, %%esp; \ | 165 movl %4, %%esp; \ |
| 195 movl %5, %%ebp; \ | 166 movl %5, %%ebp; \ |
| 196 movl $0x0, (%%ebx); \ | 167 movl $0x0, (%%ebx); \ |
| 197 jmp %%eax;" \ | 168 jmp %%eax;" \ |
| 198 /* outputs */ : "=g" (stackPtrAddr), "=g" (framePtrAddr), \ | 169 /* outputs */ : "=g" (stackPtrAddr), "=g" (framePtrAddr), \ |
| 199 "=g"(stillRunningAddr) \ | 170 "=g"(masterLockAddr) \ |
| 200 /* inputs */ : "g" (jmpPt), "g"(coreLoopStackPtr), "g"(coreLoopFramePtr)\ | 171 /* inputs */ : "g" (jmpPt), "g"(coreLoopStackPtr), "g"(coreLoopFramePtr)\ |
| 201 /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" \ | 172 /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" \ |
| 202 );//can probably make clobber list empty -- but safe for now | 173 );//can probably make clobber list empty -- but safe for now |
| 203 } | 174 } |
| 204 | 175 |
