comparison MasterLoop.c @ 209:0c83ea8adefc

Close to compilable version of common_ancestor -- still includes HW dep stuff
author Some Random Person <seanhalle@yahoo.com>
date Sun, 04 Mar 2012 14:26:35 -0800
parents eaf7e4c58c9e
children a18539c0bc37
comparison
equal deleted inserted replaced
58:9335afc4a64d 59:fb4f1317b78c
8 8
9 #include <stdio.h> 9 #include <stdio.h>
10 #include <stddef.h> 10 #include <stddef.h>
11 11
12 #include "VMS.h" 12 #include "VMS.h"
13 #include "ProcrContext.h"
14 13
15 14
16 //=========================================================================== 15 //===========================================================================
17 void inline 16 void inline
18 stealWorkInto( SchedSlot *currSlot, VMSQueueStruc *readyToAnimateQ, 17 stealWorkInto( SchedSlot *currSlot, VMSQueueStruc *readyToAnimateQ,
19 SlaveVP *masterPr ); 18 SlaveVP *masterVP );
20 19
21 //=========================================================================== 20 //===========================================================================
22 21
23 22
24 23
25 /*This code is animated by the virtual Master processor. 24 /*This code is animated by the virtual Master processor.
26 * 25 *
27 *Polls each sched slot exactly once, hands any requests made by a newly 26 *Polls each sched slot exactly once, hands any requests made by a newly
28 * done slave to the "request handler" plug-in function 27 * done slave to the "request handler" plug-in function
29 * 28 *
30 *Any slots that need a virt procr assigned are given to the "schedule" 29 *Any slots that need a Slv assigned are given to the "schedule"
31 * plug-in function, which tries to assign a virt procr (slave) to it. 30 * plug-in function, which tries to assign a Slv (slave) to it.
32 * 31 *
33 *When all slots needing a processor have been given to the schedule plug-in, 32 *When all slots needing a processor have been given to the schedule plug-in,
34 * a fraction of the procrs successfully scheduled are put into the 33 * a fraction of the slaves successfully scheduled are put into the
35 * work queue, then a continuation of this function is put in, then the rest 34 * work queue, then a continuation of this function is put in, then the rest
36 * of the virt procrs that were successfully scheduled. 35 * of the Slvs that were successfully scheduled.
37 * 36 *
38 *The first thing the continuation does is busy-wait until the previous 37 *The first thing the continuation does is busy-wait until the previous
39 * animation completes. This is because an (unlikely) continuation may 38 * animation completes. This is because an (unlikely) continuation may
40 * sneak through queue before previous continuation is done putting second 39 * sneak through queue before previous continuation is done putting second
41 * part of scheduled slaves in, which is the only race condition. 40 * part of scheduled slaves in, which is the only race condition.
44 43
45 /*May 29, 2010 -- birth a Master during init so that first core loop to 44 /*May 29, 2010 -- birth a Master during init so that first core loop to
46 * start running gets it and does all the stuff for a newly born -- 45 * start running gets it and does all the stuff for a newly born --
47 * from then on, will be doing continuation, but do suspension self 46 * from then on, will be doing continuation, but do suspension self
48 * directly at end of master loop 47 * directly at end of master loop
49 *So VMS__init just births the master virtual processor same way it births 48 *So VMS_WL__init just births the master virtual processor same way it births
50 * all the others -- then does any extra setup needed and puts it into the 49 * all the others -- then does any extra setup needed and puts it into the
51 * work queue. 50 * work queue.
52 *However means have to make masterEnv a global static volatile the same way 51 *However means have to make masterEnv a global static volatile the same way
53 * did with readyToAnimateQ in core loop. -- for performance, put the 52 * did with readyToAnimateQ in core loop. -- for performance, put the
54 * jump to the core loop directly in here, and have it directly jump back. 53 * jump to the core loop directly in here, and have it directly jump back.
63 * animates this function has a different one. 62 * animates this function has a different one.
64 * 63 *
65 *At this point, the masterLoop does not write itself into the queue anymore, 64 *At this point, the masterLoop does not write itself into the queue anymore,
66 * instead, the coreLoop acquires the masterLock when it has nothing to 65 * instead, the coreLoop acquires the masterLock when it has nothing to
67 * animate, and then animates its own masterLoop. However, still try to put 66 * animate, and then animates its own masterLoop. However, still try to put
68 * several AppVPs into the queue to amortize the startup cost of switching 67 * several AppSlvs into the queue to amortize the startup cost of switching
69 * to the MasterVP. Note, don't have to worry about latency of requests much 68 * to the MasterVP. Note, don't have to worry about latency of requests much
70 * because most requests generate work for same core -- only latency issue 69 * because most requests generate work for same core -- only latency issue
71 * is case when other cores starved and one core's requests generate work 70 * is case when other cores starved and one core's requests generate work
72 * for them -- so keep max in queue to 3 or 4.. 71 * for them -- so keep max in queue to 3 or 4..
73 */ 72 */
74 void masterLoop( void *initData, SlaveVP *animatingPr ) 73 void masterLoop( void *initData, SlaveVP *animatingSlv )
75 { 74 {
76 int32 slotIdx, numSlotsFilled; 75 int32 slotIdx, numSlotsFilled;
77 SlaveVP *schedVirtPr; 76 SlaveVP *schedSlaveVP;
78 SchedSlot *currSlot, **schedSlots; 77 SchedSlot *currSlot, **schedSlots;
79 MasterEnv *masterEnv; 78 MasterEnv *masterEnv;
80 VMSQueueStruc *readyToAnimateQ; 79 VMSQueueStruc *readyToAnimateQ;
81 80
82 Sched_Assigner slaveScheduler; 81 Sched_Assigner slaveAssigner;
83 RequestHandler requestHandler; 82 RequestHandler requestHandler;
84 void *semanticEnv; 83 void *semanticEnv;
85 84
86 int32 thisCoresIdx; 85 int32 thisCoresIdx;
87 SlaveVP *masterPr; 86 SlaveVP *masterVP;
88 volatile SlaveVP *volatileMasterPr; 87 volatile SlaveVP *volatileMasterVP;
89 88
90 volatileMasterPr = animatingPr; 89 volatileMasterVP = animatingSlv;
91 masterPr = (SlaveVP*)volatileMasterPr; //used to force re-define after jmp 90 masterVP = (SlaveVP*)volatileMasterVP; //used to force re-define after jmp
92 91
93 //First animation of each MasterVP will in turn animate this part 92 //First animation of each MasterVP will in turn animate this part
94 // of setup code.. (VP creator sets up the stack as if this function 93 // of setup code.. (Slv creator sets up the stack as if this function
95 // was called normally, but actually get here by jmp) 94 // was called normally, but actually get here by jmp)
96 //So, setup values about stack ptr, jmp pt and all that 95 //So, setup values about stack ptr, jmp pt and all that
97 //masterPr->resumeInstrPtr = &&masterLoopStartPt; 96 //masterVP->resumeInstrPtr = &&masterLoopStartPt;
98 97
99 98
100 //Note, got rid of writing the stack and frame ptr up here, because 99 //Note, got rid of writing the stack and frame ptr up here, because
101 // only one 100 // only one
102 // core can ever animate a given MasterVP, so don't need to communicate 101 // core can ever animate a given MasterVP, so don't need to communicate
106 105
107 106
108 //masterLoopStartPt: 107 //masterLoopStartPt:
109 while(1){ 108 while(1){
110 109
111 //============================= MEASUREMENT STUFF ======================== 110 MEAS__Capture_Pre_Master_Point
112 #ifdef MEAS__TIME_MASTER
113 //Total Master time includes one coreloop time -- just assume the core
114 // loop time is same for Master as for AppVPs, even though it may be
115 // smaller due to higher predictability of the fixed jmp.
116 saveLowTimeStampCountInto( masterPr->startMasterTSCLow );
117 #endif
118 //========================================================================
119 111
120 masterEnv = (MasterEnv*)_VMSMasterEnv; 112 masterEnv = (MasterEnv*)_VMSMasterEnv;
121 113
122 //GCC may optimize so doesn't always re-define from frame-storage 114 //GCC may optimize so doesn't always re-define from frame-storage
123 masterPr = (SlaveVP*)volatileMasterPr; //just to make sure after jmp 115 masterVP = (SlaveVP*)volatileMasterVP; //just to make sure after jmp
124 thisCoresIdx = masterPr->coreAnimatedBy; 116 thisCoresIdx = masterVP->coreAnimatedBy;
125 readyToAnimateQ = masterEnv->readyToAnimateQs[thisCoresIdx]; 117 readyToAnimateQ = masterEnv->readyToAnimateQs[thisCoresIdx];
126 schedSlots = masterEnv->allSchedSlots[thisCoresIdx]; 118 schedSlots = masterEnv->allSchedSlots[thisCoresIdx];
127 119
128 requestHandler = masterEnv->requestHandler; 120 requestHandler = masterEnv->requestHandler;
129 slaveScheduler = masterEnv->slaveSchedAssigner; 121 slaveAssigner = masterEnv->slaveAssigner;
130 semanticEnv = masterEnv->semanticEnv; 122 semanticEnv = masterEnv->semanticEnv;
131 123
132 124
133 //Poll each slot's Done flag 125 //Poll each slot's Done flag
134 numSlotsFilled = 0; 126 numSlotsFilled = 0;
137 currSlot = schedSlots[ slotIdx ]; 129 currSlot = schedSlots[ slotIdx ];
138 130
139 if( currSlot->workIsDone ) 131 if( currSlot->workIsDone )
140 { 132 {
141 currSlot->workIsDone = FALSE; 133 currSlot->workIsDone = FALSE;
142 currSlot->needsProcrAssigned = TRUE; 134 currSlot->needsSlaveAssigned = TRUE;
143 135
144 //process requests from slave to master 136 //process requests from slave to master
145 //====================== MEASUREMENT STUFF =================== 137 //====================== MEASUREMENT STUFF ===================
146 #ifdef MEAS__TIME_PLUGIN 138 #ifdef MEAS__TURN_ON_PLUGIN_MEAS
147 int32 startStamp1, endStamp1; 139 int32 startStamp1, endStamp1;
148 saveLowTimeStampCountInto( startStamp1 ); 140 saveLowTimeStampCountInto( startStamp1 );
149 #endif 141 #endif
150 //============================================================ 142 //============================================================
151 (*requestHandler)( currSlot->procrAssignedToSlot, semanticEnv ); 143 (*requestHandler)( currSlot->slaveAssignedToSlot, semanticEnv );
152 //====================== MEASUREMENT STUFF =================== 144 //====================== MEASUREMENT STUFF ===================
153 #ifdef MEAS__TIME_PLUGIN 145 #ifdef MEAS__TURN_ON_PLUGIN_MEAS
154 saveLowTimeStampCountInto( endStamp1 ); 146 saveLowTimeStampCountInto( endStamp1 );
155 addIntervalToHist( startStamp1, endStamp1, 147 addIntervalToHist( startStamp1, endStamp1,
156 _VMSMasterEnv->reqHdlrLowTimeHist ); 148 _VMSMasterEnv->reqHdlrLowTimeHist );
157 addIntervalToHist( startStamp1, endStamp1, 149 addIntervalToHist( startStamp1, endStamp1,
158 _VMSMasterEnv->reqHdlrHighTimeHist ); 150 _VMSMasterEnv->reqHdlrHighTimeHist );
159 #endif 151 #endif
160 //============================================================ 152 //============================================================
161 } 153 }
162 if( currSlot->needsProcrAssigned ) 154 if( currSlot->needsSlaveAssigned )
163 { //give slot a new virt procr 155 { //give slot a new Slv
164 schedVirtPr = 156 schedSlaveVP =
165 (*slaveScheduler)( semanticEnv, thisCoresIdx ); 157 (*slaveAssigner)( semanticEnv, thisCoresIdx );
166 158
167 if( schedVirtPr != NULL ) 159 if( schedSlaveVP != NULL )
168 { currSlot->procrAssignedToSlot = schedVirtPr; 160 { currSlot->slaveAssignedToSlot = schedSlaveVP;
169 schedVirtPr->schedSlot = currSlot; 161 schedSlaveVP->schedSlot = currSlot;
170 currSlot->needsProcrAssigned = FALSE; 162 currSlot->needsSlaveAssigned = FALSE;
171 numSlotsFilled += 1; 163 numSlotsFilled += 1;
172 164
173 writeVMSQ( schedVirtPr, readyToAnimateQ ); 165 writeVMSQ( schedSlaveVP, readyToAnimateQ );
174 } 166 }
175 } 167 }
176 } 168 }
177 169
178 170
179 #ifdef USE_WORK_STEALING 171 #ifdef USE_WORK_STEALING
180 //If no slots filled, means no more work, look for work to steal. 172 //If no slots filled, means no more work, look for work to steal.
181 if( numSlotsFilled == 0 ) 173 if( numSlotsFilled == 0 )
182 { gateProtected_stealWorkInto( currSlot, readyToAnimateQ, masterPr ); 174 { gateProtected_stealWorkInto( currSlot, readyToAnimateQ, masterVP );
183 } 175 }
184 #endif 176 #endif
185 177
186 178 MEAS__Capture_Post_Master_Point;
187 #ifdef MEAS__TIME_MASTER 179
188 saveLowTimeStampCountInto( masterPr->endMasterTSCLow ); 180 masterSwitchToCoreLoop(animatingSlv);
189 #endif
190
191 masterSwitchToCoreLoop(animatingPr);
192 flushRegisters(); 181 flushRegisters();
193 }//MasterLoop 182 }//MasterLoop
194 183
195 184
196 } 185 }
200 /*This has a race condition -- the coreloops are accessing their own queues 189 /*This has a race condition -- the coreloops are accessing their own queues
201 * at the same time that this work-stealer on a different core is trying to 190 * at the same time that this work-stealer on a different core is trying to
202 */ 191 */
203 void inline 192 void inline
204 stealWorkInto( SchedSlot *currSlot, VMSQueueStruc *readyToAnimateQ, 193 stealWorkInto( SchedSlot *currSlot, VMSQueueStruc *readyToAnimateQ,
205 SlaveVP *masterPr ) 194 SlaveVP *masterVP )
206 { 195 {
207 SlaveVP *stolenPr; 196 SlaveVP *stolenSlv;
208 int32 coreIdx, i; 197 int32 coreIdx, i;
209 VMSQueueStruc *currQ; 198 VMSQueueStruc *currQ;
210 199
211 stolenPr = NULL; 200 stolenSlv = NULL;
212 coreIdx = masterPr->coreAnimatedBy; 201 coreIdx = masterVP->coreAnimatedBy;
213 for( i = 0; i < NUM_CORES -1; i++ ) 202 for( i = 0; i < NUM_CORES -1; i++ )
214 { 203 {
215 if( coreIdx >= NUM_CORES -1 ) 204 if( coreIdx >= NUM_CORES -1 )
216 { coreIdx = 0; 205 { coreIdx = 0;
217 } 206 }
218 else 207 else
219 { coreIdx++; 208 { coreIdx++;
220 } 209 }
221 currQ = _VMSMasterEnv->readyToAnimateQs[coreIdx]; 210 currQ = _VMSMasterEnv->readyToAnimateQs[coreIdx];
222 if( numInVMSQ( currQ ) > 0 ) 211 if( numInVMSQ( currQ ) > 0 )
223 { stolenPr = readVMSQ (currQ ); 212 { stolenSlv = readVMSQ (currQ );
224 break; 213 break;
225 } 214 }
226 } 215 }
227 216
228 if( stolenPr != NULL ) 217 if( stolenSlv != NULL )
229 { currSlot->procrAssignedToSlot = stolenPr; 218 { currSlot->slaveAssignedToSlot = stolenSlv;
230 stolenPr->schedSlot = currSlot; 219 stolenSlv->schedSlot = currSlot;
231 currSlot->needsProcrAssigned = FALSE; 220 currSlot->needsSlaveAssigned = FALSE;
232 221
233 writeVMSQ( stolenPr, readyToAnimateQ ); 222 writeVMSQ( stolenSlv, readyToAnimateQ );
234 } 223 }
235 } 224 }
236 225
237 /*This algorithm makes the common case fast. Make the coreloop passive, 226 /*This algorithm makes the common case fast. Make the coreloop passive,
238 * and show its progress. Make the stealer control a gate that coreloop 227 * and show its progress. Make the stealer control a gate that coreloop
304 * 293 *
305 */ 294 */
306 void inline 295 void inline
307 gateProtected_stealWorkInto( SchedSlot *currSlot, 296 gateProtected_stealWorkInto( SchedSlot *currSlot,
308 VMSQueueStruc *myReadyToAnimateQ, 297 VMSQueueStruc *myReadyToAnimateQ,
309 SlaveVP *masterPr ) 298 SlaveVP *masterVP )
310 { 299 {
311 SlaveVP *stolenPr; 300 SlaveVP *stolenSlv;
312 int32 coreIdx, i, haveAVictim, gotLock; 301 int32 coreIdx, i, haveAVictim, gotLock;
313 VMSQueueStruc *victimsQ; 302 VMSQueueStruc *victimsQ;
314 303
315 volatile GateStruc *vicGate; 304 volatile GateStruc *vicGate;
316 int32 coreMightBeInProtected; 305 int32 coreMightBeInProtected;
317 306
318 307
319 308
320 //see if any other cores have work available to steal 309 //see if any other cores have work available to steal
321 haveAVictim = FALSE; 310 haveAVictim = FALSE;
322 coreIdx = masterPr->coreAnimatedBy; 311 coreIdx = masterVP->coreAnimatedBy;
323 for( i = 0; i < NUM_CORES -1; i++ ) 312 for( i = 0; i < NUM_CORES -1; i++ )
324 { 313 {
325 if( coreIdx >= NUM_CORES -1 ) 314 if( coreIdx >= NUM_CORES -1 )
326 { coreIdx = 0; 315 { coreIdx = 0;
327 } 316 }
352 coreMightBeInProtected = FALSE; 341 coreMightBeInProtected = FALSE;
353 if( vicGate->preGateProgress == vicGate->exitProgress ) 342 if( vicGate->preGateProgress == vicGate->exitProgress )
354 coreMightBeInProtected = FALSE; 343 coreMightBeInProtected = FALSE;
355 } 344 }
356 345
357 stolenPr = readVMSQ ( victimsQ ); 346 stolenSlv = readVMSQ ( victimsQ );
358 347
359 vicGate->gateClosed = FALSE; 348 vicGate->gateClosed = FALSE;
360 //======= End Gate-protection ======= 349 //======= End Gate-protection =======
361 350
362 351
363 if( stolenPr != NULL ) //victim could have been in protected and taken 352 if( stolenSlv != NULL ) //victim could have been in protected and taken
364 { currSlot->procrAssignedToSlot = stolenPr; 353 { currSlot->slaveAssignedToSlot = stolenSlv;
365 stolenPr->schedSlot = currSlot; 354 stolenSlv->schedSlot = currSlot;
366 currSlot->needsProcrAssigned = FALSE; 355 currSlot->needsSlaveAssigned = FALSE;
367 356
368 writeVMSQ( stolenPr, myReadyToAnimateQ ); 357 writeVMSQ( stolenSlv, myReadyToAnimateQ );
369 } 358 }
370 359
371 //unlock the work stealing lock 360 //unlock the work stealing lock
372 _VMSMasterEnv->workStealingLock = UNLOCKED; 361 _VMSMasterEnv->workStealingLock = UNLOCKED;
373 } 362 }