# HG changeset patch # User Me # Date 1277928634 25200 # Node ID a0af8d4fca35e601b790bfea4678b3bffdb492bd # Parent 09e0029ee0c9568e9963144949ce3b335ddc3948 Full VMS test -- works diff -r 09e0029ee0c9 -r a0af8d4fca35 MasterLoop.c --- a/MasterLoop.c Wed Jun 30 13:10:26 2010 -0700 +++ b/MasterLoop.c Wed Jun 30 13:10:34 2010 -0700 @@ -47,12 +47,14 @@ * jump to the core loop directly in here, and have it directly jump back. */ void masterLoop( void *initData, VirtProcr *masterPr ) - { bool8 retCode; - int slotIdx, numScheduled, numInFirstChunk, filledSlotIdx; + { + int slotIdx, numFilled, numInFirstChunk, filledSlotIdx; + VirtProcr *schedVirtPr; SchedSlot *currSlot, **schedSlots, **filledSlots; MasterEnv *masterEnv; CASQueueStruc *workQ; - void *jmpPt; + void *jmpPt, *stackPtrAddr, *framePtrAddr, *stillRunningAddr; + void *coreLoopFramePtr, *coreLoopStackPtr, *semanticEnv; SlaveScheduler slaveScheduler; RequestHandler requestHandler; @@ -68,12 +70,12 @@ //if another reference to same Master VirtProcr still going, busy-wait //Could put this lower, but don't want to think about shared stack.. - masterEnv = _VMSMasterEnv; - while( masterEnv->stillRunning ) /*busy wait*/ ; + while( _VMSMasterEnv->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; + _VMSMasterEnv->stillRunning = TRUE; + masterEnv = _VMSMasterEnv; //TODO: gdb -- check that a volatile _VMSMasterEnv and _VMSWorkQ means // all these will be re-filled every time jump here.. @@ -83,12 +85,12 @@ schedSlots = masterEnv->schedSlots; filledSlots = masterEnv->filledSlots; masterPr = masterEnv->masterVirtPr; //post-jmp clobbered, re-load - + semanticEnv = masterEnv->semanticEnv; //prepare for scheduling masterEnv->numFilled = 0; - //Poll each slot's Done flag -- slot 0 reseved for master, start at 1 + //Poll each slot's Done flag -- slot 0 reserved for master, start at 1 for( slotIdx = 1; slotIdx < NUM_SCHED_SLOTS; slotIdx++) { currSlot = schedSlots[ slotIdx ]; @@ -99,42 +101,52 @@ currSlot->needsProcrAssigned = TRUE; //process requests from slave to master - (*requestHandler)( currSlot->procrAssignedToSlot->requests ); + (*requestHandler)( currSlot->procrAssignedToSlot, semanticEnv ); } if( currSlot->needsProcrAssigned ) { //give slot a new virt procr - retCode = - (*slaveScheduler)( currSlot, masterEnv->semanticEnv ); + schedVirtPr = + (*slaveScheduler)( semanticEnv ); - if( retCode == 1 ) - { int numFilled = masterEnv->numFilled; + if( schedVirtPr != NULL ) + { currSlot->procrAssignedToSlot = schedVirtPr; + schedVirtPr->schedSlot = currSlot; - filledSlots[numFilled] = currSlot; + filledSlots[ masterEnv->numFilled ] = currSlot; masterEnv->numFilled += 1; currSlot->needsProcrAssigned = FALSE; } - else if( retCode == -1 ) //scheduler plug-in says to shut down VMS - { - //shutdown -- make "end Thd" virt-procs whose nextInstrPt is the - // coreloop's EndCoreLoopPt -- causing a jump to the EndThread - // and any other shut-down. - } } } - //put some scheduled slaves in, then continuation, then rest - numInFirstChunk = masterEnv->numFilled / 2; //tweak this from experiments - for( filledSlotIdx = 0; filledSlotIdx < numInFirstChunk; filledSlotIdx++) + //put some scheduled slaves in, then Master continuation, then rest + //Adjust position of master such that it maintains close to a fixed + // ratio --> make NUM_CORES - 1 slots or fewer come after the master + numFilled = masterEnv->numFilled; + + int numPrecede = numFilled; + int numFollow = NUM_CORES - 1; + + if( numFilled < numFollow ) + { numFollow = numFilled; + numPrecede = 0; + } + else + { numPrecede -= numFollow; + } + + for( filledSlotIdx = 0; filledSlotIdx < numPrecede; filledSlotIdx++) { writeCASQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ ); } //enqueue continuation of this loop // note that After this enqueue, continuation might sneak through - writeCASQ( schedSlots[0]->procrAssignedToSlot, workQ );//master always slot 0 - for( filledSlotIdx = numInFirstChunk; - filledSlotIdx < numScheduled; + writeCASQ( masterEnv->masterVirtPr, workQ ); + + for( filledSlotIdx = numPrecede; + filledSlotIdx < numFilled; filledSlotIdx++) { writeCASQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ ); @@ -142,27 +154,42 @@ 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 */ - ); + // be safe -- although the two simulatneously animated MasterLoops + // are on different cores, so have different stacks, so no worries + // there. + //Restore CoreLoop's stack frame (and stack pointer, to be safe) + //TODO: cafefully verify don't need to force saving anything to stack + // before jumping back to core loop. + stackPtrAddr = &(masterPr->stackPtr); + framePtrAddr = &(masterPr->framePtr); + stillRunningAddr = &(_VMSMasterEnv->stillRunning); //when race condition + //arises, stillRunning is shared between the two cores both animating + // MasterLoop -- but those two cores have different esp & ebp, so safe + // to change stack and frame pointer here, without one messing up other + // one + + jmpPt = masterPr->coreLoopStartPt; + coreLoopFramePtr = masterPr->coreLoopFramePtr;//need this only + coreLoopStackPtr = masterPr->coreLoopStackPtr;//shouldn't need -- safety + + asm volatile("movl %0, %%eax; \ + movl %%esp, (%%eax); \ + movl %1, %%eax; \ + movl %%ebp, (%%eax); \ + movl %2, %%ebx; \ + movl %3, %%eax; \ + movl %4, %%esp; \ + movl %5, %%ebp; \ + movl $0x0, (%%ebx); \ + jmp %%eax " \ + /* outputs */ : "=g" (stackPtrAddr), "=g" (framePtrAddr), \ + "=g"(stillRunningAddr) \ + /* inputs */ : "g" (jmpPt), "g"(coreLoopStackPtr), "g"(coreLoopFramePtr)\ + /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" \ + );//can probably make clobber list empty -- but safe for now }