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