Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
changeset 31:e69579a0e797 Pin2Core
Works multi-core.. pinned VP to a core loop
| author | Me |
|---|---|
| date | Wed, 01 Sep 2010 08:23:39 -0700 |
| parents | c8823e0bb2b4 |
| children | 609c7222e4a6 17d20e5cf924 |
| files | CoreLoop.c MasterLoop.c VMS.c VMS.h |
| diffstat | 4 files changed, 236 insertions(+), 191 deletions(-) [+] |
line diff
1.1 --- a/CoreLoop.c Mon Aug 09 02:24:31 2010 -0700 1.2 +++ b/CoreLoop.c Wed Sep 01 08:23:39 2010 -0700 1.3 @@ -30,14 +30,16 @@ 1.4 */ 1.5 void * 1.6 coreLoop( void *paramsIn ) 1.7 - { 1.8 + { 1.9 ThdParams *coreLoopThdParams; 1.10 + int thisCoresIdx; 1.11 VirtProcr *currPr; 1.12 - VMSQueueStruc *workQ; 1.13 + SRSWQueueStruc *readyToAnimateQ; 1.14 unsigned long coreMask; //has 1 in bit positions of allowed cores 1.15 int errorCode; 1.16 1.17 coreLoopThdParams = (ThdParams *)paramsIn; 1.18 + thisCoresIdx = coreLoopThdParams->coreNum; 1.19 1.20 //wait until signalled that setup is complete 1.21 pthread_mutex_lock( &suspendLock ); 1.22 @@ -66,26 +68,57 @@ 1.23 //To get label addr in non-gcc compiler, can trick it by making a call 1.24 // to a fn that does asm that pulls the "return" 1.25 // addr off the stack and stores it in a pointed-to location. 1.26 - _VMSMasterEnv->coreLoopEndPt = &&CoreLoopEndPt; 1.27 + _VMSMasterEnv->coreLoopEndPt = &&CoreLoopEndPt; 1.28 + _VMSMasterEnv->coreLoopStartPt = &&CoreLoopStartPt; 1.29 1.30 - //Core loop has no values live upon CoreLoopStartPt except workQ 1.31 + //Core loop has no values live upon CoreLoopStartPt except 1.32 + // _VMSMasterEnv 1.33 // every value in the code is defined by a statement in core loop, 1.34 - // after the start point -- with the one exception of _VMSWorkQ 1.35 + // after the start point -- with the one exception of _VMSMasterEnv 1.36 1.37 1.38 // Get to work! -- virt procr jumps back here when suspends 1.39 //Note, have to restore the frame-pointer before jump to here, to get 1.40 - // this code to work right (workQ and so forth are frame-ptr relative) 1.41 + // this code to work right (readyToAnimateQ and so forth are frame-ptr relative) 1.42 CoreLoopStartPt: 1.43 1.44 //Get virtual processor from queue 1.45 //_VMSWorkQ must be a global, static volatile var, so not kept in reg, 1.46 // which forces reloading the pointer after each jmp to this point 1.47 - workQ = _VMSWorkQ; 1.48 - currPr = (VirtProcr *) readVMSQ( workQ ); 1.49 + readyToAnimateQ = _VMSMasterEnv->readyToAnimateQs[thisCoresIdx]; 1.50 1.51 - currPr->coreLoopStartPt = &&CoreLoopStartPt; //to be sure -- chg for perf 1.52 - currPr->coreAnimatedBy = coreLoopThdParams->coreNum; 1.53 + currPr = (VirtProcr *) readSRSWQ_NonBlocking( readyToAnimateQ ); 1.54 + int tries = 0; int gotLock = 0; 1.55 + while( currPr == NULL ) 1.56 + { //no VPs ready to animate, so run MasterVP --later make "try Master" 1.57 + // VPs & put one in every queue at strategic point -- so have work 1.58 + // avail if don't get lock & short-circuit out of it if master has 1.59 + // recently run on another core 1.60 + //TODO: perf -- "try Master" VP that checks if should run Master Fn 1.61 + //But just letting queue run empty is quickest to see if pinning VP 1.62 + // to core will solve the bizarre random seg-faults in system stack. 1.63 + 1.64 + //check if get the MasterLock 1.65 + gotLock = __sync_bool_compare_and_swap( &(_VMSMasterEnv->masterLock), \ 1.66 + UNLOCKED, LOCKED ); 1.67 + 1.68 + if( gotLock ) 1.69 + { 1.70 + //run own MasterVP -- when its done, unlocks MasterLock and 1.71 + // jumps back to coreLoops's startPt 1.72 + currPr = _VMSMasterEnv->masterVPs[thisCoresIdx]; 1.73 + break; //end while -- have a VP to animate now 1.74 + } 1.75 + //Aug 24, 2010 -- changed so each core loop only gets work scheduled 1.76 + // by its own master, so now stay in loop until get lock 1.77 +// currPr = (VirtProcr *) readSRSWQ_NonBlocking( readyToAnimateQ ); 1.78 + 1.79 + tries++; 1.80 +// if( tries % 10000 == 0 ) printf("empty tries: %d\n", tries/10000 ); 1.81 + if( tries % READYTOANIMATE_RETRIES == 0 ) pthread_yield(); 1.82 + } 1.83 + 1.84 +// currPr->coreAnimatedBy = coreLoopThdParams->coreNum; 1.85 1.86 //switch to virt procr's stack and frame ptr then jump to virt procr fn 1.87 void *stackPtr, *framePtr, *jmpPt, *coreLoopFramePtrAddr, \ 1.88 @@ -139,36 +172,44 @@ 1.89 coreLoop_Seq( void *paramsIn ) 1.90 { 1.91 VirtProcr *currPr; 1.92 - VMSQueueStruc *workQ; 1.93 + SRSWQueueStruc *readyToAnimateQ; 1.94 + 1.95 + ThdParams *coreLoopThdParams; 1.96 + int thisCoresIdx; 1.97 + 1.98 + coreLoopThdParams = (ThdParams *)paramsIn; 1.99 +// thisCoresIdx = coreLoopThdParams->coreNum; 1.100 + thisCoresIdx = 0; 1.101 1.102 1.103 //Save addr of "end core loop" label - jump to it to shut down coreloop 1.104 //To get label addr in non-gcc compiler, can trick it by making a call 1.105 // to a fn that does asm that pulls the "return" 1.106 // addr off the stack and stores it in a pointed-to location. 1.107 - _VMSMasterEnv->coreLoopEndPt = &&CoreLoopEndPt; 1.108 + _VMSMasterEnv->coreLoopStartPt = &&SeqCoreLoopStartPt; 1.109 + _VMSMasterEnv->coreLoopEndPt = &&SeqCoreLoopEndPt; 1.110 1.111 - //Core loop has no values live upon CoreLoopStartPt except workQ 1.112 + //Core loop has no values live upon CoreLoopStartPt except readyToAnimateQ 1.113 // every value in the code is defined by a statement in core loop, 1.114 // after the start point -- with the one exception of _VMSWorkQ 1.115 1.116 1.117 // Get to work! -- virt procr jumps back here when done or suspends 1.118 //Note, have to restore the frame-pointer before jump to here, to get 1.119 - // this code to work right (workQ and so forth are frame-ptr relative) 1.120 -CoreLoopStartPt: 1.121 + // this code to work right (readyToAnimateQ and so forth are frame-ptr relative) 1.122 +SeqCoreLoopStartPt: 1.123 1.124 //Get virtual processor from queue 1.125 //_VMSWorkQ must be a global, static volatile var, so not kept in reg, 1.126 // which forces reloading the pointer after each jmp to this point 1.127 - workQ = _VMSWorkQ; 1.128 - currPr = (VirtProcr *) readVMSQ( workQ ); 1.129 + readyToAnimateQ = _VMSMasterEnv->readyToAnimateQs[thisCoresIdx]; 1.130 + currPr = (VirtProcr *) readSRSWQ_NonBlocking( readyToAnimateQ ); 1.131 + if( currPr == NULL ) 1.132 + currPr = _VMSMasterEnv->masterVPs[thisCoresIdx]; 1.133 + 1.134 1.135 // printf("core %d loop procr addr: %d\n", coreLoopThdParams->coreNum, \ 1.136 // (int)currPr ); fflush(stdin); 1.137 - currPr->coreLoopStartPt = &&CoreLoopStartPt; //to be sure.(GCC specific) 1.138 - 1.139 -// currPr->coreAnimatedBy = coreLoopThdParams->coreNum; 1.140 1.141 //switch to virt procr's stack and frame ptr then jump to virt procr 1.142 void *stackPtr, *framePtr, *jmpPt, *coreLoopFramePtrAddr, \ 1.143 @@ -210,7 +251,7 @@ 1.144 // to exit, and so the entry point function, which has been waiting for 1.145 // all the threads to die will proceed, gather the result, and 1.146 // return to the calling application. 1.147 - CoreLoopEndPt: 1.148 +SeqCoreLoopEndPt: 1.149 VMS__handle_dissipate_reqst( currPr ); //free shutdown pr, that jmpd here 1.150 return; 1.151 }
2.1 --- a/MasterLoop.c Mon Aug 09 02:24:31 2010 -0700 2.2 +++ b/MasterLoop.c Wed Sep 01 08:23:39 2010 -0700 2.3 @@ -42,74 +42,77 @@ 2.4 * all the others -- then does any extra setup needed and puts it into the 2.5 * work queue. 2.6 *However means have to make masterEnv a global static volatile the same way 2.7 - * did with workQ in core loop. -- for performance, put the 2.8 + * did with readyToAnimateQ in core loop. -- for performance, put the 2.9 * jump to the core loop directly in here, and have it directly jump back. 2.10 + * 2.11 + * 2.12 + *Aug 18, 2010 -- Going to a separate MasterVP for each core, to see if this 2.13 + * avoids the suspected bug in the system stack that causes bizarre faults 2.14 + * at random places in the system code. 2.15 + * 2.16 + *So, this function is coupled to each of the MasterVPs, -- meaning this 2.17 + * function can't rely on a particular stack and frame -- each MasterVP that 2.18 + * animates this function has a different one. 2.19 + * 2.20 + *At this point, the masterLoop does not write itself into the queue anymore, 2.21 + * instead, the coreLoop acquires the masterLock when it has nothing to 2.22 + * animate, and then animates its own masterLoop. However, still try to put 2.23 + * several AppVPs into the queue to amortize the startup cost of switching 2.24 + * to the MasterVP. Note, don't have to worry about latency of requests much 2.25 + * because most requests generate work for same core -- only latency issue 2.26 + * is case when other cores starved and one core's requests generate work 2.27 + * for them -- so keep max in queue to 3 or 4.. 2.28 */ 2.29 -void masterLoop( void *initData, VirtProcr *masterPr ) 2.30 +void masterLoop( void *initData, VirtProcr *animatingPr ) 2.31 { 2.32 - int slotIdx, numFilled, filledSlotIdx, masterHasBeenQueued; 2.33 + int slotIdx; 2.34 VirtProcr *schedVirtPr; 2.35 - SchedSlot *currSlot, **schedSlots, **filledSlots; 2.36 + SchedSlot *currSlot, **schedSlots; 2.37 MasterEnv *masterEnv; 2.38 - VMSQueueStruc *workQ; 2.39 - void *jmpPt, *stackPtrAddr, *framePtrAddr, *stillRunningAddr; 2.40 - void *coreLoopFramePtr, *coreLoopStackPtr, *semanticEnv; 2.41 + VMSQueueStruc *readyToAnimateQ; 2.42 2.43 SlaveScheduler slaveScheduler; 2.44 RequestHandler requestHandler; 2.45 + void *semanticEnv; 2.46 2.47 - //this will run as the first virt processor in workQ, and will be a 2.48 - // new born -- so will do all the GCC-generated allocating space on 2.49 - // the stack owned by master virt procr -- and will run this last bit 2.50 - // of setup code.. 2.51 + int thisCoresIdx; 2.52 + VirtProcr *masterPr; 2.53 + volatile VirtProcr *volatileMasterPr; 2.54 + 2.55 + volatileMasterPr = animatingPr; 2.56 + masterPr = volatileMasterPr; //used to force re-define after jmp 2.57 + 2.58 + //First animation of each MasterVP will in turn animate this part 2.59 + // of setup code.. (VP creator sets up the stack as if this function 2.60 + // was called normally, but actually get here by jmp) 2.61 + //So, setup values about stack ptr, jmp pt and all that 2.62 masterPr->nextInstrPt = &&masterLoopStartPt; 2.63 2.64 - //The second time MasterVP comes out of queue, the first animation of 2.65 - // it hasn't written the stackPtr and framePtr yet -- but the second 2.66 - // animation has already had its stackPtr and framePtr set to the old 2.67 - // value by the coreLoop. Fix this by writing the correct stack and 2.68 - // frame pointers here, at which point they're correct in the first 2.69 - // animation of MasterVP. 2.70 - //TODO: remove writing stackPtr and framePtr at the bottom, for eff 2.71 - stackPtrAddr = &(masterPr->stackPtr); 2.72 - framePtrAddr = &(masterPr->framePtr); 2.73 2.74 - asm volatile("movl %0, %%eax; \ 2.75 - movl %%esp, (%%eax); \ 2.76 - movl %1, %%eax; \ 2.77 - movl %%ebp, (%%eax); " 2.78 - /* outputs */ : "=g" (stackPtrAddr), "=g" (framePtrAddr) \ 2.79 - /* inputs */ : \ 2.80 - /* clobber */ : "memory", "%eax", "%ebx" \ 2.81 - ); 2.82 + //Note, got rid of writing the stack and frame ptr up here, because 2.83 + // only one 2.84 + // core can ever animate a given MasterVP, so don't need to communicate 2.85 + // new frame and stack ptr to the MasterVP storage before a second 2.86 + // version of that MasterVP can get animated on a different core. 2.87 + //Also got rid of the busy-wait. 2.88 2.89 - 2.90 + 2.91 masterLoopStartPt: 2.92 2.93 - //if another reference to same Master VirtProcr still going, busy-wait 2.94 - //Could put this lower, but don't want to think about shared stack.. 2.95 - while( _VMSMasterEnv->stillRunning ) /*busy wait*/ ; 2.96 - //TODO: want to do busy-wait as assembly, to be sure stack not touched? 2.97 + masterEnv = _VMSMasterEnv; 2.98 2.99 - //this is the only master running now, set flag again 2.100 - _VMSMasterEnv->stillRunning = TRUE; 2.101 - masterEnv = _VMSMasterEnv; 2.102 +//TODO: check that compiles so that always re-define from frame-storage 2.103 + masterPr = volatileMasterPr; //just to make sure after jmp 2.104 + thisCoresIdx = masterPr->coreAnimatedBy; 2.105 + readyToAnimateQ = masterEnv->readyToAnimateQs[thisCoresIdx]; 2.106 + schedSlots = masterEnv->allSchedSlots[thisCoresIdx]; 2.107 2.108 - //TODO: gdb -- check that a volatile _VMSMasterEnv and _VMSWorkQ means 2.109 - // all these will be re-filled every time jump here.. 2.110 - workQ = _VMSWorkQ; 2.111 requestHandler = masterEnv->requestHandler; 2.112 slaveScheduler = masterEnv->slaveScheduler; 2.113 - schedSlots = masterEnv->schedSlots; 2.114 - filledSlots = masterEnv->filledSlots; 2.115 - masterPr = masterEnv->masterVirtPr; //post-jmp clobbered, re-load 2.116 semanticEnv = masterEnv->semanticEnv; 2.117 2.118 - //prepare for scheduling 2.119 - numFilled = 0; 2.120 - masterHasBeenQueued = FALSE; 2.121 2.122 - //Poll each slot's Done flag -- slot 0 reserved for master, start at 1 2.123 + //Poll each slot's Done flag 2.124 for( slotIdx = 0; slotIdx < NUM_SCHED_SLOTS; slotIdx++) 2.125 { 2.126 currSlot = schedSlots[ slotIdx ]; 2.127 @@ -125,63 +128,31 @@ 2.128 if( currSlot->needsProcrAssigned ) 2.129 { //give slot a new virt procr 2.130 schedVirtPr = 2.131 - (*slaveScheduler)( semanticEnv ); 2.132 + (*slaveScheduler)( semanticEnv, thisCoresIdx ); 2.133 2.134 if( schedVirtPr != NULL ) 2.135 { currSlot->procrAssignedToSlot = schedVirtPr; 2.136 schedVirtPr->schedSlot = currSlot; 2.137 currSlot->needsProcrAssigned = FALSE; 2.138 2.139 - filledSlots[ numFilled ] = currSlot; 2.140 - 2.141 - writeVMSQ( schedVirtPr, workQ ); 2.142 - numFilled += 1; 2.143 - 2.144 - if( numFilled == masterEnv->numToPrecede ) 2.145 - { 2.146 - writeVMSQ( masterEnv->masterVirtPr, workQ ); 2.147 - masterHasBeenQueued = TRUE; 2.148 - } 2.149 - 2.150 + writeSRSWQ( schedVirtPr, readyToAnimateQ ); 2.151 } 2.152 } 2.153 } 2.154 2.155 - if( !masterHasBeenQueued ) 2.156 - { 2.157 - writeVMSQ( masterEnv->masterVirtPr, workQ ); 2.158 - } 2.159 2.160 - //Adjust the number to precede, for next round -- assume rate of 2.161 - // finishing work is stable -- which is a bad assumption! But, just 2.162 - // want something working for the moment, look at dynamic behavior 2.163 - // later 2.164 -//TODO: look at dynamic behavior -- time-average numToPrecede or something 2.165 - if( numFilled < NUM_CORES - 1 ) 2.166 - { 2.167 - masterEnv->numToPrecede = 1; 2.168 - } 2.169 - else 2.170 - { masterEnv->numToPrecede = numFilled - NUM_CORES + 1; 2.171 - } 2.172 - 2.173 - //Save stack ptr and frame -- don't need to, take out later, but safe 2.174 - // Also, wait to set stillRunning to FALSE until just before jump, to 2.175 - // be safe -- although the two simulatneously animated MasterLoops 2.176 - // are on different cores, so have different stacks, so no worries 2.177 - // there. 2.178 - //Restore CoreLoop's stack frame (and stack pointer, to be safe) 2.179 + //Save stack ptr and frame, restore CoreLoop's stack and frame, 2.180 + // and clear the MasterLock 2.181 //TODO: cafefully verify don't need to force saving anything to stack 2.182 // before jumping back to core loop. 2.183 + void *stackPtrAddr, *framePtrAddr, *masterLockAddr; 2.184 + void *jmpPt, *coreLoopFramePtr, *coreLoopStackPtr; 2.185 + 2.186 stackPtrAddr = &(masterPr->stackPtr); 2.187 framePtrAddr = &(masterPr->framePtr); 2.188 - stillRunningAddr = &(_VMSMasterEnv->stillRunning); //when race condition 2.189 - //arises, stillRunning is shared between the two cores both animating 2.190 - // MasterLoop -- but those two cores have different esp & ebp, so safe 2.191 - // to change stack and frame pointer here, without one messing up other 2.192 - // one 2.193 + masterLockAddr = &(_VMSMasterEnv->masterLock); 2.194 2.195 - jmpPt = masterPr->coreLoopStartPt; 2.196 + jmpPt = _VMSMasterEnv->coreLoopStartPt; 2.197 coreLoopFramePtr = masterPr->coreLoopFramePtr;//need this only 2.198 coreLoopStackPtr = masterPr->coreLoopStackPtr;//shouldn't need -- safety 2.199 2.200 @@ -196,7 +167,7 @@ 2.201 movl $0x0, (%%ebx); \ 2.202 jmp %%eax;" \ 2.203 /* outputs */ : "=g" (stackPtrAddr), "=g" (framePtrAddr), \ 2.204 - "=g"(stillRunningAddr) \ 2.205 + "=g"(masterLockAddr) \ 2.206 /* inputs */ : "g" (jmpPt), "g"(coreLoopStackPtr), "g"(coreLoopFramePtr)\ 2.207 /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" \ 2.208 );//can probably make clobber list empty -- but safe for now
3.1 --- a/VMS.c Mon Aug 09 02:24:31 2010 -0700 3.2 +++ b/VMS.c Wed Sep 01 08:23:39 2010 -0700 3.3 @@ -18,8 +18,8 @@ 3.4 void 3.5 shutdownFn( void *dummy, VirtProcr *dummy2 ); 3.6 3.7 -void 3.8 -create_sched_slots( MasterEnv *masterEnv ); 3.9 +SchedSlot ** 3.10 +create_sched_slots(); 3.11 3.12 void 3.13 create_masterEnv(); 3.14 @@ -48,7 +48,7 @@ 3.15 * initial virt procrs, ready to schedule them to slots when the masterLoop 3.16 * asks. Without this pattern, the semantic layer's setup would 3.17 * have to modify slots directly to assign the initial virt-procrs, and put 3.18 - * them into the workQ itself, breaking the isolation completely. 3.19 + * them into the readyToAnimateQ itself, breaking the isolation completely. 3.20 * 3.21 * 3.22 *The semantic layer creates the initial virt procr(s), and adds its 3.23 @@ -77,29 +77,45 @@ 3.24 3.25 void 3.26 create_masterEnv() 3.27 - { MasterEnv *masterEnv; 3.28 - VMSQueueStruc *workQ; 3.29 - 3.30 - //Make the central work-queue 3.31 - _VMSWorkQ = makeVMSQ(); 3.32 - workQ = _VMSWorkQ; 3.33 - 3.34 + { MasterEnv *masterEnv; 3.35 + SRSWQueueStruc **readyToAnimateQs; 3.36 + int coreIdx; 3.37 + VirtProcr **masterVPs; 3.38 + SchedSlot ***allSchedSlots; //ptr to array of ptrs 3.39 + 3.40 + //Make the master env, which holds everything else 3.41 _VMSMasterEnv = malloc( sizeof(MasterEnv) ); 3.42 masterEnv = _VMSMasterEnv; 3.43 + //Need to set start pt here 'cause used by seed procr, which is created 3.44 + // before the first core loop starts up. -- not sure how yet.. 3.45 +// masterEnv->coreLoopStartPt = ; 3.46 +// masterEnv->coreLoopEndPt = ; 3.47 + 3.48 + //Make a readyToAnimateQ for each core loop 3.49 + readyToAnimateQs = malloc( NUM_CORES * sizeof(SRSWQueueStruc *) ); 3.50 + masterVPs = malloc( NUM_CORES * sizeof(VirtProcr *) ); 3.51 3.52 - //create the master virtual processor 3.53 - masterEnv->masterVirtPr = VMS__create_procr( &masterLoop, masterEnv ); 3.54 + //One array for each core, 3 in array, core's masterVP scheds all 3.55 + allSchedSlots = malloc( NUM_CORES * sizeof(SchedSlot *) ); 3.56 3.57 - create_sched_slots( masterEnv ); 3.58 + for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 3.59 + { 3.60 + readyToAnimateQs[ coreIdx ] = makeSRSWQ(); 3.61 + 3.62 + //Q: should give masterVP core-specific into as its init data? 3.63 + masterVPs[ coreIdx ] = VMS__create_procr( &masterLoop, masterEnv ); 3.64 + masterVPs[ coreIdx ]->coreAnimatedBy = coreIdx; 3.65 + allSchedSlots[ coreIdx ] = create_sched_slots(); //makes for one core 3.66 + } 3.67 + _VMSMasterEnv->readyToAnimateQs = readyToAnimateQs; 3.68 + _VMSMasterEnv->masterVPs = masterVPs; 3.69 + _VMSMasterEnv->allSchedSlots = allSchedSlots; 3.70 3.71 - masterEnv->stillRunning = FALSE; 3.72 - masterEnv->numToPrecede = NUM_CORES; 3.73 3.74 - //First core loop to start up gets this, which will schedule seed Pr 3.75 - //TODO: debug: check address of masterVirtPr 3.76 - writeVMSQ( masterEnv->masterVirtPr, workQ ); 3.77 3.78 - numProcrsCreated = 1; //global counter for debugging 3.79 + //Aug 19, 2010: no longer need to place initial masterVP into queue 3.80 + // because coreLoop now controls -- animates its masterVP when no work 3.81 + 3.82 3.83 //==================== malloc substitute ======================== 3.84 // 3.85 @@ -143,15 +159,12 @@ 3.86 } 3.87 */ 3.88 3.89 -void 3.90 -create_sched_slots( MasterEnv *masterEnv ) 3.91 - { SchedSlot **schedSlots, **filledSlots; 3.92 +SchedSlot ** 3.93 +create_sched_slots() 3.94 + { SchedSlot **schedSlots; 3.95 int i; 3.96 3.97 schedSlots = malloc( NUM_SCHED_SLOTS * sizeof(SchedSlot *) ); 3.98 - filledSlots = malloc( NUM_SCHED_SLOTS * sizeof(SchedSlot *) ); 3.99 - masterEnv->schedSlots = schedSlots; 3.100 - masterEnv->filledSlots = filledSlots; 3.101 3.102 for( i = 0; i < NUM_SCHED_SLOTS; i++ ) 3.103 { 3.104 @@ -161,6 +174,18 @@ 3.105 schedSlots[i]->workIsDone = FALSE; 3.106 schedSlots[i]->needsProcrAssigned = TRUE; 3.107 } 3.108 + return schedSlots; 3.109 + } 3.110 + 3.111 + 3.112 +void 3.113 +freeSchedSlots( SchedSlot **schedSlots ) 3.114 + { int i; 3.115 + for( i = 0; i < NUM_SCHED_SLOTS; i++ ) 3.116 + { 3.117 + free( schedSlots[i] ); 3.118 + } 3.119 + free( schedSlots ); 3.120 } 3.121 3.122 3.123 @@ -267,6 +292,8 @@ 3.124 newPr->procrID = numProcrsCreated++; 3.125 newPr->nextInstrPt = fnPtr; 3.126 newPr->initialData = initialData; 3.127 + newPr->requests = NULL; 3.128 +// newPr->coreLoopStartPt = _VMSMasterEnv->coreLoopStartPt; 3.129 3.130 //fnPtr takes two params -- void *initData & void *animProcr 3.131 //alloc stack locations, make stackPtr be the highest addr minus room 3.132 @@ -314,7 +341,7 @@ 3.133 stackPtrAddr = &(callingPr->stackPtr); 3.134 framePtrAddr = &(callingPr->framePtr); 3.135 3.136 - jmpPt = callingPr->coreLoopStartPt; 3.137 + jmpPt = _VMSMasterEnv->coreLoopStartPt; 3.138 coreLoopFramePtr = callingPr->coreLoopFramePtr;//need this only 3.139 coreLoopStackPtr = callingPr->coreLoopStackPtr;//shouldn't need -- safety 3.140 3.141 @@ -350,21 +377,6 @@ 3.142 3.143 3.144 3.145 -/*This is equivalent to "jump back to core loop" -- it's mainly only used 3.146 - * just after adding dissipate request to a processor -- so the semantic 3.147 - * layer is the only place it will be seen and/or used. 3.148 - * 3.149 - *It does almost the same thing as suspend, except don't need to save the 3.150 - * stack nor set the nextInstrPt 3.151 - * 3.152 - *As of June 30, 2010 just implementing as a call to suspend -- just sugar 3.153 - */ 3.154 -void 3.155 -VMS__return_from_fn( VirtProcr *animatingPr ) 3.156 - { 3.157 - VMS__suspend_procr( animatingPr ); 3.158 - } 3.159 - 3.160 3.161 /*Not sure yet the form going to put "dissipate" in, so this is the third 3.162 * possibility -- the semantic layer can just make a macro that looks like 3.163 @@ -439,7 +451,7 @@ 3.164 //TODO: add a semantic-layer supplied "freer" for the semantic-data portion 3.165 // of a request -- IE call with both a virt procr and a fn-ptr to request 3.166 // freer (also maybe put sem request freer as a field in virt procr?) 3.167 -//VMSHW relies right now on this only freeing VMS layer of request -- the 3.168 +//SSR relies right now on this only freeing VMS layer of request -- the 3.169 // semantic portion of request is alloc'd and freed by request handler 3.170 void 3.171 VMS__free_request( VMSReqst *req ) 3.172 @@ -453,11 +465,23 @@ 3.173 3.174 req = procrWithReq->requests; 3.175 if( req == NULL ) return req; 3.176 - 3.177 + 3.178 procrWithReq->requests = procrWithReq->requests->nextReqst; 3.179 return req; 3.180 } 3.181 3.182 +VMSReqst * 3.183 +VMS__free_top_and_give_next_request_from( VirtProcr *procrWithReq ) 3.184 + { VMSReqst *req; 3.185 + 3.186 + req = procrWithReq->requests; 3.187 + if( req == NULL ) return req; 3.188 + 3.189 + procrWithReq->requests = procrWithReq->requests->nextReqst; 3.190 + VMS__free_request( req ); 3.191 + return procrWithReq->requests; 3.192 + } 3.193 + 3.194 inline int 3.195 VMS__isSemanticReqst( VMSReqst *req ) 3.196 { 3.197 @@ -562,7 +586,7 @@ 3.198 * the core loop threads have all exited) 3.199 * 3.200 *In here,create one core-loop shut-down processor for each core loop and put 3.201 - * them all directly into the workQ. 3.202 + * them all directly into the readyToAnimateQ. 3.203 *Note, this function can ONLY be called after the semantic environment no 3.204 * longer cares if AppVPs get animated after the point this is called. In 3.205 * other words, this can be used as an abort, or else it should only be 3.206 @@ -573,15 +597,13 @@ 3.207 VMS__handle_shutdown_reqst( void *dummy, VirtProcr *animatingPr ) 3.208 { int coreIdx; 3.209 VirtProcr *shutDownPr; 3.210 - VMSQueueStruc *workQ = _VMSWorkQ; 3.211 3.212 //create the shutdown processors, one for each core loop -- put them 3.213 - // directly into _VMSWorkQ -- each core will die when gets one, so 3.214 - // the system distributes them evenly itself. 3.215 + // directly into the Q -- each core will die when gets one 3.216 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) 3.217 { 3.218 shutDownPr = VMS__create_procr( &endOSThreadFn, NULL ); 3.219 - writeVMSQ( shutDownPr, workQ ); 3.220 + writeSRSWQ( shutDownPr, _VMSMasterEnv->readyToAnimateQs[coreIdx] ); 3.221 } 3.222 3.223 } 3.224 @@ -620,26 +642,36 @@ 3.225 } 3.226 3.227 3.228 - 3.229 -/*This is called after the threads have shut down and control as returned 3.230 +/*This is called after the threads have shut down and control has returned 3.231 * to the semantic layer, in the entry point function in the main thread. 3.232 * It has to free anything allocated during VMS_init, and any other alloc'd 3.233 * locations that might be left over. 3.234 */ 3.235 void 3.236 VMS__cleanup_after_shutdown() 3.237 - { int i; 3.238 - 3.239 - free( _VMSWorkQ ); 3.240 - free( _VMSMasterEnv->filledSlots ); 3.241 - for( i = 0; i < NUM_SCHED_SLOTS; i++ ) 3.242 + { 3.243 + SRSWQueueStruc **readyToAnimateQs; 3.244 + int coreIdx; 3.245 + VirtProcr **masterVPs; 3.246 + SchedSlot ***allSchedSlots; //ptr to array of ptrs 3.247 + 3.248 + readyToAnimateQs = _VMSMasterEnv->readyToAnimateQs; 3.249 + masterVPs = _VMSMasterEnv->masterVPs; 3.250 + allSchedSlots = _VMSMasterEnv->allSchedSlots; 3.251 + 3.252 + for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 3.253 { 3.254 - free( _VMSMasterEnv->schedSlots[i] ); 3.255 + freeSRSWQ( readyToAnimateQs[ coreIdx ] ); 3.256 + 3.257 + VMS__handle_dissipate_reqst( masterVPs[ coreIdx ] ); 3.258 + 3.259 + freeSchedSlots( allSchedSlots[ coreIdx ] ); 3.260 } 3.261 + 3.262 + free( _VMSMasterEnv->readyToAnimateQs ); 3.263 + free( _VMSMasterEnv->masterVPs ); 3.264 + free( _VMSMasterEnv->allSchedSlots ); 3.265 3.266 - free( _VMSMasterEnv->schedSlots); 3.267 - VMS__handle_dissipate_reqst( _VMSMasterEnv->masterVirtPr ); 3.268 - 3.269 free( _VMSMasterEnv ); 3.270 } 3.271
4.1 --- a/VMS.h Mon Aug 09 02:24:31 2010 -0700 4.2 +++ b/VMS.h Wed Sep 01 08:23:39 2010 -0700 4.3 @@ -14,6 +14,11 @@ 4.4 #include "Queue_impl/BlockingQueue.h" 4.5 #include <pthread.h> 4.6 4.7 + //When DEBUG is defined, VMS does sequential exe in the main thread 4.8 + // It still does co-routines and all the mechanisms are the same, it just 4.9 + // has only a single thread and animates VPs one at a time 4.10 +//#define DEBUG 4.11 + 4.12 //This value is the number of hardware threads in the shared memory 4.13 // machine 4.14 #define NUM_CORES 4 4.15 @@ -22,8 +27,10 @@ 4.16 //#define NUM_SCHED_SLOTS (2 * NUM_CORES + 1) 4.17 #define NUM_SCHED_SLOTS 3 4.18 4.19 - // 8K stack 4.20 -#define VIRT_PROCR_STACK_SIZE 0x20000 4.21 +#define READYTOANIMATE_RETRIES 10000 4.22 + 4.23 + // stack 4.24 +#define VIRT_PROCR_STACK_SIZE 0x10000 4.25 4.26 //256M of total memory for VMS application to VMS__malloc 4.27 #define MASSIVE_MALLOC_SIZE 0x10000000 4.28 @@ -43,7 +50,7 @@ 4.29 typedef struct _VMSReqst VMSReqst; 4.30 typedef struct _VirtProcr VirtProcr; 4.31 4.32 -typedef VirtProcr * (*SlaveScheduler) ( void * ); //semEnv 4.33 +typedef VirtProcr * (*SlaveScheduler) ( void *, int ); //semEnv, coreIdx 4.34 typedef void (*RequestHandler) ( VirtProcr *, void * ); //prWReqst, semEnv 4.35 typedef void (*VirtProcrFnPtr) ( void *, VirtProcr * ); //initData, animPr 4.36 typedef void VirtProcrFn ( void *, VirtProcr * ); //initData, animPr 4.37 @@ -109,25 +116,21 @@ 4.38 4.39 typedef struct 4.40 { 4.41 - SlaveScheduler slaveScheduler; 4.42 - RequestHandler requestHandler; 4.43 + SlaveScheduler slaveScheduler; 4.44 + RequestHandler requestHandler; 4.45 4.46 - SchedSlot **schedSlots; 4.47 - SchedSlot **filledSlots; 4.48 - int numToPrecede; 4.49 - 4.50 - volatile int stillRunning; 4.51 - 4.52 - VirtProcr *masterVirtPr; 4.53 + SchedSlot ***allSchedSlots; 4.54 + SRSWQueueStruc **readyToAnimateQs; 4.55 + VirtProcr **masterVPs; 4.56 4.57 - void *semanticEnv; 4.58 - void *OSEventStruc; //for future, when add I/O to BLIS 4.59 + void *semanticEnv; 4.60 + void *OSEventStruc; //for future, when add I/O to BLIS 4.61 4.62 - void *coreLoopEndPt; //addr to jump to to shut down a coreLoop 4.63 + void *coreLoopStartPt;//addr to jump to to re-enter coreLoop 4.64 + void *coreLoopEndPt; //addr to jump to to shut down a coreLoop 4.65 4.66 - int setupComplete; 4.67 - 4.68 - void *mallocChunk; 4.69 + int setupComplete; 4.70 + int masterLock; 4.71 } 4.72 MasterEnv; 4.73 4.74 @@ -149,11 +152,6 @@ 4.75 4.76 volatile MasterEnv *_VMSMasterEnv; 4.77 4.78 - //workQ is global, static, and volatile so that core loop has its location 4.79 - // hard coded, and reloads every time through the loop -- that way don't 4.80 - // need to save any regs used by core loop 4.81 -volatile VMSQueueStruc *_VMSWorkQ; 4.82 - 4.83 //========================== 4.84 void 4.85 VMS__init(); 4.86 @@ -190,6 +188,9 @@ 4.87 VMSReqst * 4.88 VMS__take_top_request_from( VirtProcr *reqstingPr ); 4.89 4.90 +VMSReqst * 4.91 +VMS__free_top_and_give_next_request_from( VirtProcr *procrWithReq ); 4.92 + 4.93 inline void * 4.94 VMS__take_sem_reqst_from( VMSReqst *req ); 4.95
