# HG changeset patch # User Me # Date 1275344682 25200 # Node ID ca61f77ed41722007752f3507a76a1ba7207d69a # Parent 2a6fd371c333c3c144fb6efc86797e626aa07442 Compiles with assembly diff -r 2a6fd371c333 -r ca61f77ed417 MasterLoop.c --- a/MasterLoop.c Mon May 31 15:01:08 2010 -0700 +++ b/MasterLoop.c Mon May 31 15:24:42 2010 -0700 @@ -37,77 +37,129 @@ * */ -void masterLoop( void *data ) +/*May 29, 2010 -- birth a Master during init so that first core loop to + * start running gets it and does all the stuff for a newly born + * from then on, will be doing continuation -- but do suspension self + * directly at end of master loop + *So VMS__init just births the master virtual processor same way it births + * all the others -- then does any extra setup needed and puts it into the + * work queue. + *However means have to make masterEnv a global static volatile the same way + * did with workQ in core loop. -- for performance, put the + * jump to core loop directly in here, and have it directly jump back. + */ +void masterLoop( void *initData, VirtProcr *masterPr ) { bool8 success; - int slaveIdx, numScheduled, numInFirstHalf, schedSlaveIdx; - VMSProcr currSlave, *virtSlaves; + int slotIdx, numScheduled, numInFirstChunk, filledSlotIdx; + SchedSlot *currSlot, **schedSlots, **filledSlots; MasterEnv *masterEnv; + QueueStruc *workQ; +// VirtProcr *masterPr; + void *jmpPt; + SlaveScheduler slaveScheduler; RequestHandler requestHandler; + //this will run as the first virt processor in workQ, and will be a + // new born -- so will do all the GCC-generated allocating space on + // the stack owned by master virt procr -- and will run this last bit + // of setup code.. + masterPr->nextInstrPt = &&masterLoopStartPt; - masterEnv = (MasterEnv *)data; + + masterLoopStartPt: + //if another reference to same Master VirtProcr still going, busy-wait + //Could put this lower, but don't want to think about shared stack.. + while( masterEnv->stillRunning ) /*busy wait*/ ; + //TODO: want to do busy-wait as assembly, to be sure stack not touched? + + //this is the only master running now, set flag again + masterEnv->stillRunning = TRUE; + + //TODO: gdb -- check that a volatile _VMSMasterEnv and _VMSWorkQ means + // all these will be re-filled every time jump here.. + workQ = _VMSWorkQ; + masterEnv = _VMSMasterEnv; requestHandler = masterEnv->requestHandler; slaveScheduler = masterEnv->slaveScheduler; - virtSlaves = masterEnv->virtSlaves; + schedSlots = masterEnv->schedSlots; + filledSlots = masterEnv->filledSlots; + masterPr = masterEnv->masterVirtPr; - //if another continuation of Master still running, busy-wait - while( masterEnv->stillRunning ) /*busy wait*/ ; - - //this is the only master running now, set flag again - masterEnv->stillRunning = 1; //prepare for scheduling - masterEnv->numScheduled = 0; + masterEnv->numFilled = 0; - //Poll each slave structure's Done flag - for( slaveIdx = 0; slaveIdx < NUM_SLAVES; slaveIdx++) + //Poll each slot's Done flag -- slot 0 reseved for master, start at 1 + for( slotIdx = 1; slotIdx < NUM_SCHED_SLOTS; slotIdx++) { - currSlave = virtSlaves[ slaveIdx ]; + currSlot = schedSlots[ slotIdx ]; - if( currSlave->workIsDone ) + if( currSlot->workIsDone ) { - currSlave->workIsDone = FALSE; - currSlave->needsWorkAssigned = TRUE; + currSlot->workIsDone = FALSE; + currSlot->needsProcrAssigned = TRUE; //process requests from slave to master - (*requestHandler)( currSlave ); + (*requestHandler)( currSlot->procrAssignedToSlot->requests ); } - if( currSlave->needsWorkAssigned ) - { //give slave a new work-unit + if( currSlot->needsProcrAssigned ) + { //give slot a new virt procr success = - (*slaveScheduler)( currSlave, masterEnv ); + (*slaveScheduler)( currSlot, masterEnv->semanticEnv ); if( success ) - { addToVect( currSlave, &(masterEnv->scheduledSlaves), - &(masterEnv->numScheduled) ); - currSlave->needsWorkAssigned = FALSE; + { int numFilled = masterEnv->numFilled; + + filledSlots[numFilled] = currSlot; + masterEnv->numFilled += 1; + + currSlot->needsProcrAssigned = FALSE; } } } - //put half scheduled slaves in, then continuation, then other half - VMSProcr **scheduledSlaves; - numInFirstHalf = masterEnv->numScheduled / 2; - scheduledSlaves = masterEnv->scheduledSlaves; - for( schedSlaveIdx = 0; schedSlaveIdx < numInFirstHalf; schedSlaveIdx++) + //put some scheduled slaves in, then continuation, then rest + numInFirstChunk = masterEnv->numFilled / 2; //tweak this from experiments + for( filledSlotIdx = 0; filledSlotIdx < numInFirstChunk; filledSlotIdx++) { - writeQ( scheduledSlaves[ schedSlaveIdx ], workQ ); + writeQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ ); } //enqueue continuation of this loop // note that After this enqueue, continuation might sneak through - writeQ( masterEnv->masterWorkUnit, workQ ); - for( schedSlaveIdx = numInFirstHalf; - schedSlaveIdx < numScheduled; - schedSlaveIdx++) + writeQ( schedSlots[0]->procrAssignedToSlot, workQ );//master always slot 0 + for( filledSlotIdx = numInFirstChunk; + filledSlotIdx < numScheduled; + filledSlotIdx++) { - writeQ( scheduledSlaves[ schedSlaveIdx ]->workUnitToDo, workQ ); + writeQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ ); } - //all done, so okay for continuation to proceed - masterEnv->stillRunning = 0; + masterEnv->numFilled = 0; + + //Don't want code above to try to look at requests in masterVirtPr, + // so leave workDone at FALSE, but do want it to schedule into + // the slot, so set needs procr assigned to TRUE. + masterPr->schedSlot->needsProcrAssigned = TRUE; + + //Save stack ptr and frame -- don't need to, take out later, but safe + // Also, wait to set stillRunning to FALSE until just before jump, to + // protect stack might need to jmp directly to asm busy-wait to be + // sure stack not touched + //TODO: gdb check that busy-wait doesn't touch stack, so this is safe + //don't need any regs to be valid when come back, so clobber list empty + //TODO: gdb the jmp -- make sure it jumps through register or mem + asm volatile("movl %%esp, %0; \ + movl %%ebp, %1; \ + movl $0x0, %2; \ + jmp %3 " + /* outputs */ : "=m" (masterPr->stackPtr), "=m" (masterPr->framePtr), + "=m" (masterEnv->stillRunning) + /* inputs */ : "r" (masterPr->coreLoopStartPt) + /* clobber */ + ); }