diff 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
line diff
     1.1 --- a/AnimationMaster.c	Tue Feb 05 20:23:27 2013 -0800
     1.2 +++ b/AnimationMaster.c	Sat Mar 02 09:43:45 2013 -0800
     1.3 @@ -12,23 +12,30 @@
     1.4  #include "PR.h"
     1.5  #include "VSs_impl/VSs.h"
     1.6  
     1.7 -/*
     1.8 -void        PRHandle_CreateTask_SL(SlaveVP *slave);
     1.9 +//=========================  Local Declarations  ========================
    1.10 +inline PRProcess * 
    1.11 +pickAProcess( AnimSlot *slot );
    1.12 +inline bool32      
    1.13 +assignWork( PRProcess *process, AnimSlot *slot );
    1.14  
    1.15 -void        PRHandle_CreateSlave_SL(SlaveVP *slave);
    1.16 -void        PRHandle_Dissipate_SL(SlaveVP *slave);
    1.17 -void        PR_int__handle_PRServiceReq_SL(SlaveVP *slave);
    1.18 -*/
    1.19 -inline void PRHandle__CreateTask( PRReqst *req, SlaveVP *slave );
    1.20 -inline void PRHandle__EndTask(    PRReqst *req, SlaveVP *slave );
    1.21 -inline void PRHandle__CreateSlave(PRReqst *req, SlaveVP *slave );
    1.22 -void        PRHandle__EndSlave(  PRReqst *req, SlaveVP *slave );
    1.23 +inline void 
    1.24 +PRHandle__CreateTask( PRReqst *req, SlaveVP *slave );
    1.25 +inline void 
    1.26 +PRHandle__EndTask(    PRReqst *req, SlaveVP *slave );
    1.27 +inline void 
    1.28 +PRHandle__CreateSlave(PRReqst *req, SlaveVP *slave );
    1.29 +inline void        
    1.30 +PRHandle__EndSlave(   PRReqst *req, SlaveVP *slave );
    1.31  
    1.32 +inline void
    1.33 +PRHandle__LangShutdown( PRReqst *req, SlaveVP *requestingSlv );
    1.34  
    1.35 -//inline void  masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot );
    1.36 -inline PRProcess * pickAProcess( AnimSlot *slot );
    1.37 -inline bool32 assignWork( PRProcess *process, AnimSlot *slot );
    1.38 +inline void
    1.39 +handleMakeProbe( PRServiceReq *langReq, PRLangEnv *protoLangEnv );
    1.40 +inline void
    1.41 +handleThrowException( PRServiceReq *langReq, PRLangEnv *protoLangEnv );
    1.42  
    1.43 +//===========================================================================
    1.44  
    1.45  /*Note: there used to be a coreController that was another animation 
    1.46   * layer below both the masterVP and the slaveVPs.. in that case, the
    1.47 @@ -59,7 +66,7 @@
    1.48     PRLangEnv      *langEnv;
    1.49     PRReqst        *req;
    1.50     PRProcess      *process;
    1.51 -   bool32          foundWork;
    1.52 +   bool32          didAssignWork;
    1.53  
    1.54        //Check if newly-done slave in slot, which will need request handled
    1.55        //NOTE: left over from when had a coreController & MasterVP managed
    1.56 @@ -67,53 +74,58 @@
    1.57     if( slot->workIsDone )
    1.58      { slot->workIsDone = FALSE;
    1.59        slot->needsWorkAssigned = TRUE;
    1.60 +      
    1.61 +         //An Idle VP has no request to handle, so skip to assign..
    1.62 +      if( slot->slaveAssignedToSlot->typeOfVP != IdleVP )
    1.63 +       {
    1.64 +               HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot
    1.65 +               MEAS__startReqHdlr;
    1.66  
    1.67 -            HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot
    1.68 -            MEAS__startReqHdlr;
    1.69  
    1.70 +            //process the request made by the slave (held inside slave struc)
    1.71 +         slave = slot->slaveAssignedToSlot;
    1.72 +         req = slave->request;
    1.73  
    1.74 -         //process the request made by the slave (held inside slave struc)
    1.75 -      slave = slot->slaveAssignedToSlot;
    1.76 -      req = slave->request;
    1.77 +            //If the requesting slave is a slot slave, and request is not
    1.78 +            // task-end, then turn it into a free task slave & continue
    1.79 +         if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd )
    1.80 +            PR_int__replace_with_new_slot_slv( slave );
    1.81  
    1.82 -         //If the requesting slave is a slot slave, and request is not
    1.83 -         // task-end, then turn it into a free task slave. 
    1.84 -      if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd )
    1.85 -         PR_int__replace_with_new_slot_slv( slave );
    1.86 -
    1.87 -      //Handle task create and end first -- they're special cases..
    1.88 -      switch( req->reqType )
    1.89 -       { case TaskEnd: 
    1.90 -          { //do PR handler, which calls lang's hdlr and does recycle of
    1.91 -            // free task slave if needed -- PR handler checks for free task Slv
    1.92 -            PRHandle__EndTask( req, slave );                          break;
    1.93 +         //Handle task create and end first -- they're special cases..
    1.94 +         switch( req->reqType )
    1.95 +          { case TaskEnd: 
    1.96 +             { //do PR handler, which calls lang's hdlr and does recycle of
    1.97 +               // free task slave if needed -- PR handler checks for free task Slv
    1.98 +               PRHandle__EndTask( req, slave );                          break;
    1.99 +             }
   1.100 +            case TaskCreate:
   1.101 +             { //Do PR's create-task handler, which calls the lang's hdlr
   1.102 +               // PR handler checks for free task Slv
   1.103 +               PRHandle__CreateTask( req, slave );                       break;
   1.104 +             }
   1.105 +            case SlvCreate:    PRHandle__CreateSlave( req, slave );      break;
   1.106 +            case SlvDissipate: PRHandle__EndSlave( req, slave );         break;
   1.107 +            case Service:      PRHandle__ServiceReq( slave );    break; //resumes into Service lang env
   1.108 +            case Hardware: //for future expansion
   1.109 +            case IO:       //for future expansion
   1.110 +            case OSCall:   //for future expansion
   1.111 +               PR_int__throw_exception("Not implemented", slave, NULL); break;
   1.112 +            case LangShutdown: PRHandle__LangShutdown( req, slave ); break;
   1.113 +            case Language: //normal lang request
   1.114 +             { magicNumber = req->langMagicNumber;
   1.115 +               langEnv = PR_PI__give_lang_env_for_slave( slave, magicNumber );
   1.116 +               (*req->handler)( req->langReq, slave, langEnv );
   1.117 +             }
   1.118            }
   1.119 -         case TaskCreate:
   1.120 -          { //Do PR's create-task handler, which calls the lang's hdlr
   1.121 -            // PR handler checks for free task Slv
   1.122 -            PRHandle__CreateTask( req, slave );                       break;
   1.123 -          }
   1.124 -         case SlvCreate:    PRHandle__CreateSlave( req, slave );      break;
   1.125 -         case SlvDissipate: PRHandle__EndSlave( req, slave );         break;
   1.126 -         case Service:      PRHandle__ServiceReq( slave );    break; //resumes into Service lang env
   1.127 -         case Hardware: //for future expansion
   1.128 -         case IO:       //for future expansion
   1.129 -         case OSCall:   //for future expansion
   1.130 -            PR_int__throw_exception("Not implemented", slave, NULL); break;
   1.131 -         case Language: //normal lang request
   1.132 -          { magicNumber = req->langMagicNumber;
   1.133 -            langEnv = PR_PI__give_lang_env_for( slave, magicNumber );
   1.134 -            (*req->handler)( req->langReq, slave, langEnv );
   1.135 -          }
   1.136 -       }
   1.137 -
   1.138 +      
   1.139             MEAS__endReqHdlr;          
   1.140             HOLISTIC__Record_AppResponder_end;
   1.141 +       }//if not idleVP
   1.142      } //if have request to be handled
   1.143  
   1.144        //NOTE: IF statement is leftover from when master managed many slots
   1.145 -   foundWork = FALSE;
   1.146 -   if( slot->needsWorkAssigned ) //can probably remove IF, not that only one slot
   1.147 +   didAssignWork = FALSE;
   1.148 +   if( slot->needsWorkAssigned ) //can probably remove IF, now that only one slot
   1.149      {
   1.150              HOLISTIC__Record_Assigner_start;
   1.151        
   1.152 @@ -122,15 +134,19 @@
   1.153  
   1.154           //Scan lang environs, looking for langEnv with ready work.
   1.155           // call the Assigner for that lang Env, to get a slave for the slot
   1.156 -      foundWork =
   1.157 -      assignWork( process, slot );
   1.158 -
   1.159 +      if( process != NULL )
   1.160 +       { didAssignWork =
   1.161 +           assignWork( process, slot );
   1.162 +       }
   1.163              HOLISTIC__Record_Assigner_end;
   1.164  
   1.165 -//      fixme; //make this a while loop that tries a different process if this one fails
   1.166 +      if( !didAssignWork ) //if no work assigned, be sure idle slave is in slot
   1.167 +       { slot->slaveAssignedToSlot = _PRTopEnv->idleSlv[slot->coreSlotIsOn][0];
   1.168 +       }
   1.169 +//      fixme; //make into a loop that tries more processes if fails to assign
   1.170      }//if slot needs slave assigned
   1.171     
   1.172 -   return foundWork;
   1.173 +   return didAssignWork;
   1.174   }
   1.175  
   1.176  /*When several processes exist, use some pattern for picking one to give
   1.177 @@ -201,19 +217,19 @@
   1.178      }
   1.179     
   1.180        //If here, then no override assigner, so search language envs for work
   1.181 -   int32 envIdx, numEnvs; PRLangEnv **langEnvsList, *langEnv;
   1.182 -   langEnvsList = process->langEnvsList;
   1.183 +   int32 envIdx, numEnvs; PRLangEnv **protoLangEnvsList, *protoLangEnv;
   1.184 +   protoLangEnvsList = process->protoLangEnvsList;
   1.185     numEnvs = process->numLangEnvs;
   1.186     for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep langEnvs in hash & array
   1.187 -    { langEnv = langEnvsList[envIdx];
   1.188 -      if( langEnv->numReadyWork > 0 )
   1.189 +    { protoLangEnv = protoLangEnvsList[envIdx];
   1.190 +      if( protoLangEnv->numReadyWork > 0 )
   1.191         { bool32 
   1.192           didAssignWork =
   1.193 -          (*langEnv->workAssigner)( langEnv, slot ); //assigner calls PR to put slave/task into slot
   1.194 +          (*protoLangEnv->workAssigner)( PR_int__give_lang_env(protoLangEnv), slot ); //assigner calls PR to put slave/task into slot
   1.195  
   1.196           if(didAssignWork)
   1.197 -          { langEnv->numReadyWork -= 1;
   1.198 -            if( langEnv->numReadyWork == 0 )
   1.199 +          { protoLangEnv->numReadyWork -= 1;
   1.200 +            if( protoLangEnv->numReadyWork == 0 )
   1.201               { process->numEnvsWithWork -= 1;
   1.202               }
   1.203              goto ReturnAfterAssigningWork; //quit for-loop, 'cause found work
   1.204 @@ -260,6 +276,124 @@
   1.205   }
   1.206  
   1.207  
   1.208 +//=================================
   1.209 +//===
   1.210 +//=
   1.211 +/*Create task is a special form, that has PR behavior in addition to plugin
   1.212 + * behavior.  Master calls this first, and it then calls the plugin's
   1.213 + * create task handler.
   1.214 + * 
   1.215 + *Note: the requesting slave must be either generic slave or free task slave
   1.216 + */
   1.217 +inline
   1.218 +void
   1.219 +PRHandle__CreateTask( PRReqst *req, SlaveVP *slave )
   1.220 + { PRMetaTask     *protoMetaTask;
   1.221 +   PRProcess      *process;
   1.222 +   PRLangEnv      *protoLangEnv;
   1.223 +   void           *task;
   1.224 +                
   1.225 +   process = slave->processSlaveIsIn;
   1.226 +   
   1.227 +   protoLangEnv = PR_int__give_proto_lang_env_for_slave( slave, 
   1.228 +                                                        req->langMagicNumber );
   1.229 +   
   1.230 +   //Do the langlet's create-task handler, which keeps the task
   1.231 +   // inside the langlet's lang env, but returns the langMetaTask
   1.232 +   // so that PR can then put stuff into the prolog
   1.233 +   //typedef void * (*CreateHandler)( void *, SlaveVP *, void * ); //req, slv, langEnv
   1.234 +   //
   1.235 +   task = 
   1.236 +      (*req->createHdlr)(req->langReq, slave, PR_int__give_lang_env(protoLangEnv) );
   1.237 +   protoMetaTask = PR_int__give_prolog_of_lang_meta_task( task );
   1.238 +   protoMetaTask->ID         = req->ID; //may be NULL
   1.239 +   protoMetaTask->topLevelFn = req->topLevelFn;
   1.240 +   protoMetaTask->initData   = req->initData;
   1.241 +   protoMetaTask->processTaskIsIn = process;
   1.242 +           
   1.243 +   process->numLiveTasks += 1;
   1.244 +   protoLangEnv->numLiveWork += 1;  //used in wait statements -- small added overhead
   1.245 +   
   1.246 +   return;
   1.247 + }
   1.248 +
   1.249 +/*When a task ends, have two scenarios: 1) task ran to completion, or 2) task
   1.250 + * has been suspended at some point in its code.
   1.251 + *For 1, just decr count of live tasks (and check for end condition) -- the
   1.252 + * master loop will decide what goes into the slot freed up by this task end,
   1.253 + * so, here, don't worry about assigning a new task to the slot slave.
   1.254 + *For 2, the task's slot slave has been converted to a free task slave, which
   1.255 + * now has nothing more to do, so send it to the recycle Q (which includes
   1.256 + * freeing all the langData and meta task structs alloc'd for it).  Then
   1.257 + * decrement the live task count and check end condition.
   1.258 + * 
   1.259 + *PR has to update count of live tasks, and check end of process condition.
   1.260 + * The "main" can invoke constructs that wait for a process to end, so when
   1.261 + * end detected, have to resume what's waiting..
   1.262 + *Thing is, that wait involves the main OS thread.  That means
   1.263 + * PR internals have to do OS thread signaling.  Want to do that in the
   1.264 + * core controller, which has the original stack of an OS thread.  So the
   1.265 + * end process handling happens in the core controller.
   1.266 + * 
   1.267 + *So here, when detect process end, signal to the core controller, which will
   1.268 + * then do the condition variable notify to the OS thread that's waiting.
   1.269 + * 
   1.270 + *Note: slave may be either a slot slave or a free task slave. 
   1.271 + */
   1.272 +inline 
   1.273 +void
   1.274 +PRHandle__EndTask( PRReqst *req, SlaveVP *requestingSlv )
   1.275 + { void       *langEnv;
   1.276 +   PRLangEnv  *protoLangEnv;
   1.277 +   PRProcess  *process;
   1.278 +   void       *langMetaTask;
   1.279 +   
   1.280 +   process = requestingSlv->processSlaveIsIn;
   1.281 +   langEnv = PR_int__give_lang_env_of_req( req, requestingSlv ); //magic num in req
   1.282 +   protoLangEnv = PR_int__give_proto_lang_env( langEnv );
   1.283 +   
   1.284 +   langMetaTask = PR_int__give_lang_meta_task_from_slave( requestingSlv, req->langMagicNumber);
   1.285 +   
   1.286 +   //Do the langlet's request handler
   1.287 +   //Want to keep PR structs hidden from plugin, so extract langReq..
   1.288 +   //This is supposed to free any langlet-malloc'd mem, including meta task 
   1.289 +   (*req->handler)( req->langReq, requestingSlv, langEnv );
   1.290 +
   1.291 +   protoLangEnv->numLiveWork -= 1;  //used in wait statements -- small added overhead
   1.292 +   if( protoLangEnv->numLiveWork == 0 &&
   1.293 +       numInPrivQ( protoLangEnv->waitingForWorkToEndQ ) > 0 )
   1.294 +    { SlaveVP *
   1.295 +      waitingSlave = readPrivQ( protoLangEnv->waitingForWorkToEndQ );
   1.296 +         //can't resume into langlet that just ended its last work!
   1.297 +         // and don't have env that the waiter was created in, so resume
   1.298 +         // into PRServ env..
   1.299 +      void *
   1.300 +      resumeEnv = PR_PI__give_lang_env_from_process( process, PRServ_MAGIC_NUMBER );
   1.301 +      while( waitingSlave != NULL )
   1.302 +       {    //resume a slave that was waiting for work in this env to finish
   1.303 +         PR_PI__make_slave_ready( waitingSlave, resumeEnv );
   1.304 +            //get next waiting slave, repeat..
   1.305 +         waitingSlave = readPrivQ( protoLangEnv->waitingForWorkToEndQ );
   1.306 +       }
   1.307 +    }
   1.308 +   
   1.309 +
   1.310 +   //Now that the langlet's done with it, recycle the slave if it's a freeTaskSlv
   1.311 +   if( requestingSlv->typeOfVP == FreeTaskSlv )
   1.312 +      PR_int__recycle_slaveVP( requestingSlv ); //Doesn't decr num live slaves
   1.313 +   
   1.314 +   process->numLiveTasks -= 1;
   1.315 +   //NOTE: end-task is unrelated to work available (just in case wondering)
   1.316 +  
   1.317 +      //check End Of Process Condition
   1.318 +   if( process->numLiveTasks == 0 &&
   1.319 +       process->numLiveGenericSlvs == 0 )
   1.320 +    { //Tell the core controller to do wakeup of any waiting OS thread
   1.321 +      PR_SS__end_process_normally( process );
   1.322 +    }
   1.323 + }
   1.324 +
   1.325 +
   1.326  
   1.327  /*This is first thing called when creating a slave..  it hands off to the 
   1.328   * langlet's creator, then adds updates of its own..
   1.329 @@ -293,7 +427,7 @@
   1.330     PRLangEnv *protoLangEnv;
   1.331   
   1.332     process = slave->processSlaveIsIn;
   1.333 -   protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, req->langMagicNumber );
   1.334 +   protoLangEnv = PR_int__give_proto_lang_env_for_slave( slave, req->langMagicNumber );
   1.335        
   1.336     //create handler, or a future request handler will call PR_PI__make_slave_ready
   1.337     // which will in turn handle updating which langlets and which processes have
   1.338 @@ -306,6 +440,7 @@
   1.339     newSlv->processSlaveIsIn = process;
   1.340     newSlv->ID = req->ID;
   1.341     process->numLiveGenericSlvs += 1; //not same as work ready!
   1.342 +   protoLangEnv->numLiveWork += 1;  //used in wait statements -- small added overhead
   1.343   }
   1.344  
   1.345  /*The dissipate handler has to, update the number of slaves of the type, within
   1.346 @@ -327,105 +462,60 @@
   1.347     process = slave->processSlaveIsIn;
   1.348     
   1.349        //do the language's dissipate handler
   1.350 -   protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, slave->request->langMagicNumber );
   1.351 +   protoLangEnv = PR_int__give_proto_lang_env_for_slave( slave, slave->request->langMagicNumber );
   1.352     
   1.353     if(req->handler != NULL)
   1.354        (*req->handler)( req->langReq, slave, PR_int__give_lang_env(protoLangEnv) );
   1.355     
   1.356 +   protoLangEnv->numLiveWork -= 1;  //used in wait statements -- small added overhead
   1.357 +   if( protoLangEnv->numLiveWork == 0 &&
   1.358 +       numInPrivQ( protoLangEnv->waitingForWorkToEndQ ) > 0 )
   1.359 +    { SlaveVP *
   1.360 +      waitingSlave = readPrivQ( protoLangEnv->waitingForWorkToEndQ );
   1.361 +         //can't resume into langlet that just ended its last work!
   1.362 +         // and don't have env that the waiter was created in, so resume
   1.363 +         // into PRServ env..
   1.364 +      void *
   1.365 +      resumeEnv = PR_PI__give_lang_env_from_process( process, PRServ_MAGIC_NUMBER );
   1.366 +      while( waitingSlave != NULL )
   1.367 +       {    //resume a slave that was waiting for work in this env to finish
   1.368 +         PR_PI__make_slave_ready( waitingSlave, resumeEnv );
   1.369 +            //get next waiting slave, repeat..
   1.370 +         waitingSlave = readPrivQ( protoLangEnv->waitingForWorkToEndQ );
   1.371 +       }
   1.372 +    }
   1.373 +   
   1.374     process->numLiveGenericSlvs -= 1; 
   1.375 -   PR_int__recycle_slave( slave );
   1.376 +   PR_int__recycle_slaveVP( slave );
   1.377     //NOTE: dissipate is unrelated to work available (just in case wondering)
   1.378  
   1.379        //check End Of Process Condition
   1.380     if( process->numLiveTasks == 0 &&
   1.381         process->numLiveGenericSlvs == 0 )
   1.382 -      PR_SS__shutdown_process( process );
   1.383 +      PR_SS__end_process_normally( process );
   1.384   }
   1.385  
   1.386 -/*Create task is a special form, that has PR behavior in addition to plugin
   1.387 - * behavior.  Master calls this first, and it then calls the plugin's
   1.388 - * create task handler.
   1.389 - * 
   1.390 - *Note: the requesting slave must be either generic slave or free task slave
   1.391 +//=======================
   1.392 +//===
   1.393 +//=
   1.394 +/*Langlet shutdown triggers this, which calls the registered shutdown 
   1.395 + * handler for the langlet, and removes the lang's env from the process
   1.396   */
   1.397  inline
   1.398  void
   1.399 -PRHandle__CreateTask( PRReqst *req, SlaveVP *slave )
   1.400 - { PRMetaTask     *metaTask;
   1.401 -   PRProcess      *process;
   1.402 -   PRLangEnv      *protoLangEnv;
   1.403 -   void           *task;
   1.404 -                
   1.405 -   process = slave->processSlaveIsIn;
   1.406 +PRHandle__LangShutdown( PRReqst *req, SlaveVP *requestingSlv )
   1.407 + { void       *langEnv;
   1.408 +   PRLangEnv  *protoLangEnv;
   1.409 +   PRProcess  *process;
   1.410     
   1.411 -   protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, 
   1.412 -                                                        req->langMagicNumber );
   1.413 +   process = requestingSlv->processSlaveIsIn;
   1.414 +   protoLangEnv = PR_int__give_proto_lang_env_from_process( process, req->langMagicNumber );
   1.415 +   langEnv = PR_int__give_lang_env( protoLangEnv );
   1.416     
   1.417 -   //Do the langlet's create-task handler, which keeps the task
   1.418 -   // inside the langlet's lang env, but returns the langMetaTask
   1.419 -   // so PR can put stuff into the prolog
   1.420 -   task = 
   1.421 -      (*req->createHdlr)(req->langReq, slave, PR_int__give_lang_env(protoLangEnv) );
   1.422 -   metaTask = PR_int__give_prolog_of_task( task );
   1.423 -   metaTask->ID         = req->ID; //may be NULL
   1.424 -   metaTask->topLevelFn = req->topLevelFn;
   1.425 -   metaTask->initData   = req->initData;
   1.426 -           
   1.427 -   process->numLiveTasks += 1;
   1.428 -
   1.429 -   return;
   1.430 - }
   1.431 -
   1.432 -/*When a task ends, have two scenarios: 1) task ran to completion, or 2) task
   1.433 - * has been suspended at some point in its code.
   1.434 - *For 1, just decr count of live tasks (and check for end condition) -- the
   1.435 - * master loop will decide what goes into the slot freed up by this task end,
   1.436 - * so, here, don't worry about assigning a new task to the slot slave.
   1.437 - *For 2, the task's slot slave has been converted to a free task slave, which
   1.438 - * now has nothing more to do, so send it to the recycle Q (which includes
   1.439 - * freeing all the langData and meta task structs alloc'd for it).  Then
   1.440 - * decrement the live task count and check end condition.
   1.441 - * 
   1.442 - *PR has to update count of live tasks, and check end of process condition.
   1.443 - * The "main" can invoke constructs that wait for a process to end, so when
   1.444 - * end detected, have to resume what's waiting..
   1.445 - *Thing is, that wait involves the main OS thread.  That means
   1.446 - * PR internals have to do OS thread signaling.  Want to do that in the
   1.447 - * core controller, which has the original stack of an OS thread.  So the
   1.448 - * end process handling happens in the core controller.
   1.449 - * 
   1.450 - *So here, when detect process end, signal to the core controller, which will
   1.451 - * then do the condition variable notify to the OS thread that's waiting.
   1.452 - * 
   1.453 - *Note: slave may be either a slot slave or a free task slave. 
   1.454 - */
   1.455 -inline 
   1.456 -void
   1.457 -PRHandle__EndTask( PRReqst *req, SlaveVP *requestingSlv )
   1.458 - { void       *langEnv;
   1.459 -   PRProcess  *process;
   1.460 -   void       *langMetaTask;
   1.461 +      //call the langlet's registered handler
   1.462 +   (*protoLangEnv->shutdownHdlr)( langEnv );
   1.463     
   1.464 -   langEnv = PR_int__give_lang_env_of_req( req, requestingSlv ); //magic num in req
   1.465 -   langMetaTask = PR_int__give_lang_meta_task_from_slave( requestingSlv, req->langMagicNumber);
   1.466 -   
   1.467 -   //Do the langlet's request handler
   1.468 -   //Want to keep PR structs hidden from plugin, so extract langReq..
   1.469 -   (*req->handler)( req->langReq, requestingSlv, langEnv );
   1.470 -   
   1.471 -   //Now that the langlet's done with it, recycle the slave if it's a freeTaskSlv
   1.472 -   if( requestingSlv->typeOfVP == FreeTaskSlv )
   1.473 -      PR_int__recycle_slave( requestingSlv ); //Doesn't decr num live slaves
   1.474 -   
   1.475 -   process->numLiveTasks -= 1;
   1.476 -   //NOTE: end-task is unrelated to work available (just in case wondering)
   1.477 -  
   1.478 -      //check End Of Process Condition
   1.479 -   if( process->numLiveTasks == 0 &&
   1.480 -       process->numLiveGenericSlvs == 0 )
   1.481 -    { //Tell the core controller to do wakeup of any waiting OS thread
   1.482 -      PR_SS__shutdown_process( process );
   1.483 -    }
   1.484 +   PR_int__remove_lang_env_from_process_and_free( langEnv ); //removes from process and frees
   1.485   }
   1.486  
   1.487  
   1.488 @@ -438,24 +528,58 @@
   1.489   */
   1.490  void inline
   1.491  PRHandle__ServiceReq( SlaveVP *requestingSlv )
   1.492 - { PRReqst   *req;
   1.493 -   PRServReq *langReq;
   1.494 -   void      *langEnv;
   1.495 -   int32      magicNumber;
   1.496 + { PRReqst      *req;
   1.497 +   PRServiceReq *langReq;
   1.498 +   PRLangEnv    *protoLangEnv;
   1.499 +   int32         magicNumber;
   1.500     
   1.501   
   1.502     req = requestingSlv->request;
   1.503   
   1.504     magicNumber = req->langMagicNumber;
   1.505 -   langEnv = PR_PI__give_lang_env_for( slave, magicNumber );
   1.506 +   protoLangEnv = PR_int__give_proto_lang_env_for_slave( requestingSlv, magicNumber );
   1.507  
   1.508     langReq = PR_PI__take_lang_reqst_from(req);
   1.509     if( langReq == NULL ) return;
   1.510     switch( langReq->reqType )  //lang handlers are all in other file
   1.511      {
   1.512 -      case make_probe:      handleMakeProbe(   langReq, langEnv );
   1.513 +      case make_probe:      handleMakeProbe(   langReq, protoLangEnv );
   1.514           break;
   1.515 -      case throw_excp:  handleThrowException(  langReq, langEnv );
   1.516 +      case throw_excp:  handleThrowException(  langReq, protoLangEnv );
   1.517           break;
   1.518      }
   1.519   }
   1.520 +
   1.521 +
   1.522 +/*These handlers are special -- they don't belong to a language, because they
   1.523 + * deal with things internal to PR, so put them here..
   1.524 + */
   1.525 +inline
   1.526 +void
   1.527 +handleMakeProbe( PRServiceReq *langReq, PRLangEnv *protoLangEnv )
   1.528 + { IntervalProbe *newProbe;
   1.529 +
   1.530 +   newProbe          = PR_int__malloc( sizeof(IntervalProbe) );
   1.531 +   newProbe->nameStr = PR_int__strDup( langReq->nameStr );
   1.532 +   newProbe->hist    = NULL;
   1.533 +   newProbe->schedChoiceWasRecorded = FALSE;
   1.534 +
   1.535 +      //This runs in masterVP, so no race-condition worries
   1.536 +      //BUG: move to process
   1.537 +   newProbe->probeID =
   1.538 +            addToDynArray( newProbe, _PRTopEnv->dynIntervalProbesInfo );
   1.539 +
   1.540 +   langReq->requestingSlv->dataRetFromReq = newProbe;
   1.541 +
   1.542 +   (*protoLangEnv->makeSlaveReadyFn)( langReq->requestingSlv, PR_int__give_lang_env(protoLangEnv) );
   1.543 + }
   1.544 +
   1.545 +inline
   1.546 +void
   1.547 +handleThrowException( PRServiceReq *langReq, PRLangEnv *protoLangEnv )
   1.548 + {
   1.549 +   PR_int__throw_exception(  langReq->msgStr, langReq->requestingSlv, langReq->exceptionData );
   1.550 +   
   1.551 +   (*protoLangEnv->makeSlaveReadyFn)( langReq->requestingSlv, PR_int__give_lang_env(protoLangEnv) );
   1.552 + }
   1.553 +