comparison VMS.c @ 1:cf5007e51b96

In flux -- has PThread startup -- about to change to winblows threads
author Me
date Mon, 31 May 2010 14:11:14 -0700
parents a5fe730dfc2e
children 9a1b7de19e39
comparison
equal deleted inserted replaced
0:45391308a69a 1:c3d3af1bdd18
39 * and master environment, and returns the master environment to the semantic 39 * and master environment, and returns the master environment to the semantic
40 * layer. 40 * layer.
41 */ 41 */
42 //Global vars are all inside VMS.h 42 //Global vars are all inside VMS.h
43 MasterEnv * 43 MasterEnv *
44 init_VMS( ) 44 VMS__init( )
45 { 45 { MasterEnv *masterEnv;
46 QueueStruc *workQ;
47
46 //Make the central work-queue 48 //Make the central work-queue
47 workQ = makeQ(); 49 _VMSWorkQ = makeQ();
48 50 workQ = _VMSWorkQ;
49 masterEnv = malloc( sizeof(MasterEnv) ); 51
52 _VMSMasterEnv = malloc( sizeof(MasterEnv) );
53 masterEnv = _VMSMasterEnv;
50 54
51 create_master( masterEnv ); 55 create_master( masterEnv );
52 56
53 create_slaves( masterEnv ); 57 create_sched_slots( masterEnv );
54 58
55 //When coreLoops start up, the first thing 59 masterEnv->schedSlots[0]->needsProcrAssigned = FALSE; //never checked
56 writeQ( masterEnv->masterWorkUnit, workQ ); 60 masterEnv->schedSlots[0]->workIsDone = FALSE; //never checked
57 } 61 masterEnv->schedSlots[0]->procrAssignedToSlot = masterEnv->masterVirtPr;
58 62
59 63 //First core loop to start up gets this, which will schedule seed Pr
60 64 //TODO: debug: check address of masterVirtPr
61 /*Fill up the virtual master data structure, which is already alloc'd in the 65 writeQ( &(masterEnv->masterVirtPr), workQ );
62 * masterEnv. 66 }
63 *The virtual Master is the same structure as a virtual slave, but it 67
64 * isn't in the array of virtual slaves. 68
65 * The reason it's the same structure is so that the coreLoop doesn't 69
66 * have to differentiate -- all work units are assigned to a VMSProcr, and 70 /*Fill up the master VirtProcr data structure, which is already alloc'd
67 * the core loop treats them all the same way, whether it's the virtual 71 * in the masterEnv.
68 * master continuation or a slave's work-unit. 72 * The coreLoop treats master virt pr same as the slave virt processors
69 *Note: masterLoop is jumped into an back out of, so have to be careful with 73 *
70 * register usage and saving all persistent-across-calls state to masterEnv 74 *The first time it runs, will jump to the function ptr so have to, in here,
75 * create the stack, which will be used by the plug-in functions, and set
76 * up __cdecl just like do for the other virtual processors.
71 */ 77 */
72 void 78 void
73 create_master( MasterEnv *masterEnv ) 79 create_master( MasterEnv *masterEnv )
74 { VMSProcr virtMaster; 80 { VirtProcr masterPr;
75 81 char * stackLocs, stackPtr;
76 virtMaster = &(masterEnv->virtMaster); 82
77 virtMaster->workUnitToDo = malloc( sizeof( WorkUnit ) ); 83 //TODO: debug this to be sure got addr of struct in masterEnv correctly
78 virtMaster->workUnitToDo->workData = masterEnv; 84 masterPr = &(masterEnv->masterVirtPr);
79 //TODO: figure out call structure: what GCC will do with regs 85 masterPr->initialData = masterEnv;
80 // will jump to the masterLoop from the coreLoop -- what regs need 86
81 // saving, from before jump to after -- and what reg to put masterEnv 87 masterPr->nextInstrPt = &masterLoop;
82 // pointer in when jump to masterLoop 88
83 virtMaster->workUnitToDo->addrToJumpTo = &masterLoop; 89 //alloc stack locations, make stackPtr be the last addr in the locs,
84 virtMaster->workUnitToDo->slaveAssignedTo = virtMaster; 90 // minus room for the two parameters. Put initData at stackPtr,
91 // animatingPr just above
92 stackLocs = malloc( 0x100000 ); //1 meg stack -- default Win thread's size
93 stackPtr = ( (char *)stackLocs + 0x100000 - 0x8 );
94 masterPr->stackPtr = stackPtr;
95 masterPr->framePtr = stackPtr;
96 asm volatile("movl %0, %%esp;
97 movl %1, (%%esp);
98 movl %2, $0x4(%%esp);
99 movl %%esp, %%ebp; " /*framePtr in ebp never used*/
100 /* outputs */ :
101 /* inputs */ : "g" (stackPtr), "g" (initData), "g" (animPr)
102 /* clobber */ :
103 );
85 } 104 }
86 105
87 void 106 void
88 create_slaves( MasterEnv *masterEnv ) 107 create_sched_slots( MasterEnv *masterEnv )
89 { VMSProcr *virtSlaves; 108 { SchedSlot *slots;
90 int i; 109 int i;
91 110
92 virtSlaves = masterEnv->virtSlaves; //TODO: make sure this is right 111 slots = masterEnv->schedSlots; //TODO: make sure this is right
93 for( i = 0; i < NUM_SLAVES; i++ ) 112 for( i = 0; i < NUM_SCHED_SLOTS; i++ )
94 { 113 {
95 //Set state to mean "everything done, schedule work to slave" 114 //Set state to mean "handling requests done, slot needs filling"
96 virtSlaves[i].workIsDone = FALSE; 115 slots[i].workIsDone = FALSE;
97 virtSlaves[i].needsWorkAssigned = TRUE; 116 slots[i].needsProcrAssigned = TRUE;
98 } 117 }
99 } 118 }
100 119
101 /*Semantic layer calls this when it want the system to start running.. 120 /*Semantic layer calls this when it want the system to start running..
102 * 121 *
111 130
112 //Create the PThread loops that take from work-queue, and start them 131 //Create the PThread loops that take from work-queue, and start them
113 for( coreIdx=0; coreIdx < NUM_WORKERS; coreIdx++ ) 132 for( coreIdx=0; coreIdx < NUM_WORKERS; coreIdx++ )
114 { 133 {
115 thdParams[coreIdx] = (ThdParams *)malloc( sizeof(ThdParams) ); 134 thdParams[coreIdx] = (ThdParams *)malloc( sizeof(ThdParams) );
116 thdParams[coreIdx]->workQ = workQ; 135 thdParams[coreIdx]->workQ = _VMSWorkQ;
117 thdParams[coreIdx]->id = coreIdx; 136 thdParams[coreIdx]->id = coreIdx;
118 137
119 //Now make and start thd.. the coreLoopThds entry 138 //Now make and start thd.. the coreLoopThds entry
120 // has all the info needed to later stop the thread. 139 // has all the info needed to later stop the thread.
121 retCode = 140 retCode =
141 * "done with work-unit" label. The procr struc is in the request in the 160 * "done with work-unit" label. The procr struc is in the request in the
142 * slave that animated the just-ended work-unit, so all the state is saved 161 * slave that animated the just-ended work-unit, so all the state is saved
143 * there, and will get passed along, inside the request handler, to the 162 * there, and will get passed along, inside the request handler, to the
144 * next work-unit for that procr. 163 * next work-unit for that procr.
145 */ 164 */
146 VMS__save_ret_and_jump_to_CoreLoop( callingPr ) 165 VMS__suspend_processor( VirtProcr *callingPr )
147 { 166 { void *jmpPt;
148 //TODO: figure out how to save the addr of a label into a mem loc 167
149 //NOTE: because resume pt is inside the VMS fn, it's always the same, no 168 callingPr->nextInstrPt = &&ResumePt;
150 // matter what the semantic layer is, no matter what semantic libr called. 169
151 callingPr->resumePt = &resumeNextWorkUnitPt; 170 //return ownership of the virt procr and sched slot to Master virt pr
152 save_processor_state_in( callingPr ); //save x86 regs, if GCC needs it to 171 callingPr->schedSlot->workIsDone = TRUE;
153 coreLoopRetPt = callingPr->coreLoopRetPt; 172
154 //TODO: figure out how to do jump correctly -- target addr is constant 173 jmpPt = callingPr->coreLoopStartPt;
155 asm( jmp coreLoopRetPt ); 174
156 175 //put all regs in the clobber list to make sure GCC has saved all
157 resumeNextWorkUnitPt: 176 // so safe to jump to core loop, where they *will* get clobbered
177 asm volatile("movl %%esp, %0;
178 movl %%ebp, %1;
179 jmp %2 "
180 /* outputs */ : "=m" (currPr->stackPtr), "=m" (currPr->framePtr)
181 /* inputs */ : "g" (jmpPt)
182 /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi","%esi"
183 );
184
185 ResumePt:
158 return; 186 return;
187 }
188
189
190 /*Create stack, then create __cdecl structure on it and put initialData and
191 * pointer to the new structure instance into the parameter positions on
192 * the stack
193 *Then put function pointer into nextInstrPt -- the stack is setup in std
194 * call structure, so jumping to function ptr is same as a GCC generated
195 * function call
196 *No need to save registers on old stack frame, because there's no old
197 * animator state to return to --
198 *
199 */
200 VirtProcr *
201 VMS__create_procr( VirtProcrFnPtr fnPtr, void *initialData )
202 { VirtProcr newPr;
203
204 newPr = malloc( sizeof(VirtProcr) );
205 newPr->nextInstrPt = fnPtr;
206 newPr->initialData = initialData;
207 newPr->stackPtr = createNewStack();
208 newPr->framePtr = newPr->stackPtr;
209 put params onto stack and setup __cdecl call structure
210
211 return newPr;
159 } 212 }
160 213
161 214
162 /*The semantic virt procr is available in the request sent from the slave 215 /*The semantic virt procr is available in the request sent from the slave
163 * 216 *
164 * The request handler has to add the work-unit created to the semantic 217 * The request handler has to add the work-unit created to the semantic
165 * virtual processor the work-unit is a section of its time-line -- does this when create the 218 * virtual processor the work-unit is a section of its time-line -- does this when create the
166 * work-unit -- means the procr data struc is available in the request sent 219 * work-unit -- means the procr data struc is available in the request sent
167 * from the slave, from which the new work-unit is generated.. 220 * from the slave, from which the new work-unit is generated..
168 */ 221 */
169 VMS__add_request_to_slave( SlaveReqst req, VMSProcr callingPr ) 222 inline void
170 { VMSProcr slave; 223 VMS__add_request_to_slave( SlaveReqst req, VirtProcr callingPr )
171 slave = callingPr->workUnit->currSlave 224 {
172 req->nextRequest = callingPr->workUnit->currSlave->requests = req; 225 req->nextRequest = callingPr->requests;
173 } 226 callingPr->requests = req;
174 227 }
175 228
176 229
230