| rev |
line source |
|
seanhalle@230
|
1 /*
|
|
seanhalle@270
|
2 * Copyright 2012 OpenSourceResearchInstitute.org
|
|
seanhalle@230
|
3 *
|
|
seanhalle@230
|
4 * Licensed under BSD
|
|
seanhalle@230
|
5 */
|
|
seanhalle@230
|
6
|
|
seanhalle@230
|
7
|
|
seanhalle@230
|
8
|
|
seanhalle@230
|
9 #include <stdio.h>
|
|
seanhalle@230
|
10 #include <stddef.h>
|
|
seanhalle@230
|
11
|
|
seanhalle@260
|
12 #include "PR.h"
|
|
seanhalle@261
|
13 #include "VSs_impl/VSs.h"
|
|
seanhalle@230
|
14
|
|
seanhalle@268
|
15 /*
|
|
seanhalle@268
|
16 void PRHandle_CreateTask_SL(SlaveVP *slave);
|
|
seanhalle@230
|
17
|
|
seanhalle@268
|
18 void PRHandle_CreateSlave_SL(SlaveVP *slave);
|
|
seanhalle@268
|
19 void PRHandle_Dissipate_SL(SlaveVP *slave);
|
|
seanhalle@268
|
20 void PR_int__handle_PRServiceReq_SL(SlaveVP *slave);
|
|
seanhalle@268
|
21 */
|
|
seanhalle@272
|
22 inline void PRHandle__CreateTask( PRReqst *req, SlaveVP *slave );
|
|
seanhalle@272
|
23 inline void PRHandle__EndTask( PRReqst *req, SlaveVP *slave );
|
|
seanhalle@272
|
24 inline void PRHandle__CreateSlave(PRReqst *req, SlaveVP *slave );
|
|
seanhalle@272
|
25 void PRHandle__EndSlave( PRReqst *req, SlaveVP *slave );
|
|
seanhalle@268
|
26
|
|
seanhalle@268
|
27
|
|
seanhalle@268
|
28 //inline void masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot );
|
|
seanhalle@268
|
29 inline PRProcess * pickAProcess( AnimSlot *slot );
|
|
seanhalle@270
|
30 inline bool32 assignWork( PRProcess *process, AnimSlot *slot );
|
|
seanhalle@230
|
31
|
|
seanhalle@272
|
32
|
|
seanhalle@272
|
33 /*Note: there used to be a coreController that was another animation
|
|
seanhalle@272
|
34 * layer below both the masterVP and the slaveVPs.. in that case, the
|
|
seanhalle@272
|
35 * masterVP was a virtual processor whose processor-state was the same
|
|
seanhalle@272
|
36 * as a slaveVP's processor sate, both implemented as a SlaveVP struct.
|
|
seanhalle@272
|
37 * Have removed that, and
|
|
seanhalle@272
|
38 * changed the masterVP implementation. Instead of being a special version
|
|
seanhalle@272
|
39 * of a proto-runtime virtual processor, using the slaveVP stuct, the
|
|
seanhalle@272
|
40 * Master "virtual processor" is now implemented as a pthread pinned to
|
|
seanhalle@272
|
41 * a physical core.
|
|
seanhalle@260
|
42 */
|
|
seanhalle@260
|
43
|
|
seanhalle@272
|
44 /*This is the behavior of the Master. The physical processor switches
|
|
seanhalle@272
|
45 * between animating the master, and animating a slave. When a slave
|
|
seanhalle@272
|
46 * suspends, the PR "suspend" primitive switches the physical core over
|
|
seanhalle@272
|
47 * to animating the masterVP, which is implemented as a pinned pthread.
|
|
seanhalle@272
|
48 * This function is the behavior of that masterVP.
|
|
seanhalle@272
|
49 *This function's job is to manage processing
|
|
seanhalle@272
|
50 * requests and to trigger assignment of new work to the physical core,
|
|
seanhalle@272
|
51 * and to manage sharing the core among processes.
|
|
seanhalle@272
|
52 */
|
|
seanhalle@261
|
53 inline
|
|
seanhalle@270
|
54 bool32
|
|
seanhalle@269
|
55 masterFunction( AnimSlot *slot )
|
|
seanhalle@261
|
56 { //Scan the animation slots
|
|
seanhalle@261
|
57 int32 magicNumber;
|
|
seanhalle@261
|
58 SlaveVP *slave;
|
|
seanhalle@268
|
59 PRLangEnv *langEnv;
|
|
seanhalle@261
|
60 PRReqst *req;
|
|
seanhalle@268
|
61 PRProcess *process;
|
|
seanhalle@270
|
62 bool32 foundWork;
|
|
seanhalle@260
|
63
|
|
seanhalle@268
|
64 //Check if newly-done slave in slot, which will need request handled
|
|
seanhalle@272
|
65 //NOTE: left over from when had a coreController & MasterVP managed
|
|
seanhalle@272
|
66 // several slots
|
|
seanhalle@268
|
67 if( slot->workIsDone )
|
|
seanhalle@268
|
68 { slot->workIsDone = FALSE;
|
|
seanhalle@268
|
69 slot->needsWorkAssigned = TRUE;
|
|
seanhalle@261
|
70
|
|
seanhalle@268
|
71 HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot
|
|
seanhalle@268
|
72 MEAS__startReqHdlr;
|
|
seanhalle@261
|
73
|
|
seanhalle@268
|
74
|
|
seanhalle@268
|
75 //process the request made by the slave (held inside slave struc)
|
|
seanhalle@268
|
76 slave = slot->slaveAssignedToSlot;
|
|
seanhalle@268
|
77 req = slave->request;
|
|
seanhalle@268
|
78
|
|
seanhalle@268
|
79 //If the requesting slave is a slot slave, and request is not
|
|
seanhalle@268
|
80 // task-end, then turn it into a free task slave.
|
|
seanhalle@268
|
81 if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd )
|
|
seanhalle@268
|
82 PR_int__replace_with_new_slot_slv( slave );
|
|
seanhalle@268
|
83
|
|
seanhalle@268
|
84 //Handle task create and end first -- they're special cases..
|
|
seanhalle@268
|
85 switch( req->reqType )
|
|
seanhalle@268
|
86 { case TaskEnd:
|
|
seanhalle@268
|
87 { //do PR handler, which calls lang's hdlr and does recycle of
|
|
seanhalle@268
|
88 // free task slave if needed -- PR handler checks for free task Slv
|
|
seanhalle@272
|
89 PRHandle__EndTask( req, slave ); break;
|
|
seanhalle@267
|
90 }
|
|
seanhalle@268
|
91 case TaskCreate:
|
|
seanhalle@268
|
92 { //Do PR's create-task handler, which calls the lang's hdlr
|
|
seanhalle@268
|
93 // PR handler checks for free task Slv
|
|
seanhalle@272
|
94 PRHandle__CreateTask( req, slave ); break;
|
|
seanhalle@268
|
95 }
|
|
seanhalle@272
|
96 case SlvCreate: PRHandle__CreateSlave( req, slave ); break;
|
|
seanhalle@272
|
97 case SlvDissipate: PRHandle__EndSlave( req, slave ); break;
|
|
seanhalle@272
|
98 case Service: PRHandle__ServiceReq( slave ); break; //resumes into Service lang env
|
|
seanhalle@268
|
99 case Hardware: //for future expansion
|
|
seanhalle@268
|
100 case IO: //for future expansion
|
|
seanhalle@268
|
101 case OSCall: //for future expansion
|
|
seanhalle@268
|
102 PR_int__throw_exception("Not implemented", slave, NULL); break;
|
|
seanhalle@268
|
103 case Language: //normal lang request
|
|
seanhalle@268
|
104 { magicNumber = req->langMagicNumber;
|
|
seanhalle@268
|
105 langEnv = PR_PI__give_lang_env_for( slave, magicNumber );
|
|
seanhalle@268
|
106 (*req->handler)( req->langReq, slave, langEnv );
|
|
seanhalle@268
|
107 }
|
|
seanhalle@268
|
108 }
|
|
seanhalle@261
|
109
|
|
seanhalle@268
|
110 MEAS__endReqHdlr;
|
|
seanhalle@267
|
111 HOLISTIC__Record_AppResponder_end;
|
|
seanhalle@268
|
112 } //if have request to be handled
|
|
seanhalle@268
|
113
|
|
seanhalle@272
|
114 //NOTE: IF statement is leftover from when master managed many slots
|
|
seanhalle@272
|
115 foundWork = FALSE;
|
|
seanhalle@272
|
116 if( slot->needsWorkAssigned ) //can probably remove IF, not that only one slot
|
|
seanhalle@268
|
117 {
|
|
seanhalle@268
|
118 HOLISTIC__Record_Assigner_start;
|
|
seanhalle@272
|
119
|
|
seanhalle@268
|
120 //Pick a process to get this slot
|
|
seanhalle@268
|
121 process = pickAProcess( slot );
|
|
seanhalle@268
|
122
|
|
seanhalle@268
|
123 //Scan lang environs, looking for langEnv with ready work.
|
|
seanhalle@268
|
124 // call the Assigner for that lang Env, to get a slave for the slot
|
|
seanhalle@270
|
125 foundWork =
|
|
seanhalle@268
|
126 assignWork( process, slot );
|
|
seanhalle@268
|
127
|
|
seanhalle@268
|
128 HOLISTIC__Record_Assigner_end;
|
|
seanhalle@272
|
129
|
|
seanhalle@272
|
130 // fixme; //make this a while loop that tries a different process if this one fails
|
|
seanhalle@268
|
131 }//if slot needs slave assigned
|
|
seanhalle@270
|
132
|
|
seanhalle@270
|
133 return foundWork;
|
|
seanhalle@261
|
134 }
|
|
seanhalle@260
|
135
|
|
seanhalle@268
|
136 /*When several processes exist, use some pattern for picking one to give
|
|
seanhalle@268
|
137 * the animation slot to.
|
|
seanhalle@268
|
138 *First, it has to be a process that has work available.
|
|
seanhalle@268
|
139 *For now, just do a round-robin
|
|
seanhalle@261
|
140 */
|
|
seanhalle@268
|
141 inline
|
|
seanhalle@268
|
142 PRProcess *
|
|
seanhalle@268
|
143 pickAProcess( AnimSlot *slot )
|
|
seanhalle@268
|
144 { int32 idx;
|
|
seanhalle@268
|
145 PRProcess *process;
|
|
seanhalle@268
|
146
|
|
seanhalle@268
|
147 for( idx = _PRTopEnv->currProcessIdx; idx < _PRTopEnv->numProcesses; idx++)
|
|
seanhalle@268
|
148 {
|
|
seanhalle@268
|
149 process = _PRTopEnv->processes[ idx ];
|
|
seanhalle@268
|
150 if( process->numEnvsWithWork != 0 )
|
|
seanhalle@268
|
151 { _PRTopEnv->currProcessIdx = idx;
|
|
seanhalle@268
|
152 return process;
|
|
seanhalle@268
|
153 }
|
|
seanhalle@261
|
154 }
|
|
seanhalle@268
|
155 for( idx = 0; idx < _PRTopEnv->currProcessIdx; idx++)
|
|
seanhalle@268
|
156 {
|
|
seanhalle@268
|
157 process = _PRTopEnv->processes[ idx ];
|
|
seanhalle@268
|
158 if( process->numEnvsWithWork != 0 )
|
|
seanhalle@268
|
159 { _PRTopEnv->currProcessIdx = idx;
|
|
seanhalle@268
|
160 return process;
|
|
seanhalle@268
|
161 }
|
|
seanhalle@268
|
162 }
|
|
seanhalle@268
|
163 //none found
|
|
seanhalle@268
|
164 return NULL;
|
|
seanhalle@260
|
165 }
|
|
seanhalle@260
|
166
|
|
seanhalle@261
|
167 /*This does:
|
|
seanhalle@268
|
168 * 1) searches the language environments for one with work ready
|
|
seanhalle@261
|
169 * if finds one, asks its assigner to return work
|
|
seanhalle@261
|
170 * 2) checks what kind of work: new task, resuming task, resuming slave
|
|
seanhalle@261
|
171 * if new task, gets the slot slave and assigns task to it and returns slave
|
|
seanhalle@261
|
172 * else, gets the slave attached to the metaTask and returns that.
|
|
seanhalle@261
|
173 * 3) if no work found, then prune former task slaves waiting to be recycled.
|
|
seanhalle@261
|
174 * If no work and no slaves to prune, check for shutdown conditions.
|
|
seanhalle@261
|
175 *
|
|
seanhalle@268
|
176 * language env keeps its own work in its own structures, and has its own
|
|
seanhalle@261
|
177 * assigner. It chooses
|
|
seanhalle@261
|
178 * However, include a switch that switches-in an override assigner, which
|
|
seanhalle@268
|
179 * sees all the work in all the language env's. This is most likely
|
|
seanhalle@261
|
180 * generated by static tools and included in the executable. That means it
|
|
seanhalle@261
|
181 * has to be called via a registered pointer from here. The idea is that
|
|
seanhalle@261
|
182 * the static tools know which languages are grouped together.. and the
|
|
seanhalle@261
|
183 * override enables them to generate a custom assigner that uses info from
|
|
seanhalle@261
|
184 * all the languages in a unified way.. Don't really expect this to happen,
|
|
seanhalle@261
|
185 * but am making it possible.
|
|
seanhalle@260
|
186 */
|
|
seanhalle@268
|
187 inline
|
|
seanhalle@270
|
188 bool32
|
|
seanhalle@261
|
189 assignWork( PRProcess *process, AnimSlot *slot )
|
|
seanhalle@272
|
190 { int32 coreNum;
|
|
seanhalle@260
|
191
|
|
seanhalle@261
|
192 coreNum = slot->coreSlotIsOn;
|
|
seanhalle@260
|
193
|
|
seanhalle@267
|
194 if( process->overrideAssigner != NULL )
|
|
seanhalle@268
|
195 { if( process->numEnvsWithWork != 0 )
|
|
seanhalle@268
|
196 { (*process->overrideAssigner)( process, slot ); //calls PR fn that inserts work into slot
|
|
seanhalle@268
|
197 goto ReturnAfterAssigningWork; //quit for-loop, cause found work
|
|
seanhalle@261
|
198 }
|
|
seanhalle@268
|
199 else
|
|
seanhalle@261
|
200 goto NoWork;
|
|
seanhalle@261
|
201 }
|
|
seanhalle@261
|
202
|
|
seanhalle@268
|
203 //If here, then no override assigner, so search language envs for work
|
|
seanhalle@268
|
204 int32 envIdx, numEnvs; PRLangEnv **langEnvsList, *langEnv;
|
|
seanhalle@268
|
205 langEnvsList = process->langEnvsList;
|
|
seanhalle@268
|
206 numEnvs = process->numLangEnvs;
|
|
seanhalle@268
|
207 for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep langEnvs in hash & array
|
|
seanhalle@268
|
208 { langEnv = langEnvsList[envIdx];
|
|
seanhalle@272
|
209 if( langEnv->numReadyWork > 0 )
|
|
seanhalle@272
|
210 { bool32
|
|
seanhalle@272
|
211 didAssignWork =
|
|
seanhalle@272
|
212 (*langEnv->workAssigner)( langEnv, slot ); //assigner calls PR to put slave/task into slot
|
|
seanhalle@272
|
213
|
|
seanhalle@272
|
214 if(didAssignWork)
|
|
seanhalle@272
|
215 { langEnv->numReadyWork -= 1;
|
|
seanhalle@272
|
216 if( langEnv->numReadyWork == 0 )
|
|
seanhalle@272
|
217 { process->numEnvsWithWork -= 1;
|
|
seanhalle@272
|
218 }
|
|
seanhalle@272
|
219 goto ReturnAfterAssigningWork; //quit for-loop, 'cause found work
|
|
seanhalle@272
|
220 }
|
|
seanhalle@272
|
221 else
|
|
seanhalle@272
|
222 goto NoWork; //quit for-loop, cause found work
|
|
seanhalle@272
|
223
|
|
seanhalle@268
|
224 //NOTE: bad search alg -- should start where left off, then wrap around
|
|
seanhalle@260
|
225 }
|
|
seanhalle@260
|
226 }
|
|
seanhalle@268
|
227 //If reach here, then have searched all langEnv's & none have work..
|
|
seanhalle@260
|
228
|
|
seanhalle@268
|
229 NoWork: //No work, if end up here..
|
|
seanhalle@260
|
230 {
|
|
seanhalle@260
|
231 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
|
|
seanhalle@272
|
232 returnSlv = process->idleSlv[coreNum][0]; //only one slot now, so [0]
|
|
seanhalle@260
|
233
|
|
seanhalle@260
|
234 //things that would normally happen in resume(), but idle VPs
|
|
seanhalle@260
|
235 // never go there
|
|
seanhalle@261
|
236 returnSlv->numTimesAssignedToASlot++; //gives each idle unit a unique ID
|
|
seanhalle@260
|
237 Unit newU;
|
|
seanhalle@268
|
238 newU.vp = returnSlv->slaveNum;
|
|
seanhalle@261
|
239 newU.task = returnSlv->numTimesAssignedToASlot;
|
|
seanhalle@261
|
240 addToListOfArrays(Unit,newU,process->unitList);
|
|
seanhalle@260
|
241
|
|
seanhalle@261
|
242 if (returnSlv->numTimesAssignedToASlot > 1) //make a dependency from prev idle unit
|
|
seanhalle@260
|
243 { Dependency newD; // to this one
|
|
seanhalle@268
|
244 newD.from_vp = returnSlv->slaveNum;
|
|
seanhalle@261
|
245 newD.from_task = returnSlv->numTimesAssignedToASlot - 1;
|
|
seanhalle@268
|
246 newD.to_vp = returnSlv->slaveNum;
|
|
seanhalle@261
|
247 newD.to_task = returnSlv->numTimesAssignedToASlot;
|
|
seanhalle@261
|
248 addToListOfArrays(Dependency, newD ,process->ctlDependenciesList);
|
|
seanhalle@260
|
249 }
|
|
seanhalle@268
|
250 #endif
|
|
seanhalle@268
|
251 HOLISTIC__Record_Assigner_end;
|
|
seanhalle@269
|
252 return FALSE;
|
|
seanhalle@260
|
253 }
|
|
seanhalle@268
|
254
|
|
seanhalle@268
|
255 ReturnAfterAssigningWork: //All paths goto here.. to provide single point for holistic..
|
|
seanhalle@268
|
256 {
|
|
seanhalle@268
|
257 HOLISTIC__Record_Assigner_end;
|
|
seanhalle@269
|
258 return TRUE;
|
|
seanhalle@260
|
259 }
|
|
seanhalle@260
|
260 }
|
|
seanhalle@260
|
261
|
|
seanhalle@260
|
262
|
|
seanhalle@268
|
263
|
|
seanhalle@268
|
264 /*This is first thing called when creating a slave.. it hands off to the
|
|
seanhalle@268
|
265 * langlet's creator, then adds updates of its own..
|
|
seanhalle@268
|
266 *
|
|
seanhalle@268
|
267 *There's a question of things like lang data, meta tasks, and such..
|
|
seanhalle@268
|
268 *In creator, only PR related things happen, and things for the langlet whose
|
|
seanhalle@261
|
269 * creator construct was used.
|
|
seanhalle@268
|
270 *
|
|
seanhalle@268
|
271 *Other langlets still get a chance to create langData -- but by registering a
|
|
seanhalle@268
|
272 * "createLangData" handler in the langEnv. When a construct of the langlet
|
|
seanhalle@268
|
273 * calls "PR__give_lang_data()", if there is no langData for that langlet,
|
|
seanhalle@268
|
274 * the PR will call the creator in the langlet's langEnv, place whatever it
|
|
seanhalle@268
|
275 * makes as the langData in that slave for that langlet, and return that langData
|
|
seanhalle@261
|
276 *
|
|
seanhalle@261
|
277 *So, as far as counting things, a langlet is only allowed to count creation
|
|
seanhalle@261
|
278 * of slaves it creates itself.. may have to change this later.. add a way for
|
|
seanhalle@261
|
279 * langlet to register a trigger Fn called each time a slave gets created..
|
|
seanhalle@261
|
280 * need more experience with what langlets will do at create time.. think Cilk
|
|
seanhalle@261
|
281 * has interesting create behavior.. not sure how that will differ in light
|
|
seanhalle@261
|
282 * of true tasks and langlet approach. Look at it after all done and start
|
|
seanhalle@261
|
283 * modifying the langs to be langlets..
|
|
seanhalle@261
|
284 *
|
|
seanhalle@261
|
285 *PR itself needs to create the slave, then update numLiveSlaves in process,
|
|
seanhalle@261
|
286 * copy processID from requestor to newly created
|
|
seanhalle@261
|
287 */
|
|
seanhalle@268
|
288 inline
|
|
seanhalle@268
|
289 void
|
|
seanhalle@272
|
290 PRHandle__CreateSlave( PRReqst *req, SlaveVP *slave )
|
|
seanhalle@268
|
291 { SlaveVP *newSlv;
|
|
seanhalle@261
|
292 PRProcess *process;
|
|
seanhalle@268
|
293 PRLangEnv *protoLangEnv;
|
|
seanhalle@261
|
294
|
|
seanhalle@268
|
295 process = slave->processSlaveIsIn;
|
|
seanhalle@268
|
296 protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, req->langMagicNumber );
|
|
seanhalle@272
|
297
|
|
seanhalle@272
|
298 //create handler, or a future request handler will call PR_PI__make_slave_ready
|
|
seanhalle@272
|
299 // which will in turn handle updating which langlets and which processes have
|
|
seanhalle@272
|
300 // work available.
|
|
seanhalle@272
|
301 //NOTE: create slv has diff prototype than standard reqst hdlr
|
|
seanhalle@268
|
302 newSlv =
|
|
seanhalle@268
|
303 (*req->createHdlr)(req->langReq, slave, PR_int__give_lang_env(protoLangEnv));
|
|
seanhalle@268
|
304
|
|
seanhalle@261
|
305 newSlv->typeOfVP = GenericSlv;
|
|
seanhalle@261
|
306 newSlv->processSlaveIsIn = process;
|
|
seanhalle@268
|
307 newSlv->ID = req->ID;
|
|
seanhalle@272
|
308 process->numLiveGenericSlvs += 1; //not same as work ready!
|
|
seanhalle@260
|
309 }
|
|
seanhalle@260
|
310
|
|
seanhalle@268
|
311 /*The dissipate handler has to, update the number of slaves of the type, within
|
|
seanhalle@261
|
312 * the process, and call the langlet handler linked into the request,
|
|
seanhalle@261
|
313 * and after that returns, then call the PR function that frees the slave state
|
|
seanhalle@261
|
314 * (or recycles the slave).
|
|
seanhalle@261
|
315 *
|
|
seanhalle@261
|
316 *The PR function that frees the slave state has to also free all of the
|
|
seanhalle@268
|
317 * langData in the slave.. or else reset all of the langDatas.. by, say, marking
|
|
seanhalle@268
|
318 * them, then in PR__give_langData( magicNum ) call the langlet registered
|
|
seanhalle@268
|
319 * "resetLangData" Fn.
|
|
seanhalle@261
|
320 */
|
|
seanhalle@268
|
321 inline
|
|
seanhalle@268
|
322 void
|
|
seanhalle@272
|
323 PRHandle__EndSlave( PRReqst *req, SlaveVP *slave )
|
|
seanhalle@261
|
324 { PRProcess *process;
|
|
seanhalle@268
|
325 PRLangEnv *protoLangEnv;
|
|
seanhalle@261
|
326
|
|
seanhalle@261
|
327 process = slave->processSlaveIsIn;
|
|
seanhalle@261
|
328
|
|
seanhalle@261
|
329 //do the language's dissipate handler
|
|
seanhalle@268
|
330 protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, slave->request->langMagicNumber );
|
|
seanhalle@268
|
331
|
|
seanhalle@268
|
332 if(req->handler != NULL)
|
|
seanhalle@268
|
333 (*req->handler)( req->langReq, slave, PR_int__give_lang_env(protoLangEnv) );
|
|
seanhalle@261
|
334
|
|
seanhalle@272
|
335 process->numLiveGenericSlvs -= 1;
|
|
seanhalle@272
|
336 PR_int__recycle_slave( slave );
|
|
seanhalle@272
|
337 //NOTE: dissipate is unrelated to work available (just in case wondering)
|
|
seanhalle@272
|
338
|
|
seanhalle@261
|
339 //check End Of Process Condition
|
|
seanhalle@261
|
340 if( process->numLiveTasks == 0 &&
|
|
seanhalle@266
|
341 process->numLiveGenericSlvs == 0 )
|
|
seanhalle@272
|
342 PR_SS__shutdown_process( process );
|
|
seanhalle@261
|
343 }
|
|
seanhalle@261
|
344
|
|
seanhalle@261
|
345 /*Create task is a special form, that has PR behavior in addition to plugin
|
|
seanhalle@268
|
346 * behavior. Master calls this first, and it then calls the plugin's
|
|
seanhalle@261
|
347 * create task handler.
|
|
seanhalle@267
|
348 *
|
|
seanhalle@267
|
349 *Note: the requesting slave must be either generic slave or free task slave
|
|
seanhalle@261
|
350 */
|
|
seanhalle@268
|
351 inline
|
|
seanhalle@268
|
352 void
|
|
seanhalle@272
|
353 PRHandle__CreateTask( PRReqst *req, SlaveVP *slave )
|
|
seanhalle@267
|
354 { PRMetaTask *metaTask;
|
|
seanhalle@267
|
355 PRProcess *process;
|
|
seanhalle@268
|
356 PRLangEnv *protoLangEnv;
|
|
seanhalle@268
|
357 void *task;
|
|
seanhalle@267
|
358
|
|
seanhalle@268
|
359 process = slave->processSlaveIsIn;
|
|
seanhalle@268
|
360
|
|
seanhalle@268
|
361 protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave,
|
|
seanhalle@268
|
362 req->langMagicNumber );
|
|
seanhalle@268
|
363
|
|
seanhalle@268
|
364 //Do the langlet's create-task handler, which keeps the task
|
|
seanhalle@268
|
365 // inside the langlet's lang env, but returns the langMetaTask
|
|
seanhalle@268
|
366 // so PR can put stuff into the prolog
|
|
seanhalle@268
|
367 task =
|
|
seanhalle@268
|
368 (*req->createHdlr)(req->langReq, slave, PR_int__give_lang_env(protoLangEnv) );
|
|
seanhalle@268
|
369 metaTask = PR_int__give_prolog_of_task( task );
|
|
seanhalle@268
|
370 metaTask->ID = req->ID; //may be NULL
|
|
seanhalle@267
|
371 metaTask->topLevelFn = req->topLevelFn;
|
|
seanhalle@267
|
372 metaTask->initData = req->initData;
|
|
seanhalle@261
|
373
|
|
seanhalle@261
|
374 process->numLiveTasks += 1;
|
|
seanhalle@267
|
375
|
|
seanhalle@261
|
376 return;
|
|
seanhalle@261
|
377 }
|
|
seanhalle@261
|
378
|
|
seanhalle@272
|
379 /*When a task ends, have two scenarios: 1) task ran to completion, or 2) task
|
|
seanhalle@272
|
380 * has been suspended at some point in its code.
|
|
seanhalle@261
|
381 *For 1, just decr count of live tasks (and check for end condition) -- the
|
|
seanhalle@261
|
382 * master loop will decide what goes into the slot freed up by this task end,
|
|
seanhalle@261
|
383 * so, here, don't worry about assigning a new task to the slot slave.
|
|
seanhalle@261
|
384 *For 2, the task's slot slave has been converted to a free task slave, which
|
|
seanhalle@261
|
385 * now has nothing more to do, so send it to the recycle Q (which includes
|
|
seanhalle@268
|
386 * freeing all the langData and meta task structs alloc'd for it). Then
|
|
seanhalle@261
|
387 * decrement the live task count and check end condition.
|
|
seanhalle@261
|
388 *
|
|
seanhalle@261
|
389 *PR has to update count of live tasks, and check end of process condition.
|
|
seanhalle@267
|
390 * The "main" can invoke constructs that wait for a process to end, so when
|
|
seanhalle@267
|
391 * end detected, have to resume what's waiting..
|
|
seanhalle@267
|
392 *Thing is, that wait involves the main OS thread. That means
|
|
seanhalle@261
|
393 * PR internals have to do OS thread signaling. Want to do that in the
|
|
seanhalle@267
|
394 * core controller, which has the original stack of an OS thread. So the
|
|
seanhalle@267
|
395 * end process handling happens in the core controller.
|
|
seanhalle@261
|
396 *
|
|
seanhalle@261
|
397 *So here, when detect process end, signal to the core controller, which will
|
|
seanhalle@267
|
398 * then do the condition variable notify to the OS thread that's waiting.
|
|
seanhalle@267
|
399 *
|
|
seanhalle@267
|
400 *Note: slave may be either a slot slave or a free task slave.
|
|
seanhalle@261
|
401 */
|
|
seanhalle@268
|
402 inline
|
|
seanhalle@268
|
403 void
|
|
seanhalle@272
|
404 PRHandle__EndTask( PRReqst *req, SlaveVP *requestingSlv )
|
|
seanhalle@268
|
405 { void *langEnv;
|
|
seanhalle@261
|
406 PRProcess *process;
|
|
seanhalle@268
|
407 void *langMetaTask;
|
|
seanhalle@267
|
408
|
|
seanhalle@272
|
409 langEnv = PR_int__give_lang_env_of_req( req, requestingSlv ); //magic num in req
|
|
seanhalle@272
|
410 langMetaTask = PR_int__give_lang_meta_task_from_slave( requestingSlv, req->langMagicNumber);
|
|
seanhalle@261
|
411
|
|
seanhalle@267
|
412 //Do the langlet's request handler
|
|
seanhalle@268
|
413 //Want to keep PR structs hidden from plugin, so extract langReq..
|
|
seanhalle@268
|
414 (*req->handler)( req->langReq, requestingSlv, langEnv );
|
|
seanhalle@267
|
415
|
|
seanhalle@267
|
416 //Now that the langlet's done with it, recycle the slave if it's a freeTaskSlv
|
|
seanhalle@267
|
417 if( requestingSlv->typeOfVP == FreeTaskSlv )
|
|
seanhalle@272
|
418 PR_int__recycle_slave( requestingSlv ); //Doesn't decr num live slaves
|
|
seanhalle@261
|
419
|
|
seanhalle@261
|
420 process->numLiveTasks -= 1;
|
|
seanhalle@272
|
421 //NOTE: end-task is unrelated to work available (just in case wondering)
|
|
seanhalle@261
|
422
|
|
seanhalle@261
|
423 //check End Of Process Condition
|
|
seanhalle@261
|
424 if( process->numLiveTasks == 0 &&
|
|
seanhalle@266
|
425 process->numLiveGenericSlvs == 0 )
|
|
seanhalle@268
|
426 { //Tell the core controller to do wakeup of any waiting OS thread
|
|
seanhalle@272
|
427 PR_SS__shutdown_process( process );
|
|
seanhalle@268
|
428 }
|
|
seanhalle@261
|
429 }
|
|
seanhalle@261
|
430
|
|
seanhalle@272
|
431
|
|
seanhalle@272
|
432 /*This is for OS requests and PR infrastructure requests, which are not
|
|
seanhalle@272
|
433 * part of the PRServ language -- this is for things that have to be in the
|
|
seanhalle@272
|
434 * infrastructure of PR itself, such as I/O requests, which have to go through
|
|
seanhalle@272
|
435 * pthreads inside the core controller..
|
|
seanhalle@272
|
436 *
|
|
seanhalle@272
|
437 *As of Jan 2013, doesn't do much of anything..
|
|
seanhalle@272
|
438 */
|
|
seanhalle@272
|
439 void inline
|
|
seanhalle@272
|
440 PRHandle__ServiceReq( SlaveVP *requestingSlv )
|
|
seanhalle@272
|
441 { PRReqst *req;
|
|
seanhalle@272
|
442 PRServReq *langReq;
|
|
seanhalle@272
|
443 void *langEnv;
|
|
seanhalle@272
|
444 int32 magicNumber;
|
|
seanhalle@272
|
445
|
|
seanhalle@272
|
446
|
|
seanhalle@272
|
447 req = requestingSlv->request;
|
|
seanhalle@272
|
448
|
|
seanhalle@272
|
449 magicNumber = req->langMagicNumber;
|
|
seanhalle@272
|
450 langEnv = PR_PI__give_lang_env_for( slave, magicNumber );
|
|
seanhalle@272
|
451
|
|
seanhalle@272
|
452 langReq = PR_PI__take_lang_reqst_from(req);
|
|
seanhalle@272
|
453 if( langReq == NULL ) return;
|
|
seanhalle@272
|
454 switch( langReq->reqType ) //lang handlers are all in other file
|
|
seanhalle@272
|
455 {
|
|
seanhalle@272
|
456 case make_probe: handleMakeProbe( langReq, langEnv );
|
|
seanhalle@272
|
457 break;
|
|
seanhalle@272
|
458 case throw_excp: handleThrowException( langReq, langEnv );
|
|
seanhalle@272
|
459 break;
|
|
seanhalle@272
|
460 }
|
|
seanhalle@272
|
461 }
|