comparison AnimationMaster.c @ 273:40e7625e57bd

Compiles and runs, up to end of process, working on end process and shutdown
author Sean Halle <seanhalle@yahoo.com>
date Sat, 02 Mar 2013 09:43:45 -0800
parents bc5030385120
children 1d7ea1b0f176
comparison
equal deleted inserted replaced
17:1f4f559c0919 18:cb4417c0c163
10 #include <stddef.h> 10 #include <stddef.h>
11 11
12 #include "PR.h" 12 #include "PR.h"
13 #include "VSs_impl/VSs.h" 13 #include "VSs_impl/VSs.h"
14 14
15 /* 15 //========================= Local Declarations ========================
16 void PRHandle_CreateTask_SL(SlaveVP *slave); 16 inline PRProcess *
17 17 pickAProcess( AnimSlot *slot );
18 void PRHandle_CreateSlave_SL(SlaveVP *slave); 18 inline bool32
19 void PRHandle_Dissipate_SL(SlaveVP *slave); 19 assignWork( PRProcess *process, AnimSlot *slot );
20 void PR_int__handle_PRServiceReq_SL(SlaveVP *slave); 20
21 */ 21 inline void
22 inline void PRHandle__CreateTask( PRReqst *req, SlaveVP *slave ); 22 PRHandle__CreateTask( PRReqst *req, SlaveVP *slave );
23 inline void PRHandle__EndTask( PRReqst *req, SlaveVP *slave ); 23 inline void
24 inline void PRHandle__CreateSlave(PRReqst *req, SlaveVP *slave ); 24 PRHandle__EndTask( PRReqst *req, SlaveVP *slave );
25 void PRHandle__EndSlave( PRReqst *req, SlaveVP *slave ); 25 inline void
26 26 PRHandle__CreateSlave(PRReqst *req, SlaveVP *slave );
27 27 inline void
28 //inline void masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot ); 28 PRHandle__EndSlave( PRReqst *req, SlaveVP *slave );
29 inline PRProcess * pickAProcess( AnimSlot *slot ); 29
30 inline bool32 assignWork( PRProcess *process, AnimSlot *slot ); 30 inline void
31 31 PRHandle__LangShutdown( PRReqst *req, SlaveVP *requestingSlv );
32
33 inline void
34 handleMakeProbe( PRServiceReq *langReq, PRLangEnv *protoLangEnv );
35 inline void
36 handleThrowException( PRServiceReq *langReq, PRLangEnv *protoLangEnv );
37
38 //===========================================================================
32 39
33 /*Note: there used to be a coreController that was another animation 40 /*Note: there used to be a coreController that was another animation
34 * layer below both the masterVP and the slaveVPs.. in that case, the 41 * layer below both the masterVP and the slaveVPs.. in that case, the
35 * masterVP was a virtual processor whose processor-state was the same 42 * masterVP was a virtual processor whose processor-state was the same
36 * as a slaveVP's processor sate, both implemented as a SlaveVP struct. 43 * as a slaveVP's processor sate, both implemented as a SlaveVP struct.
57 int32 magicNumber; 64 int32 magicNumber;
58 SlaveVP *slave; 65 SlaveVP *slave;
59 PRLangEnv *langEnv; 66 PRLangEnv *langEnv;
60 PRReqst *req; 67 PRReqst *req;
61 PRProcess *process; 68 PRProcess *process;
62 bool32 foundWork; 69 bool32 didAssignWork;
63 70
64 //Check if newly-done slave in slot, which will need request handled 71 //Check if newly-done slave in slot, which will need request handled
65 //NOTE: left over from when had a coreController & MasterVP managed 72 //NOTE: left over from when had a coreController & MasterVP managed
66 // several slots 73 // several slots
67 if( slot->workIsDone ) 74 if( slot->workIsDone )
68 { slot->workIsDone = FALSE; 75 { slot->workIsDone = FALSE;
69 slot->needsWorkAssigned = TRUE; 76 slot->needsWorkAssigned = TRUE;
70 77
71 HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot 78 //An Idle VP has no request to handle, so skip to assign..
72 MEAS__startReqHdlr; 79 if( slot->slaveAssignedToSlot->typeOfVP != IdleVP )
73 80 {
74 81 HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot
75 //process the request made by the slave (held inside slave struc) 82 MEAS__startReqHdlr;
76 slave = slot->slaveAssignedToSlot; 83
77 req = slave->request; 84
78 85 //process the request made by the slave (held inside slave struc)
79 //If the requesting slave is a slot slave, and request is not 86 slave = slot->slaveAssignedToSlot;
80 // task-end, then turn it into a free task slave. 87 req = slave->request;
81 if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd ) 88
82 PR_int__replace_with_new_slot_slv( slave ); 89 //If the requesting slave is a slot slave, and request is not
83 90 // task-end, then turn it into a free task slave & continue
84 //Handle task create and end first -- they're special cases.. 91 if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd )
85 switch( req->reqType ) 92 PR_int__replace_with_new_slot_slv( slave );
86 { case TaskEnd: 93
87 { //do PR handler, which calls lang's hdlr and does recycle of 94 //Handle task create and end first -- they're special cases..
88 // free task slave if needed -- PR handler checks for free task Slv 95 switch( req->reqType )
89 PRHandle__EndTask( req, slave ); break; 96 { case TaskEnd:
97 { //do PR handler, which calls lang's hdlr and does recycle of
98 // free task slave if needed -- PR handler checks for free task Slv
99 PRHandle__EndTask( req, slave ); break;
100 }
101 case TaskCreate:
102 { //Do PR's create-task handler, which calls the lang's hdlr
103 // PR handler checks for free task Slv
104 PRHandle__CreateTask( req, slave ); break;
105 }
106 case SlvCreate: PRHandle__CreateSlave( req, slave ); break;
107 case SlvDissipate: PRHandle__EndSlave( req, slave ); break;
108 case Service: PRHandle__ServiceReq( slave ); break; //resumes into Service lang env
109 case Hardware: //for future expansion
110 case IO: //for future expansion
111 case OSCall: //for future expansion
112 PR_int__throw_exception("Not implemented", slave, NULL); break;
113 case LangShutdown: PRHandle__LangShutdown( req, slave ); break;
114 case Language: //normal lang request
115 { magicNumber = req->langMagicNumber;
116 langEnv = PR_PI__give_lang_env_for_slave( slave, magicNumber );
117 (*req->handler)( req->langReq, slave, langEnv );
118 }
90 } 119 }
91 case TaskCreate: 120
92 { //Do PR's create-task handler, which calls the lang's hdlr
93 // PR handler checks for free task Slv
94 PRHandle__CreateTask( req, slave ); break;
95 }
96 case SlvCreate: PRHandle__CreateSlave( req, slave ); break;
97 case SlvDissipate: PRHandle__EndSlave( req, slave ); break;
98 case Service: PRHandle__ServiceReq( slave ); break; //resumes into Service lang env
99 case Hardware: //for future expansion
100 case IO: //for future expansion
101 case OSCall: //for future expansion
102 PR_int__throw_exception("Not implemented", slave, NULL); break;
103 case Language: //normal lang request
104 { magicNumber = req->langMagicNumber;
105 langEnv = PR_PI__give_lang_env_for( slave, magicNumber );
106 (*req->handler)( req->langReq, slave, langEnv );
107 }
108 }
109
110 MEAS__endReqHdlr; 121 MEAS__endReqHdlr;
111 HOLISTIC__Record_AppResponder_end; 122 HOLISTIC__Record_AppResponder_end;
123 }//if not idleVP
112 } //if have request to be handled 124 } //if have request to be handled
113 125
114 //NOTE: IF statement is leftover from when master managed many slots 126 //NOTE: IF statement is leftover from when master managed many slots
115 foundWork = FALSE; 127 didAssignWork = FALSE;
116 if( slot->needsWorkAssigned ) //can probably remove IF, not that only one slot 128 if( slot->needsWorkAssigned ) //can probably remove IF, now that only one slot
117 { 129 {
118 HOLISTIC__Record_Assigner_start; 130 HOLISTIC__Record_Assigner_start;
119 131
120 //Pick a process to get this slot 132 //Pick a process to get this slot
121 process = pickAProcess( slot ); 133 process = pickAProcess( slot );
122 134
123 //Scan lang environs, looking for langEnv with ready work. 135 //Scan lang environs, looking for langEnv with ready work.
124 // call the Assigner for that lang Env, to get a slave for the slot 136 // call the Assigner for that lang Env, to get a slave for the slot
125 foundWork = 137 if( process != NULL )
126 assignWork( process, slot ); 138 { didAssignWork =
127 139 assignWork( process, slot );
140 }
128 HOLISTIC__Record_Assigner_end; 141 HOLISTIC__Record_Assigner_end;
129 142
130 // fixme; //make this a while loop that tries a different process if this one fails 143 if( !didAssignWork ) //if no work assigned, be sure idle slave is in slot
144 { slot->slaveAssignedToSlot = _PRTopEnv->idleSlv[slot->coreSlotIsOn][0];
145 }
146 // fixme; //make into a loop that tries more processes if fails to assign
131 }//if slot needs slave assigned 147 }//if slot needs slave assigned
132 148
133 return foundWork; 149 return didAssignWork;
134 } 150 }
135 151
136 /*When several processes exist, use some pattern for picking one to give 152 /*When several processes exist, use some pattern for picking one to give
137 * the animation slot to. 153 * the animation slot to.
138 *First, it has to be a process that has work available. 154 *First, it has to be a process that has work available.
199 else 215 else
200 goto NoWork; 216 goto NoWork;
201 } 217 }
202 218
203 //If here, then no override assigner, so search language envs for work 219 //If here, then no override assigner, so search language envs for work
204 int32 envIdx, numEnvs; PRLangEnv **langEnvsList, *langEnv; 220 int32 envIdx, numEnvs; PRLangEnv **protoLangEnvsList, *protoLangEnv;
205 langEnvsList = process->langEnvsList; 221 protoLangEnvsList = process->protoLangEnvsList;
206 numEnvs = process->numLangEnvs; 222 numEnvs = process->numLangEnvs;
207 for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep langEnvs in hash & array 223 for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep langEnvs in hash & array
208 { langEnv = langEnvsList[envIdx]; 224 { protoLangEnv = protoLangEnvsList[envIdx];
209 if( langEnv->numReadyWork > 0 ) 225 if( protoLangEnv->numReadyWork > 0 )
210 { bool32 226 { bool32
211 didAssignWork = 227 didAssignWork =
212 (*langEnv->workAssigner)( langEnv, slot ); //assigner calls PR to put slave/task into slot 228 (*protoLangEnv->workAssigner)( PR_int__give_lang_env(protoLangEnv), slot ); //assigner calls PR to put slave/task into slot
213 229
214 if(didAssignWork) 230 if(didAssignWork)
215 { langEnv->numReadyWork -= 1; 231 { protoLangEnv->numReadyWork -= 1;
216 if( langEnv->numReadyWork == 0 ) 232 if( protoLangEnv->numReadyWork == 0 )
217 { process->numEnvsWithWork -= 1; 233 { process->numEnvsWithWork -= 1;
218 } 234 }
219 goto ReturnAfterAssigningWork; //quit for-loop, 'cause found work 235 goto ReturnAfterAssigningWork; //quit for-loop, 'cause found work
220 } 236 }
221 else 237 else
254 270
255 ReturnAfterAssigningWork: //All paths goto here.. to provide single point for holistic.. 271 ReturnAfterAssigningWork: //All paths goto here.. to provide single point for holistic..
256 { 272 {
257 HOLISTIC__Record_Assigner_end; 273 HOLISTIC__Record_Assigner_end;
258 return TRUE; 274 return TRUE;
275 }
276 }
277
278
279 //=================================
280 //===
281 //=
282 /*Create task is a special form, that has PR behavior in addition to plugin
283 * behavior. Master calls this first, and it then calls the plugin's
284 * create task handler.
285 *
286 *Note: the requesting slave must be either generic slave or free task slave
287 */
288 inline
289 void
290 PRHandle__CreateTask( PRReqst *req, SlaveVP *slave )
291 { PRMetaTask *protoMetaTask;
292 PRProcess *process;
293 PRLangEnv *protoLangEnv;
294 void *task;
295
296 process = slave->processSlaveIsIn;
297
298 protoLangEnv = PR_int__give_proto_lang_env_for_slave( slave,
299 req->langMagicNumber );
300
301 //Do the langlet's create-task handler, which keeps the task
302 // inside the langlet's lang env, but returns the langMetaTask
303 // so that PR can then put stuff into the prolog
304 //typedef void * (*CreateHandler)( void *, SlaveVP *, void * ); //req, slv, langEnv
305 //
306 task =
307 (*req->createHdlr)(req->langReq, slave, PR_int__give_lang_env(protoLangEnv) );
308 protoMetaTask = PR_int__give_prolog_of_lang_meta_task( task );
309 protoMetaTask->ID = req->ID; //may be NULL
310 protoMetaTask->topLevelFn = req->topLevelFn;
311 protoMetaTask->initData = req->initData;
312 protoMetaTask->processTaskIsIn = process;
313
314 process->numLiveTasks += 1;
315 protoLangEnv->numLiveWork += 1; //used in wait statements -- small added overhead
316
317 return;
318 }
319
320 /*When a task ends, have two scenarios: 1) task ran to completion, or 2) task
321 * has been suspended at some point in its code.
322 *For 1, just decr count of live tasks (and check for end condition) -- the
323 * master loop will decide what goes into the slot freed up by this task end,
324 * so, here, don't worry about assigning a new task to the slot slave.
325 *For 2, the task's slot slave has been converted to a free task slave, which
326 * now has nothing more to do, so send it to the recycle Q (which includes
327 * freeing all the langData and meta task structs alloc'd for it). Then
328 * decrement the live task count and check end condition.
329 *
330 *PR has to update count of live tasks, and check end of process condition.
331 * The "main" can invoke constructs that wait for a process to end, so when
332 * end detected, have to resume what's waiting..
333 *Thing is, that wait involves the main OS thread. That means
334 * PR internals have to do OS thread signaling. Want to do that in the
335 * core controller, which has the original stack of an OS thread. So the
336 * end process handling happens in the core controller.
337 *
338 *So here, when detect process end, signal to the core controller, which will
339 * then do the condition variable notify to the OS thread that's waiting.
340 *
341 *Note: slave may be either a slot slave or a free task slave.
342 */
343 inline
344 void
345 PRHandle__EndTask( PRReqst *req, SlaveVP *requestingSlv )
346 { void *langEnv;
347 PRLangEnv *protoLangEnv;
348 PRProcess *process;
349 void *langMetaTask;
350
351 process = requestingSlv->processSlaveIsIn;
352 langEnv = PR_int__give_lang_env_of_req( req, requestingSlv ); //magic num in req
353 protoLangEnv = PR_int__give_proto_lang_env( langEnv );
354
355 langMetaTask = PR_int__give_lang_meta_task_from_slave( requestingSlv, req->langMagicNumber);
356
357 //Do the langlet's request handler
358 //Want to keep PR structs hidden from plugin, so extract langReq..
359 //This is supposed to free any langlet-malloc'd mem, including meta task
360 (*req->handler)( req->langReq, requestingSlv, langEnv );
361
362 protoLangEnv->numLiveWork -= 1; //used in wait statements -- small added overhead
363 if( protoLangEnv->numLiveWork == 0 &&
364 numInPrivQ( protoLangEnv->waitingForWorkToEndQ ) > 0 )
365 { SlaveVP *
366 waitingSlave = readPrivQ( protoLangEnv->waitingForWorkToEndQ );
367 //can't resume into langlet that just ended its last work!
368 // and don't have env that the waiter was created in, so resume
369 // into PRServ env..
370 void *
371 resumeEnv = PR_PI__give_lang_env_from_process( process, PRServ_MAGIC_NUMBER );
372 while( waitingSlave != NULL )
373 { //resume a slave that was waiting for work in this env to finish
374 PR_PI__make_slave_ready( waitingSlave, resumeEnv );
375 //get next waiting slave, repeat..
376 waitingSlave = readPrivQ( protoLangEnv->waitingForWorkToEndQ );
377 }
378 }
379
380
381 //Now that the langlet's done with it, recycle the slave if it's a freeTaskSlv
382 if( requestingSlv->typeOfVP == FreeTaskSlv )
383 PR_int__recycle_slaveVP( requestingSlv ); //Doesn't decr num live slaves
384
385 process->numLiveTasks -= 1;
386 //NOTE: end-task is unrelated to work available (just in case wondering)
387
388 //check End Of Process Condition
389 if( process->numLiveTasks == 0 &&
390 process->numLiveGenericSlvs == 0 )
391 { //Tell the core controller to do wakeup of any waiting OS thread
392 PR_SS__end_process_normally( process );
259 } 393 }
260 } 394 }
261 395
262 396
263 397
291 { SlaveVP *newSlv; 425 { SlaveVP *newSlv;
292 PRProcess *process; 426 PRProcess *process;
293 PRLangEnv *protoLangEnv; 427 PRLangEnv *protoLangEnv;
294 428
295 process = slave->processSlaveIsIn; 429 process = slave->processSlaveIsIn;
296 protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, req->langMagicNumber ); 430 protoLangEnv = PR_int__give_proto_lang_env_for_slave( slave, req->langMagicNumber );
297 431
298 //create handler, or a future request handler will call PR_PI__make_slave_ready 432 //create handler, or a future request handler will call PR_PI__make_slave_ready
299 // which will in turn handle updating which langlets and which processes have 433 // which will in turn handle updating which langlets and which processes have
300 // work available. 434 // work available.
301 //NOTE: create slv has diff prototype than standard reqst hdlr 435 //NOTE: create slv has diff prototype than standard reqst hdlr
304 438
305 newSlv->typeOfVP = GenericSlv; 439 newSlv->typeOfVP = GenericSlv;
306 newSlv->processSlaveIsIn = process; 440 newSlv->processSlaveIsIn = process;
307 newSlv->ID = req->ID; 441 newSlv->ID = req->ID;
308 process->numLiveGenericSlvs += 1; //not same as work ready! 442 process->numLiveGenericSlvs += 1; //not same as work ready!
443 protoLangEnv->numLiveWork += 1; //used in wait statements -- small added overhead
309 } 444 }
310 445
311 /*The dissipate handler has to, update the number of slaves of the type, within 446 /*The dissipate handler has to, update the number of slaves of the type, within
312 * the process, and call the langlet handler linked into the request, 447 * the process, and call the langlet handler linked into the request,
313 * and after that returns, then call the PR function that frees the slave state 448 * and after that returns, then call the PR function that frees the slave state
325 PRLangEnv *protoLangEnv; 460 PRLangEnv *protoLangEnv;
326 461
327 process = slave->processSlaveIsIn; 462 process = slave->processSlaveIsIn;
328 463
329 //do the language's dissipate handler 464 //do the language's dissipate handler
330 protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, slave->request->langMagicNumber ); 465 protoLangEnv = PR_int__give_proto_lang_env_for_slave( slave, slave->request->langMagicNumber );
331 466
332 if(req->handler != NULL) 467 if(req->handler != NULL)
333 (*req->handler)( req->langReq, slave, PR_int__give_lang_env(protoLangEnv) ); 468 (*req->handler)( req->langReq, slave, PR_int__give_lang_env(protoLangEnv) );
334 469
470 protoLangEnv->numLiveWork -= 1; //used in wait statements -- small added overhead
471 if( protoLangEnv->numLiveWork == 0 &&
472 numInPrivQ( protoLangEnv->waitingForWorkToEndQ ) > 0 )
473 { SlaveVP *
474 waitingSlave = readPrivQ( protoLangEnv->waitingForWorkToEndQ );
475 //can't resume into langlet that just ended its last work!
476 // and don't have env that the waiter was created in, so resume
477 // into PRServ env..
478 void *
479 resumeEnv = PR_PI__give_lang_env_from_process( process, PRServ_MAGIC_NUMBER );
480 while( waitingSlave != NULL )
481 { //resume a slave that was waiting for work in this env to finish
482 PR_PI__make_slave_ready( waitingSlave, resumeEnv );
483 //get next waiting slave, repeat..
484 waitingSlave = readPrivQ( protoLangEnv->waitingForWorkToEndQ );
485 }
486 }
487
335 process->numLiveGenericSlvs -= 1; 488 process->numLiveGenericSlvs -= 1;
336 PR_int__recycle_slave( slave ); 489 PR_int__recycle_slaveVP( slave );
337 //NOTE: dissipate is unrelated to work available (just in case wondering) 490 //NOTE: dissipate is unrelated to work available (just in case wondering)
338 491
339 //check End Of Process Condition 492 //check End Of Process Condition
340 if( process->numLiveTasks == 0 && 493 if( process->numLiveTasks == 0 &&
341 process->numLiveGenericSlvs == 0 ) 494 process->numLiveGenericSlvs == 0 )
342 PR_SS__shutdown_process( process ); 495 PR_SS__end_process_normally( process );
343 } 496 }
344 497
345 /*Create task is a special form, that has PR behavior in addition to plugin 498 //=======================
346 * behavior. Master calls this first, and it then calls the plugin's 499 //===
347 * create task handler. 500 //=
348 * 501 /*Langlet shutdown triggers this, which calls the registered shutdown
349 *Note: the requesting slave must be either generic slave or free task slave 502 * handler for the langlet, and removes the lang's env from the process
350 */ 503 */
351 inline 504 inline
352 void 505 void
353 PRHandle__CreateTask( PRReqst *req, SlaveVP *slave ) 506 PRHandle__LangShutdown( PRReqst *req, SlaveVP *requestingSlv )
354 { PRMetaTask *metaTask;
355 PRProcess *process;
356 PRLangEnv *protoLangEnv;
357 void *task;
358
359 process = slave->processSlaveIsIn;
360
361 protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave,
362 req->langMagicNumber );
363
364 //Do the langlet's create-task handler, which keeps the task
365 // inside the langlet's lang env, but returns the langMetaTask
366 // so PR can put stuff into the prolog
367 task =
368 (*req->createHdlr)(req->langReq, slave, PR_int__give_lang_env(protoLangEnv) );
369 metaTask = PR_int__give_prolog_of_task( task );
370 metaTask->ID = req->ID; //may be NULL
371 metaTask->topLevelFn = req->topLevelFn;
372 metaTask->initData = req->initData;
373
374 process->numLiveTasks += 1;
375
376 return;
377 }
378
379 /*When a task ends, have two scenarios: 1) task ran to completion, or 2) task
380 * has been suspended at some point in its code.
381 *For 1, just decr count of live tasks (and check for end condition) -- the
382 * master loop will decide what goes into the slot freed up by this task end,
383 * so, here, don't worry about assigning a new task to the slot slave.
384 *For 2, the task's slot slave has been converted to a free task slave, which
385 * now has nothing more to do, so send it to the recycle Q (which includes
386 * freeing all the langData and meta task structs alloc'd for it). Then
387 * decrement the live task count and check end condition.
388 *
389 *PR has to update count of live tasks, and check end of process condition.
390 * The "main" can invoke constructs that wait for a process to end, so when
391 * end detected, have to resume what's waiting..
392 *Thing is, that wait involves the main OS thread. That means
393 * PR internals have to do OS thread signaling. Want to do that in the
394 * core controller, which has the original stack of an OS thread. So the
395 * end process handling happens in the core controller.
396 *
397 *So here, when detect process end, signal to the core controller, which will
398 * then do the condition variable notify to the OS thread that's waiting.
399 *
400 *Note: slave may be either a slot slave or a free task slave.
401 */
402 inline
403 void
404 PRHandle__EndTask( PRReqst *req, SlaveVP *requestingSlv )
405 { void *langEnv; 507 { void *langEnv;
508 PRLangEnv *protoLangEnv;
406 PRProcess *process; 509 PRProcess *process;
407 void *langMetaTask; 510
408 511 process = requestingSlv->processSlaveIsIn;
409 langEnv = PR_int__give_lang_env_of_req( req, requestingSlv ); //magic num in req 512 protoLangEnv = PR_int__give_proto_lang_env_from_process( process, req->langMagicNumber );
410 langMetaTask = PR_int__give_lang_meta_task_from_slave( requestingSlv, req->langMagicNumber); 513 langEnv = PR_int__give_lang_env( protoLangEnv );
411 514
412 //Do the langlet's request handler 515 //call the langlet's registered handler
413 //Want to keep PR structs hidden from plugin, so extract langReq.. 516 (*protoLangEnv->shutdownHdlr)( langEnv );
414 (*req->handler)( req->langReq, requestingSlv, langEnv ); 517
415 518 PR_int__remove_lang_env_from_process_and_free( langEnv ); //removes from process and frees
416 //Now that the langlet's done with it, recycle the slave if it's a freeTaskSlv
417 if( requestingSlv->typeOfVP == FreeTaskSlv )
418 PR_int__recycle_slave( requestingSlv ); //Doesn't decr num live slaves
419
420 process->numLiveTasks -= 1;
421 //NOTE: end-task is unrelated to work available (just in case wondering)
422
423 //check End Of Process Condition
424 if( process->numLiveTasks == 0 &&
425 process->numLiveGenericSlvs == 0 )
426 { //Tell the core controller to do wakeup of any waiting OS thread
427 PR_SS__shutdown_process( process );
428 }
429 } 519 }
430 520
431 521
432 /*This is for OS requests and PR infrastructure requests, which are not 522 /*This is for OS requests and PR infrastructure requests, which are not
433 * part of the PRServ language -- this is for things that have to be in the 523 * part of the PRServ language -- this is for things that have to be in the
436 * 526 *
437 *As of Jan 2013, doesn't do much of anything.. 527 *As of Jan 2013, doesn't do much of anything..
438 */ 528 */
439 void inline 529 void inline
440 PRHandle__ServiceReq( SlaveVP *requestingSlv ) 530 PRHandle__ServiceReq( SlaveVP *requestingSlv )
441 { PRReqst *req; 531 { PRReqst *req;
442 PRServReq *langReq; 532 PRServiceReq *langReq;
443 void *langEnv; 533 PRLangEnv *protoLangEnv;
444 int32 magicNumber; 534 int32 magicNumber;
445 535
446 536
447 req = requestingSlv->request; 537 req = requestingSlv->request;
448 538
449 magicNumber = req->langMagicNumber; 539 magicNumber = req->langMagicNumber;
450 langEnv = PR_PI__give_lang_env_for( slave, magicNumber ); 540 protoLangEnv = PR_int__give_proto_lang_env_for_slave( requestingSlv, magicNumber );
451 541
452 langReq = PR_PI__take_lang_reqst_from(req); 542 langReq = PR_PI__take_lang_reqst_from(req);
453 if( langReq == NULL ) return; 543 if( langReq == NULL ) return;
454 switch( langReq->reqType ) //lang handlers are all in other file 544 switch( langReq->reqType ) //lang handlers are all in other file
455 { 545 {
456 case make_probe: handleMakeProbe( langReq, langEnv ); 546 case make_probe: handleMakeProbe( langReq, protoLangEnv );
457 break; 547 break;
458 case throw_excp: handleThrowException( langReq, langEnv ); 548 case throw_excp: handleThrowException( langReq, protoLangEnv );
459 break; 549 break;
460 } 550 }
461 } 551 }
552
553
554 /*These handlers are special -- they don't belong to a language, because they
555 * deal with things internal to PR, so put them here..
556 */
557 inline
558 void
559 handleMakeProbe( PRServiceReq *langReq, PRLangEnv *protoLangEnv )
560 { IntervalProbe *newProbe;
561
562 newProbe = PR_int__malloc( sizeof(IntervalProbe) );
563 newProbe->nameStr = PR_int__strDup( langReq->nameStr );
564 newProbe->hist = NULL;
565 newProbe->schedChoiceWasRecorded = FALSE;
566
567 //This runs in masterVP, so no race-condition worries
568 //BUG: move to process
569 newProbe->probeID =
570 addToDynArray( newProbe, _PRTopEnv->dynIntervalProbesInfo );
571
572 langReq->requestingSlv->dataRetFromReq = newProbe;
573
574 (*protoLangEnv->makeSlaveReadyFn)( langReq->requestingSlv, PR_int__give_lang_env(protoLangEnv) );
575 }
576
577 inline
578 void
579 handleThrowException( PRServiceReq *langReq, PRLangEnv *protoLangEnv )
580 {
581 PR_int__throw_exception( langReq->msgStr, langReq->requestingSlv, langReq->exceptionData );
582
583 (*protoLangEnv->makeSlaveReadyFn)( langReq->requestingSlv, PR_int__give_lang_env(protoLangEnv) );
584 }
585