| rev |
line source |
|
Me@0
|
1 /*
|
|
Me@38
|
2 * Copyright 2010 OpenSourceStewardshipFoundation
|
|
Me@43
|
3 *
|
|
Me@0
|
4 * Licensed under BSD
|
|
Me@0
|
5 */
|
|
Me@0
|
6
|
|
Me@0
|
7
|
|
Me@0
|
8
|
|
Me@0
|
9 #include <stdio.h>
|
|
Me@0
|
10 #include <malloc.h>
|
|
Me@9
|
11 #include <stddef.h>
|
|
Me@0
|
12
|
|
Me@0
|
13 #include "VMS.h"
|
|
Me@0
|
14
|
|
Me@0
|
15
|
|
Me@0
|
16
|
|
Me@0
|
17 /*This code is animated by the virtual Master processor.
|
|
Me@0
|
18 *
|
|
Me@11
|
19 *Polls each sched slot exactly once, hands any requests made by a newly
|
|
Me@11
|
20 * done slave to the "request handler" plug-in function
|
|
Me@0
|
21 *
|
|
Me@11
|
22 *Any slots that need a virt procr assigned are given to the "schedule"
|
|
Me@11
|
23 * plug-in function, which tries to assign a virt procr (slave) to it.
|
|
Me@0
|
24 *
|
|
Me@11
|
25 *When all slots needing a processor have been given to the schedule plug-in,
|
|
Me@11
|
26 * a fraction of the procrs successfully scheduled are put into the
|
|
Me@11
|
27 * work queue, then a continuation of this function is put in, then the rest
|
|
Me@11
|
28 * of the virt procrs that were successfully scheduled.
|
|
Me@0
|
29 *
|
|
Me@11
|
30 *The first thing the continuation does is busy-wait until the previous
|
|
Me@11
|
31 * animation completes. This is because an (unlikely) continuation may
|
|
Me@11
|
32 * sneak through queue before previous continuation is done putting second
|
|
Me@11
|
33 * part of scheduled slaves in, which is the only race condition.
|
|
Me@0
|
34 *
|
|
Me@0
|
35 */
|
|
Me@0
|
36
|
|
Me@4
|
37 /*May 29, 2010 -- birth a Master during init so that first core loop to
|
|
Me@11
|
38 * start running gets it and does all the stuff for a newly born --
|
|
Me@11
|
39 * from then on, will be doing continuation, but do suspension self
|
|
Me@4
|
40 * directly at end of master loop
|
|
Me@4
|
41 *So VMS__init just births the master virtual processor same way it births
|
|
Me@4
|
42 * all the others -- then does any extra setup needed and puts it into the
|
|
Me@4
|
43 * work queue.
|
|
Me@4
|
44 *However means have to make masterEnv a global static volatile the same way
|
|
Me@31
|
45 * did with readyToAnimateQ in core loop. -- for performance, put the
|
|
Me@11
|
46 * jump to the core loop directly in here, and have it directly jump back.
|
|
Me@31
|
47 *
|
|
Me@31
|
48 *
|
|
Me@31
|
49 *Aug 18, 2010 -- Going to a separate MasterVP for each core, to see if this
|
|
Me@31
|
50 * avoids the suspected bug in the system stack that causes bizarre faults
|
|
Me@31
|
51 * at random places in the system code.
|
|
Me@31
|
52 *
|
|
Me@31
|
53 *So, this function is coupled to each of the MasterVPs, -- meaning this
|
|
Me@31
|
54 * function can't rely on a particular stack and frame -- each MasterVP that
|
|
Me@31
|
55 * animates this function has a different one.
|
|
Me@31
|
56 *
|
|
Me@31
|
57 *At this point, the masterLoop does not write itself into the queue anymore,
|
|
Me@31
|
58 * instead, the coreLoop acquires the masterLock when it has nothing to
|
|
Me@31
|
59 * animate, and then animates its own masterLoop. However, still try to put
|
|
Me@31
|
60 * several AppVPs into the queue to amortize the startup cost of switching
|
|
Me@31
|
61 * to the MasterVP. Note, don't have to worry about latency of requests much
|
|
Me@31
|
62 * because most requests generate work for same core -- only latency issue
|
|
Me@31
|
63 * is case when other cores starved and one core's requests generate work
|
|
Me@31
|
64 * for them -- so keep max in queue to 3 or 4..
|
|
Me@4
|
65 */
|
|
Me@31
|
66 void masterLoop( void *initData, VirtProcr *animatingPr )
|
|
Me@21
|
67 {
|
|
Me@31
|
68 int slotIdx;
|
|
Me@21
|
69 VirtProcr *schedVirtPr;
|
|
Me@31
|
70 SchedSlot *currSlot, **schedSlots;
|
|
Me@0
|
71 MasterEnv *masterEnv;
|
|
Me@31
|
72 VMSQueueStruc *readyToAnimateQ;
|
|
Me@4
|
73
|
|
Me@0
|
74 SlaveScheduler slaveScheduler;
|
|
Me@0
|
75 RequestHandler requestHandler;
|
|
Me@31
|
76 void *semanticEnv;
|
|
Me@0
|
77
|
|
Me@31
|
78 int thisCoresIdx;
|
|
Me@31
|
79 VirtProcr *masterPr;
|
|
Me@31
|
80 volatile VirtProcr *volatileMasterPr;
|
|
Me@31
|
81
|
|
Me@31
|
82 volatileMasterPr = animatingPr;
|
|
Me@31
|
83 masterPr = volatileMasterPr; //used to force re-define after jmp
|
|
Me@31
|
84
|
|
Me@31
|
85 //First animation of each MasterVP will in turn animate this part
|
|
Me@31
|
86 // of setup code.. (VP creator sets up the stack as if this function
|
|
Me@31
|
87 // was called normally, but actually get here by jmp)
|
|
Me@31
|
88 //So, setup values about stack ptr, jmp pt and all that
|
|
Me@4
|
89 masterPr->nextInstrPt = &&masterLoopStartPt;
|
|
Me@0
|
90
|
|
Me@26
|
91
|
|
Me@31
|
92 //Note, got rid of writing the stack and frame ptr up here, because
|
|
Me@31
|
93 // only one
|
|
Me@31
|
94 // core can ever animate a given MasterVP, so don't need to communicate
|
|
Me@31
|
95 // new frame and stack ptr to the MasterVP storage before a second
|
|
Me@31
|
96 // version of that MasterVP can get animated on a different core.
|
|
Me@31
|
97 //Also got rid of the busy-wait.
|
|
Me@26
|
98
|
|
Me@31
|
99
|
|
Me@4
|
100 masterLoopStartPt:
|
|
Me@38
|
101 //============================= MEASUREMENT STUFF ========================
|
|
Me@38
|
102 #ifdef MEAS__TIME_MASTER
|
|
Me@38
|
103 //Total Master time includes one coreloop time -- just assume the core
|
|
Me@38
|
104 // loop time is same for Master as for AppVPs, even though it will be
|
|
Me@41
|
105 // smaller due to high predictability of the fixed jmp.
|
|
Me@38
|
106 saveLowTimeStampCountInto( masterPr->startMasterTSCLow );
|
|
Me@38
|
107 #endif
|
|
Me@38
|
108 //========================================================================
|
|
Me@0
|
109
|
|
Me@31
|
110 masterEnv = _VMSMasterEnv;
|
|
Me@4
|
111
|
|
Me@31
|
112 //TODO: check that compiles so that always re-define from frame-storage
|
|
Me@31
|
113 masterPr = volatileMasterPr; //just to make sure after jmp
|
|
Me@31
|
114 thisCoresIdx = masterPr->coreAnimatedBy;
|
|
Me@31
|
115 readyToAnimateQ = masterEnv->readyToAnimateQs[thisCoresIdx];
|
|
Me@31
|
116 schedSlots = masterEnv->allSchedSlots[thisCoresIdx];
|
|
Me@4
|
117
|
|
Me@0
|
118 requestHandler = masterEnv->requestHandler;
|
|
Me@0
|
119 slaveScheduler = masterEnv->slaveScheduler;
|
|
Me@21
|
120 semanticEnv = masterEnv->semanticEnv;
|
|
Me@0
|
121
|
|
Me@0
|
122
|
|
Me@31
|
123 //Poll each slot's Done flag
|
|
Me@26
|
124 for( slotIdx = 0; slotIdx < NUM_SCHED_SLOTS; slotIdx++)
|
|
Me@0
|
125 {
|
|
Me@4
|
126 currSlot = schedSlots[ slotIdx ];
|
|
Me@0
|
127
|
|
Me@4
|
128 if( currSlot->workIsDone )
|
|
Me@0
|
129 {
|
|
Me@4
|
130 currSlot->workIsDone = FALSE;
|
|
Me@4
|
131 currSlot->needsProcrAssigned = TRUE;
|
|
Me@0
|
132
|
|
Me@0
|
133 //process requests from slave to master
|
|
Me@21
|
134 (*requestHandler)( currSlot->procrAssignedToSlot, semanticEnv );
|
|
Me@0
|
135 }
|
|
Me@4
|
136 if( currSlot->needsProcrAssigned )
|
|
Me@4
|
137 { //give slot a new virt procr
|
|
Me@21
|
138 schedVirtPr =
|
|
Me@31
|
139 (*slaveScheduler)( semanticEnv, thisCoresIdx );
|
|
Me@0
|
140
|
|
Me@21
|
141 if( schedVirtPr != NULL )
|
|
Me@21
|
142 { currSlot->procrAssignedToSlot = schedVirtPr;
|
|
Me@26
|
143 schedVirtPr->schedSlot = currSlot;
|
|
Me@26
|
144 currSlot->needsProcrAssigned = FALSE;
|
|
Me@4
|
145
|
|
Me@31
|
146 writeSRSWQ( schedVirtPr, readyToAnimateQ );
|
|
Me@0
|
147 }
|
|
Me@0
|
148 }
|
|
Me@0
|
149 }
|
|
Me@0
|
150
|
|
Me@26
|
151
|
|
Me@31
|
152 //Save stack ptr and frame, restore CoreLoop's stack and frame,
|
|
Me@31
|
153 // and clear the MasterLock
|
|
Me@21
|
154 //TODO: cafefully verify don't need to force saving anything to stack
|
|
Me@21
|
155 // before jumping back to core loop.
|
|
Me@31
|
156 void *stackPtrAddr, *framePtrAddr, *masterLockAddr;
|
|
Me@31
|
157 void *jmpPt, *coreLoopFramePtr, *coreLoopStackPtr;
|
|
Me@31
|
158
|
|
Me@21
|
159 stackPtrAddr = &(masterPr->stackPtr);
|
|
Me@21
|
160 framePtrAddr = &(masterPr->framePtr);
|
|
Me@31
|
161 masterLockAddr = &(_VMSMasterEnv->masterLock);
|
|
Me@21
|
162
|
|
Me@31
|
163 jmpPt = _VMSMasterEnv->coreLoopStartPt;
|
|
Me@21
|
164 coreLoopFramePtr = masterPr->coreLoopFramePtr;//need this only
|
|
Me@21
|
165 coreLoopStackPtr = masterPr->coreLoopStackPtr;//shouldn't need -- safety
|
|
Me@21
|
166
|
|
Me@38
|
167 #ifdef MEAS__TIME_MASTER
|
|
Me@38
|
168 saveLowTimeStampCountInto( masterPr->endMasterTSCLow );
|
|
Me@38
|
169 #endif
|
|
Me@38
|
170
|
|
Me@21
|
171 asm volatile("movl %0, %%eax; \
|
|
Me@21
|
172 movl %%esp, (%%eax); \
|
|
Me@21
|
173 movl %1, %%eax; \
|
|
Me@21
|
174 movl %%ebp, (%%eax); \
|
|
Me@21
|
175 movl %2, %%ebx; \
|
|
Me@21
|
176 movl %3, %%eax; \
|
|
Me@21
|
177 movl %4, %%esp; \
|
|
Me@21
|
178 movl %5, %%ebp; \
|
|
Me@21
|
179 movl $0x0, (%%ebx); \
|
|
Me@30
|
180 jmp %%eax;" \
|
|
Me@21
|
181 /* outputs */ : "=g" (stackPtrAddr), "=g" (framePtrAddr), \
|
|
Me@38
|
182 "=g"(masterLockAddr) \
|
|
Me@21
|
183 /* inputs */ : "g" (jmpPt), "g"(coreLoopStackPtr), "g"(coreLoopFramePtr)\
|
|
Me@21
|
184 /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" \
|
|
Me@21
|
185 );//can probably make clobber list empty -- but safe for now
|
|
Me@0
|
186 }
|
|
Me@0
|
187
|
|
Me@0
|
188
|