Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
comparison MasterLoop.c @ 24:2b161e1a50ee
1st working version -- as far as can tell due to SEH bugs
| author | Me |
|---|---|
| date | Wed, 07 Jul 2010 13:15:54 -0700 |
| parents | e2de204909bf |
| children | 668278fa7a63 |
comparison
equal
deleted
inserted
replaced
| 3:1f57dfe9eb12 | 4:a6f548e8b898 |
|---|---|
| 45 *However means have to make masterEnv a global static volatile the same way | 45 *However means have to make masterEnv a global static volatile the same way |
| 46 * did with workQ in core loop. -- for performance, put the | 46 * did with workQ in core loop. -- for performance, put the |
| 47 * jump to the core loop directly in here, and have it directly jump back. | 47 * jump to the core loop directly in here, and have it directly jump back. |
| 48 */ | 48 */ |
| 49 void masterLoop( void *initData, VirtProcr *masterPr ) | 49 void masterLoop( void *initData, VirtProcr *masterPr ) |
| 50 { bool8 retCode; | 50 { |
| 51 int slotIdx, numScheduled, numInFirstChunk, filledSlotIdx; | 51 int slotIdx, numFilled, numInFirstChunk, filledSlotIdx; |
| 52 VirtProcr *schedVirtPr; | |
| 52 SchedSlot *currSlot, **schedSlots, **filledSlots; | 53 SchedSlot *currSlot, **schedSlots, **filledSlots; |
| 53 MasterEnv *masterEnv; | 54 MasterEnv *masterEnv; |
| 54 CASQueueStruc *workQ; | 55 CASQueueStruc *workQ; |
| 55 void *jmpPt; | 56 void *jmpPt, *stackPtrAddr, *framePtrAddr, *stillRunningAddr; |
| 57 void *coreLoopFramePtr, *coreLoopStackPtr, *semanticEnv; | |
| 56 | 58 |
| 57 SlaveScheduler slaveScheduler; | 59 SlaveScheduler slaveScheduler; |
| 58 RequestHandler requestHandler; | 60 RequestHandler requestHandler; |
| 59 | 61 |
| 60 //this will run as the first virt processor in workQ, and will be a | 62 //this will run as the first virt processor in workQ, and will be a |
| 66 | 68 |
| 67 masterLoopStartPt: | 69 masterLoopStartPt: |
| 68 | 70 |
| 69 //if another reference to same Master VirtProcr still going, busy-wait | 71 //if another reference to same Master VirtProcr still going, busy-wait |
| 70 //Could put this lower, but don't want to think about shared stack.. | 72 //Could put this lower, but don't want to think about shared stack.. |
| 71 masterEnv = _VMSMasterEnv; | 73 while( _VMSMasterEnv->stillRunning ) /*busy wait*/ ; |
| 72 while( masterEnv->stillRunning ) /*busy wait*/ ; | |
| 73 //TODO: want to do busy-wait as assembly, to be sure stack not touched? | 74 //TODO: want to do busy-wait as assembly, to be sure stack not touched? |
| 74 | 75 |
| 75 //this is the only master running now, set flag again | 76 //this is the only master running now, set flag again |
| 76 masterEnv->stillRunning = TRUE; | 77 _VMSMasterEnv->stillRunning = TRUE; |
| 78 masterEnv = _VMSMasterEnv; | |
| 77 | 79 |
| 78 //TODO: gdb -- check that a volatile _VMSMasterEnv and _VMSWorkQ means | 80 //TODO: gdb -- check that a volatile _VMSMasterEnv and _VMSWorkQ means |
| 79 // all these will be re-filled every time jump here.. | 81 // all these will be re-filled every time jump here.. |
| 80 workQ = _VMSWorkQ; | 82 workQ = _VMSWorkQ; |
| 81 requestHandler = masterEnv->requestHandler; | 83 requestHandler = masterEnv->requestHandler; |
| 82 slaveScheduler = masterEnv->slaveScheduler; | 84 slaveScheduler = masterEnv->slaveScheduler; |
| 83 schedSlots = masterEnv->schedSlots; | 85 schedSlots = masterEnv->schedSlots; |
| 84 filledSlots = masterEnv->filledSlots; | 86 filledSlots = masterEnv->filledSlots; |
| 85 masterPr = masterEnv->masterVirtPr; //post-jmp clobbered, re-load | 87 masterPr = masterEnv->masterVirtPr; //post-jmp clobbered, re-load |
| 86 | 88 semanticEnv = masterEnv->semanticEnv; |
| 87 | 89 |
| 88 //prepare for scheduling | 90 //prepare for scheduling |
| 89 masterEnv->numFilled = 0; | 91 masterEnv->numFilled = 0; |
| 90 | 92 |
| 91 //Poll each slot's Done flag -- slot 0 reseved for master, start at 1 | 93 //Poll each slot's Done flag -- slot 0 reserved for master, start at 1 |
| 92 for( slotIdx = 1; slotIdx < NUM_SCHED_SLOTS; slotIdx++) | 94 for( slotIdx = 1; slotIdx < NUM_SCHED_SLOTS; slotIdx++) |
| 93 { | 95 { |
| 94 currSlot = schedSlots[ slotIdx ]; | 96 currSlot = schedSlots[ slotIdx ]; |
| 95 | 97 |
| 96 if( currSlot->workIsDone ) | 98 if( currSlot->workIsDone ) |
| 97 { | 99 { |
| 98 currSlot->workIsDone = FALSE; | 100 currSlot->workIsDone = FALSE; |
| 99 currSlot->needsProcrAssigned = TRUE; | 101 currSlot->needsProcrAssigned = TRUE; |
| 100 | 102 |
| 101 //process requests from slave to master | 103 //process requests from slave to master |
| 102 (*requestHandler)( currSlot->procrAssignedToSlot->requests ); | 104 (*requestHandler)( currSlot->procrAssignedToSlot, semanticEnv ); |
| 103 } | 105 } |
| 104 if( currSlot->needsProcrAssigned ) | 106 if( currSlot->needsProcrAssigned ) |
| 105 { //give slot a new virt procr | 107 { //give slot a new virt procr |
| 106 retCode = | 108 schedVirtPr = |
| 107 (*slaveScheduler)( currSlot, masterEnv->semanticEnv ); | 109 (*slaveScheduler)( semanticEnv ); |
| 108 | 110 |
| 109 if( retCode == 1 ) | 111 if( schedVirtPr != NULL ) |
| 110 { int numFilled = masterEnv->numFilled; | 112 { currSlot->procrAssignedToSlot = schedVirtPr; |
| 113 schedVirtPr->schedSlot = currSlot; | |
| 111 | 114 |
| 112 filledSlots[numFilled] = currSlot; | 115 filledSlots[ masterEnv->numFilled ] = currSlot; |
| 113 masterEnv->numFilled += 1; | 116 masterEnv->numFilled += 1; |
| 114 | 117 |
| 115 currSlot->needsProcrAssigned = FALSE; | 118 currSlot->needsProcrAssigned = FALSE; |
| 116 } | 119 } |
| 117 else if( retCode == -1 ) //scheduler plug-in says to shut down VMS | |
| 118 { | |
| 119 //shutdown -- make "end Thd" virt-procs whose nextInstrPt is the | |
| 120 // coreloop's EndCoreLoopPt -- causing a jump to the EndThread | |
| 121 // and any other shut-down. | |
| 122 } | |
| 123 } | 120 } |
| 124 } | 121 } |
| 125 | 122 |
| 126 //put some scheduled slaves in, then continuation, then rest | 123 //put some scheduled slaves in, then Master continuation, then rest |
| 127 numInFirstChunk = masterEnv->numFilled / 2; //tweak this from experiments | 124 //Adjust position of master such that it maintains close to a fixed |
| 128 for( filledSlotIdx = 0; filledSlotIdx < numInFirstChunk; filledSlotIdx++) | 125 // ratio --> make NUM_CORES - 1 slots or fewer come after the master |
| 126 numFilled = masterEnv->numFilled; | |
| 127 | |
| 128 int numPrecede = numFilled; | |
| 129 int numFollow = NUM_CORES - 1; | |
| 130 | |
| 131 if( numFilled < numFollow ) | |
| 132 { numFollow = numFilled; | |
| 133 numPrecede = 0; | |
| 134 } | |
| 135 else | |
| 136 { numPrecede -= numFollow; | |
| 137 } | |
| 138 | |
| 139 for( filledSlotIdx = 0; filledSlotIdx < numPrecede; filledSlotIdx++) | |
| 129 { | 140 { |
| 130 writeCASQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ ); | 141 writeCASQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ ); |
| 131 } | 142 } |
| 132 | 143 |
| 133 //enqueue continuation of this loop | 144 //enqueue continuation of this loop |
| 134 // note that After this enqueue, continuation might sneak through | 145 // note that After this enqueue, continuation might sneak through |
| 135 writeCASQ( schedSlots[0]->procrAssignedToSlot, workQ );//master always slot 0 | 146 writeCASQ( masterEnv->masterVirtPr, workQ ); |
| 136 for( filledSlotIdx = numInFirstChunk; | 147 |
| 137 filledSlotIdx < numScheduled; | 148 for( filledSlotIdx = numPrecede; |
| 149 filledSlotIdx < numFilled; | |
| 138 filledSlotIdx++) | 150 filledSlotIdx++) |
| 139 { | 151 { |
| 140 writeCASQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ ); | 152 writeCASQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ ); |
| 141 } | 153 } |
| 142 | 154 |
| 143 masterEnv->numFilled = 0; | 155 masterEnv->numFilled = 0; |
| 144 | 156 |
| 145 //Don't want code above to try to look at requests in masterVirtPr, | |
| 146 // so leave workDone at FALSE, but do want it to schedule into | |
| 147 // the slot, so set needs procr assigned to TRUE. | |
| 148 masterPr->schedSlot->needsProcrAssigned = TRUE; | |
| 149 | 157 |
| 150 //Save stack ptr and frame -- don't need to, take out later, but safe | 158 //Save stack ptr and frame -- don't need to, take out later, but safe |
| 151 // Also, wait to set stillRunning to FALSE until just before jump, to | 159 // Also, wait to set stillRunning to FALSE until just before jump, to |
| 152 // protect stack might need to jmp directly to asm busy-wait to be | 160 // be safe -- although the two simulatneously animated MasterLoops |
| 153 // sure stack not touched | 161 // are on different cores, so have different stacks, so no worries |
| 154 //TODO: gdb check that busy-wait doesn't touch stack, so this is safe | 162 // there. |
| 155 //don't need any regs to be valid when come back, so clobber list empty | 163 //Restore CoreLoop's stack frame (and stack pointer, to be safe) |
| 156 //TODO: gdb the jmp -- make sure it jumps through register or mem | 164 //TODO: cafefully verify don't need to force saving anything to stack |
| 157 asm volatile("movl %%esp, %0; \ | 165 // before jumping back to core loop. |
| 158 movl %%ebp, %1; \ | 166 stackPtrAddr = &(masterPr->stackPtr); |
| 159 movl $0x0, %2; \ | 167 framePtrAddr = &(masterPr->framePtr); |
| 160 jmp %3 " | 168 stillRunningAddr = &(_VMSMasterEnv->stillRunning); //when race condition |
| 161 /* outputs */ : "=m" (masterPr->stackPtr), "=m" (masterPr->framePtr), | 169 //arises, stillRunning is shared between the two cores both animating |
| 162 "=m" (masterEnv->stillRunning) | 170 // MasterLoop -- but those two cores have different esp & ebp, so safe |
| 163 /* inputs */ : "r" (masterPr->coreLoopStartPt) | 171 // to change stack and frame pointer here, without one messing up other |
| 164 /* clobber */ | 172 // one |
| 165 ); | 173 |
| 174 jmpPt = masterPr->coreLoopStartPt; | |
| 175 coreLoopFramePtr = masterPr->coreLoopFramePtr;//need this only | |
| 176 coreLoopStackPtr = masterPr->coreLoopStackPtr;//shouldn't need -- safety | |
| 177 | |
| 178 asm volatile("movl %0, %%eax; \ | |
| 179 movl %%esp, (%%eax); \ | |
| 180 movl %1, %%eax; \ | |
| 181 movl %%ebp, (%%eax); \ | |
| 182 movl %2, %%ebx; \ | |
| 183 movl %3, %%eax; \ | |
| 184 movl %4, %%esp; \ | |
| 185 movl %5, %%ebp; \ | |
| 186 movl $0x0, (%%ebx); \ | |
| 187 jmp %%eax " \ | |
| 188 /* outputs */ : "=g" (stackPtrAddr), "=g" (framePtrAddr), \ | |
| 189 "=g"(stillRunningAddr) \ | |
| 190 /* inputs */ : "g" (jmpPt), "g"(coreLoopStackPtr), "g"(coreLoopFramePtr)\ | |
| 191 /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" \ | |
| 192 );//can probably make clobber list empty -- but safe for now | |
| 166 } | 193 } |
| 167 | 194 |
| 168 | 195 |
