Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
diff MasterLoop.c @ 4:ca61f77ed417
Compiles with assembly
| author | Me |
|---|---|
| date | Mon, 31 May 2010 15:24:42 -0700 |
| parents | a5fe730dfc2e |
| children | a87d02855dee |
line diff
1.1 --- a/MasterLoop.c Mon May 31 15:01:08 2010 -0700 1.2 +++ b/MasterLoop.c Mon May 31 15:24:42 2010 -0700 1.3 @@ -37,77 +37,129 @@ 1.4 * 1.5 */ 1.6 1.7 -void masterLoop( void *data ) 1.8 +/*May 29, 2010 -- birth a Master during init so that first core loop to 1.9 + * start running gets it and does all the stuff for a newly born 1.10 + * from then on, will be doing continuation -- but do suspension self 1.11 + * directly at end of master loop 1.12 + *So VMS__init just births the master virtual processor same way it births 1.13 + * all the others -- then does any extra setup needed and puts it into the 1.14 + * work queue. 1.15 + *However means have to make masterEnv a global static volatile the same way 1.16 + * did with workQ in core loop. -- for performance, put the 1.17 + * jump to core loop directly in here, and have it directly jump back. 1.18 + */ 1.19 +void masterLoop( void *initData, VirtProcr *masterPr ) 1.20 { bool8 success; 1.21 - int slaveIdx, numScheduled, numInFirstHalf, schedSlaveIdx; 1.22 - VMSProcr currSlave, *virtSlaves; 1.23 + int slotIdx, numScheduled, numInFirstChunk, filledSlotIdx; 1.24 + SchedSlot *currSlot, **schedSlots, **filledSlots; 1.25 MasterEnv *masterEnv; 1.26 + QueueStruc *workQ; 1.27 +// VirtProcr *masterPr; 1.28 + void *jmpPt; 1.29 + 1.30 SlaveScheduler slaveScheduler; 1.31 RequestHandler requestHandler; 1.32 1.33 + //this will run as the first virt processor in workQ, and will be a 1.34 + // new born -- so will do all the GCC-generated allocating space on 1.35 + // the stack owned by master virt procr -- and will run this last bit 1.36 + // of setup code.. 1.37 + masterPr->nextInstrPt = &&masterLoopStartPt; 1.38 1.39 - masterEnv = (MasterEnv *)data; 1.40 + 1.41 + masterLoopStartPt: 1.42 1.43 + //if another reference to same Master VirtProcr still going, busy-wait 1.44 + //Could put this lower, but don't want to think about shared stack.. 1.45 + while( masterEnv->stillRunning ) /*busy wait*/ ; 1.46 + //TODO: want to do busy-wait as assembly, to be sure stack not touched? 1.47 + 1.48 + //this is the only master running now, set flag again 1.49 + masterEnv->stillRunning = TRUE; 1.50 + 1.51 + //TODO: gdb -- check that a volatile _VMSMasterEnv and _VMSWorkQ means 1.52 + // all these will be re-filled every time jump here.. 1.53 + workQ = _VMSWorkQ; 1.54 + masterEnv = _VMSMasterEnv; 1.55 requestHandler = masterEnv->requestHandler; 1.56 slaveScheduler = masterEnv->slaveScheduler; 1.57 - virtSlaves = masterEnv->virtSlaves; 1.58 + schedSlots = masterEnv->schedSlots; 1.59 + filledSlots = masterEnv->filledSlots; 1.60 + masterPr = masterEnv->masterVirtPr; 1.61 1.62 - //if another continuation of Master still running, busy-wait 1.63 - while( masterEnv->stillRunning ) /*busy wait*/ ; 1.64 - 1.65 - //this is the only master running now, set flag again 1.66 - masterEnv->stillRunning = 1; 1.67 1.68 //prepare for scheduling 1.69 - masterEnv->numScheduled = 0; 1.70 + masterEnv->numFilled = 0; 1.71 1.72 - //Poll each slave structure's Done flag 1.73 - for( slaveIdx = 0; slaveIdx < NUM_SLAVES; slaveIdx++) 1.74 + //Poll each slot's Done flag -- slot 0 reseved for master, start at 1 1.75 + for( slotIdx = 1; slotIdx < NUM_SCHED_SLOTS; slotIdx++) 1.76 { 1.77 - currSlave = virtSlaves[ slaveIdx ]; 1.78 + currSlot = schedSlots[ slotIdx ]; 1.79 1.80 - if( currSlave->workIsDone ) 1.81 + if( currSlot->workIsDone ) 1.82 { 1.83 - currSlave->workIsDone = FALSE; 1.84 - currSlave->needsWorkAssigned = TRUE; 1.85 + currSlot->workIsDone = FALSE; 1.86 + currSlot->needsProcrAssigned = TRUE; 1.87 1.88 //process requests from slave to master 1.89 - (*requestHandler)( currSlave ); 1.90 + (*requestHandler)( currSlot->procrAssignedToSlot->requests ); 1.91 } 1.92 - if( currSlave->needsWorkAssigned ) 1.93 - { //give slave a new work-unit 1.94 + if( currSlot->needsProcrAssigned ) 1.95 + { //give slot a new virt procr 1.96 success = 1.97 - (*slaveScheduler)( currSlave, masterEnv ); 1.98 + (*slaveScheduler)( currSlot, masterEnv->semanticEnv ); 1.99 1.100 if( success ) 1.101 - { addToVect( currSlave, &(masterEnv->scheduledSlaves), 1.102 - &(masterEnv->numScheduled) ); 1.103 - currSlave->needsWorkAssigned = FALSE; 1.104 + { int numFilled = masterEnv->numFilled; 1.105 + 1.106 + filledSlots[numFilled] = currSlot; 1.107 + masterEnv->numFilled += 1; 1.108 + 1.109 + currSlot->needsProcrAssigned = FALSE; 1.110 } 1.111 } 1.112 } 1.113 1.114 - //put half scheduled slaves in, then continuation, then other half 1.115 - VMSProcr **scheduledSlaves; 1.116 - numInFirstHalf = masterEnv->numScheduled / 2; 1.117 - scheduledSlaves = masterEnv->scheduledSlaves; 1.118 - for( schedSlaveIdx = 0; schedSlaveIdx < numInFirstHalf; schedSlaveIdx++) 1.119 + //put some scheduled slaves in, then continuation, then rest 1.120 + numInFirstChunk = masterEnv->numFilled / 2; //tweak this from experiments 1.121 + for( filledSlotIdx = 0; filledSlotIdx < numInFirstChunk; filledSlotIdx++) 1.122 { 1.123 - writeQ( scheduledSlaves[ schedSlaveIdx ], workQ ); 1.124 + writeQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ ); 1.125 } 1.126 1.127 //enqueue continuation of this loop 1.128 // note that After this enqueue, continuation might sneak through 1.129 - writeQ( masterEnv->masterWorkUnit, workQ ); 1.130 - for( schedSlaveIdx = numInFirstHalf; 1.131 - schedSlaveIdx < numScheduled; 1.132 - schedSlaveIdx++) 1.133 + writeQ( schedSlots[0]->procrAssignedToSlot, workQ );//master always slot 0 1.134 + for( filledSlotIdx = numInFirstChunk; 1.135 + filledSlotIdx < numScheduled; 1.136 + filledSlotIdx++) 1.137 { 1.138 - writeQ( scheduledSlaves[ schedSlaveIdx ]->workUnitToDo, workQ ); 1.139 + writeQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ ); 1.140 } 1.141 1.142 - //all done, so okay for continuation to proceed 1.143 - masterEnv->stillRunning = 0; 1.144 + masterEnv->numFilled = 0; 1.145 + 1.146 + //Don't want code above to try to look at requests in masterVirtPr, 1.147 + // so leave workDone at FALSE, but do want it to schedule into 1.148 + // the slot, so set needs procr assigned to TRUE. 1.149 + masterPr->schedSlot->needsProcrAssigned = TRUE; 1.150 + 1.151 + //Save stack ptr and frame -- don't need to, take out later, but safe 1.152 + // Also, wait to set stillRunning to FALSE until just before jump, to 1.153 + // protect stack might need to jmp directly to asm busy-wait to be 1.154 + // sure stack not touched 1.155 + //TODO: gdb check that busy-wait doesn't touch stack, so this is safe 1.156 + //don't need any regs to be valid when come back, so clobber list empty 1.157 + //TODO: gdb the jmp -- make sure it jumps through register or mem 1.158 + asm volatile("movl %%esp, %0; \ 1.159 + movl %%ebp, %1; \ 1.160 + movl $0x0, %2; \ 1.161 + jmp %3 " 1.162 + /* outputs */ : "=m" (masterPr->stackPtr), "=m" (masterPr->framePtr), 1.163 + "=m" (masterEnv->stillRunning) 1.164 + /* inputs */ : "r" (masterPr->coreLoopStartPt) 1.165 + /* clobber */ 1.166 + ); 1.167 } 1.168 1.169
