Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
diff MasterLoop.c @ 21:a0af8d4fca35
Full VMS test -- works
| author | Me |
|---|---|
| date | Wed, 30 Jun 2010 13:10:34 -0700 |
| parents | e2de204909bf |
| children | 668278fa7a63 |
line diff
1.1 --- a/MasterLoop.c Wed Jun 30 13:10:26 2010 -0700 1.2 +++ b/MasterLoop.c Wed Jun 30 13:10:34 2010 -0700 1.3 @@ -47,12 +47,14 @@ 1.4 * jump to the core loop directly in here, and have it directly jump back. 1.5 */ 1.6 void masterLoop( void *initData, VirtProcr *masterPr ) 1.7 - { bool8 retCode; 1.8 - int slotIdx, numScheduled, numInFirstChunk, filledSlotIdx; 1.9 + { 1.10 + int slotIdx, numFilled, numInFirstChunk, filledSlotIdx; 1.11 + VirtProcr *schedVirtPr; 1.12 SchedSlot *currSlot, **schedSlots, **filledSlots; 1.13 MasterEnv *masterEnv; 1.14 CASQueueStruc *workQ; 1.15 - void *jmpPt; 1.16 + void *jmpPt, *stackPtrAddr, *framePtrAddr, *stillRunningAddr; 1.17 + void *coreLoopFramePtr, *coreLoopStackPtr, *semanticEnv; 1.18 1.19 SlaveScheduler slaveScheduler; 1.20 RequestHandler requestHandler; 1.21 @@ -68,12 +70,12 @@ 1.22 1.23 //if another reference to same Master VirtProcr still going, busy-wait 1.24 //Could put this lower, but don't want to think about shared stack.. 1.25 - masterEnv = _VMSMasterEnv; 1.26 - while( masterEnv->stillRunning ) /*busy wait*/ ; 1.27 + while( _VMSMasterEnv->stillRunning ) /*busy wait*/ ; 1.28 //TODO: want to do busy-wait as assembly, to be sure stack not touched? 1.29 1.30 //this is the only master running now, set flag again 1.31 - masterEnv->stillRunning = TRUE; 1.32 + _VMSMasterEnv->stillRunning = TRUE; 1.33 + masterEnv = _VMSMasterEnv; 1.34 1.35 //TODO: gdb -- check that a volatile _VMSMasterEnv and _VMSWorkQ means 1.36 // all these will be re-filled every time jump here.. 1.37 @@ -83,12 +85,12 @@ 1.38 schedSlots = masterEnv->schedSlots; 1.39 filledSlots = masterEnv->filledSlots; 1.40 masterPr = masterEnv->masterVirtPr; //post-jmp clobbered, re-load 1.41 - 1.42 + semanticEnv = masterEnv->semanticEnv; 1.43 1.44 //prepare for scheduling 1.45 masterEnv->numFilled = 0; 1.46 1.47 - //Poll each slot's Done flag -- slot 0 reseved for master, start at 1 1.48 + //Poll each slot's Done flag -- slot 0 reserved for master, start at 1 1.49 for( slotIdx = 1; slotIdx < NUM_SCHED_SLOTS; slotIdx++) 1.50 { 1.51 currSlot = schedSlots[ slotIdx ]; 1.52 @@ -99,42 +101,52 @@ 1.53 currSlot->needsProcrAssigned = TRUE; 1.54 1.55 //process requests from slave to master 1.56 - (*requestHandler)( currSlot->procrAssignedToSlot->requests ); 1.57 + (*requestHandler)( currSlot->procrAssignedToSlot, semanticEnv ); 1.58 } 1.59 if( currSlot->needsProcrAssigned ) 1.60 { //give slot a new virt procr 1.61 - retCode = 1.62 - (*slaveScheduler)( currSlot, masterEnv->semanticEnv ); 1.63 + schedVirtPr = 1.64 + (*slaveScheduler)( semanticEnv ); 1.65 1.66 - if( retCode == 1 ) 1.67 - { int numFilled = masterEnv->numFilled; 1.68 + if( schedVirtPr != NULL ) 1.69 + { currSlot->procrAssignedToSlot = schedVirtPr; 1.70 + schedVirtPr->schedSlot = currSlot; 1.71 1.72 - filledSlots[numFilled] = currSlot; 1.73 + filledSlots[ masterEnv->numFilled ] = currSlot; 1.74 masterEnv->numFilled += 1; 1.75 1.76 currSlot->needsProcrAssigned = FALSE; 1.77 } 1.78 - else if( retCode == -1 ) //scheduler plug-in says to shut down VMS 1.79 - { 1.80 - //shutdown -- make "end Thd" virt-procs whose nextInstrPt is the 1.81 - // coreloop's EndCoreLoopPt -- causing a jump to the EndThread 1.82 - // and any other shut-down. 1.83 - } 1.84 } 1.85 } 1.86 1.87 - //put some scheduled slaves in, then continuation, then rest 1.88 - numInFirstChunk = masterEnv->numFilled / 2; //tweak this from experiments 1.89 - for( filledSlotIdx = 0; filledSlotIdx < numInFirstChunk; filledSlotIdx++) 1.90 + //put some scheduled slaves in, then Master continuation, then rest 1.91 + //Adjust position of master such that it maintains close to a fixed 1.92 + // ratio --> make NUM_CORES - 1 slots or fewer come after the master 1.93 + numFilled = masterEnv->numFilled; 1.94 + 1.95 + int numPrecede = numFilled; 1.96 + int numFollow = NUM_CORES - 1; 1.97 + 1.98 + if( numFilled < numFollow ) 1.99 + { numFollow = numFilled; 1.100 + numPrecede = 0; 1.101 + } 1.102 + else 1.103 + { numPrecede -= numFollow; 1.104 + } 1.105 + 1.106 + for( filledSlotIdx = 0; filledSlotIdx < numPrecede; filledSlotIdx++) 1.107 { 1.108 writeCASQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ ); 1.109 } 1.110 1.111 //enqueue continuation of this loop 1.112 // note that After this enqueue, continuation might sneak through 1.113 - writeCASQ( schedSlots[0]->procrAssignedToSlot, workQ );//master always slot 0 1.114 - for( filledSlotIdx = numInFirstChunk; 1.115 - filledSlotIdx < numScheduled; 1.116 + writeCASQ( masterEnv->masterVirtPr, workQ ); 1.117 + 1.118 + for( filledSlotIdx = numPrecede; 1.119 + filledSlotIdx < numFilled; 1.120 filledSlotIdx++) 1.121 { 1.122 writeCASQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ ); 1.123 @@ -142,27 +154,42 @@ 1.124 1.125 masterEnv->numFilled = 0; 1.126 1.127 - //Don't want code above to try to look at requests in masterVirtPr, 1.128 - // so leave workDone at FALSE, but do want it to schedule into 1.129 - // the slot, so set needs procr assigned to TRUE. 1.130 - masterPr->schedSlot->needsProcrAssigned = TRUE; 1.131 1.132 //Save stack ptr and frame -- don't need to, take out later, but safe 1.133 // Also, wait to set stillRunning to FALSE until just before jump, to 1.134 - // protect stack might need to jmp directly to asm busy-wait to be 1.135 - // sure stack not touched 1.136 - //TODO: gdb check that busy-wait doesn't touch stack, so this is safe 1.137 - //don't need any regs to be valid when come back, so clobber list empty 1.138 - //TODO: gdb the jmp -- make sure it jumps through register or mem 1.139 - asm volatile("movl %%esp, %0; \ 1.140 - movl %%ebp, %1; \ 1.141 - movl $0x0, %2; \ 1.142 - jmp %3 " 1.143 - /* outputs */ : "=m" (masterPr->stackPtr), "=m" (masterPr->framePtr), 1.144 - "=m" (masterEnv->stillRunning) 1.145 - /* inputs */ : "r" (masterPr->coreLoopStartPt) 1.146 - /* clobber */ 1.147 - ); 1.148 + // be safe -- although the two simulatneously animated MasterLoops 1.149 + // are on different cores, so have different stacks, so no worries 1.150 + // there. 1.151 + //Restore CoreLoop's stack frame (and stack pointer, to be safe) 1.152 + //TODO: cafefully verify don't need to force saving anything to stack 1.153 + // before jumping back to core loop. 1.154 + stackPtrAddr = &(masterPr->stackPtr); 1.155 + framePtrAddr = &(masterPr->framePtr); 1.156 + stillRunningAddr = &(_VMSMasterEnv->stillRunning); //when race condition 1.157 + //arises, stillRunning is shared between the two cores both animating 1.158 + // MasterLoop -- but those two cores have different esp & ebp, so safe 1.159 + // to change stack and frame pointer here, without one messing up other 1.160 + // one 1.161 + 1.162 + jmpPt = masterPr->coreLoopStartPt; 1.163 + coreLoopFramePtr = masterPr->coreLoopFramePtr;//need this only 1.164 + coreLoopStackPtr = masterPr->coreLoopStackPtr;//shouldn't need -- safety 1.165 + 1.166 + asm volatile("movl %0, %%eax; \ 1.167 + movl %%esp, (%%eax); \ 1.168 + movl %1, %%eax; \ 1.169 + movl %%ebp, (%%eax); \ 1.170 + movl %2, %%ebx; \ 1.171 + movl %3, %%eax; \ 1.172 + movl %4, %%esp; \ 1.173 + movl %5, %%ebp; \ 1.174 + movl $0x0, (%%ebx); \ 1.175 + jmp %%eax " \ 1.176 + /* outputs */ : "=g" (stackPtrAddr), "=g" (framePtrAddr), \ 1.177 + "=g"(stillRunningAddr) \ 1.178 + /* inputs */ : "g" (jmpPt), "g"(coreLoopStackPtr), "g"(coreLoopFramePtr)\ 1.179 + /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" \ 1.180 + );//can probably make clobber list empty -- but safe for now 1.181 } 1.182 1.183
