diff AnimationMaster.c @ 267:608833ae2c5d

Checkpoint -- about to clean up AnimationMaster, deleting a bunch of stuff
author Sean Halle <seanhalle@yahoo.com>
date Sun, 04 Nov 2012 18:39:28 -0800
parents a5fa1e087c7e
children e5bd470b562b
line diff
     1.1 --- a/AnimationMaster.c	Thu Oct 25 23:35:36 2012 -0700
     1.2 +++ b/AnimationMaster.c	Sun Nov 04 18:39:28 2012 -0800
     1.3 @@ -13,7 +13,7 @@
     1.4  #include "VSs_impl/VSs.h"
     1.5  
     1.6  inline void
     1.7 -replaceWithNewSlotSlv( SlaveVP *requestingSlv, PRProcessEnv *processEnv );
     1.8 +replaceWithNewSlotSlv( SlaveVP *slave );
     1.9  
    1.10  
    1.11  /*The animationMaster embodies most of the animator of the language.  The
    1.12 @@ -189,13 +189,13 @@
    1.13        if( currSlot->workIsDone )
    1.14         {
    1.15           currSlot->workIsDone         = FALSE;
    1.16 -         currSlot->needsSlaveAssigned = TRUE;
    1.17 +         currSlot->needsWorkAssigned = TRUE;
    1.18           
    1.19         HOLISTIC__Record_AppResponder_start;
    1.20                 MEAS__startReqHdlr;
    1.21                 
    1.22             currSlot->workIsDone         = FALSE;
    1.23 -            currSlot->needsSlaveAssigned = TRUE;
    1.24 +            currSlot->needsWorkAssigned = TRUE;
    1.25              SlaveVP *currSlave = currSlot->slaveAssignedToSlot;
    1.26              
    1.27  	justAddedReqHdlrChg();
    1.28 @@ -223,7 +223,7 @@
    1.29                 MEAS__endReqHdlr;
    1.30         }
    1.31           //If slot empty, hand to Assigner to fill with a slave
    1.32 -      if( currSlot->needsSlaveAssigned )
    1.33 +      if( currSlot->needsWorkAssigned )
    1.34         {    //Call plugin's Assigner to give slot a new slave
    1.35            HOLISTIC__Record_Assigner_start;
    1.36           assignedSlaveVP =
    1.37 @@ -233,7 +233,7 @@
    1.38           if( assignedSlaveVP != NULL )
    1.39            { currSlot->slaveAssignedToSlot = assignedSlaveVP;
    1.40              assignedSlaveVP->animSlotAssignedTo       = currSlot;
    1.41 -            currSlot->needsSlaveAssigned  = FALSE;
    1.42 +            currSlot->needsWorkAssigned  = FALSE;
    1.43              numSlotsFilled               += 1;
    1.44              
    1.45              HOLISTIC__Record_Assigner_end;
    1.46 @@ -270,7 +270,6 @@
    1.47     //#ifdef  MODE__MULTI_LANG
    1.48     SlaveVP        *slave;
    1.49     PRProcess      *process;
    1.50 -   PRConstrEnvHolder *constrEnvHolder;
    1.51     int32           langMagicNumber;
    1.52     //#endif
    1.53     
    1.54 @@ -318,15 +317,15 @@
    1.55           slave = currSlot->slaveAssignedToSlot;
    1.56           
    1.57              //check if the completed work was a task..
    1.58 -         if( slave->taskMetaInfo->isATask )
    1.59 +         if( slave->metaTask->isATask )
    1.60            {
    1.61 -             if( slave->reqst->type == TaskEnd ) 
    1.62 +             if( slave->request->type == TaskEnd ) 
    1.63                {    //do task end handler, which is registered separately
    1.64                     //note, end hdlr may use semantic data from reqst..
    1.65                  //#ifdef  MODE__MULTI_LANG
    1.66                     //get end-task handler
    1.67                  //taskEndHandler = lookup( slave->reqst->langMagicNumber, processEnv );
    1.68 -                taskEndHandler = slave->taskMetaInfo->endTaskHandler;
    1.69 +                taskEndHandler = slave->metaTask->endTaskHandler;
    1.70                  //#endif
    1.71                  (*taskEndHandler)( slave, semanticEnv );
    1.72                  
    1.73 @@ -353,7 +352,7 @@
    1.74         } //if has suspended slave that needs handling
    1.75        
    1.76           //if slot empty, hand to Assigner to fill with a slave
    1.77 -      if( currSlot->needsSlaveAssigned )
    1.78 +      if( currSlot->needsWorkAssigned )
    1.79         {    //Call plugin's Assigner to give slot a new slave
    1.80                 HOLISTIC__Record_Assigner_start;
    1.81                 
    1.82 @@ -365,12 +364,12 @@
    1.83           if( assignedSlaveVP != NULL )
    1.84            { currSlot->slaveAssignedToSlot = assignedSlaveVP;
    1.85              assignedSlaveVP->animSlotAssignedTo = currSlot;
    1.86 -            currSlot->needsSlaveAssigned  = FALSE;
    1.87 +            currSlot->needsWorkAssigned  = FALSE;
    1.88              numSlotsFilled               += 1;
    1.89            }
    1.90           else
    1.91            {
    1.92 -            currSlot->needsSlaveAssigned  = TRUE; //local write
    1.93 +            currSlot->needsWorkAssigned  = TRUE; //local write
    1.94            }
    1.95                 HOLISTIC__Record_Assigner_end;
    1.96         }//if slot needs slave assigned
    1.97 @@ -496,7 +495,6 @@
    1.98     //#ifdef  MODE__MULTI_LANG
    1.99     SlaveVP        *slave;
   1.100     PRProcess      *process;
   1.101 -   PRConstrEnvHolder *constrEnvHolder;
   1.102     int32           langMagicNumber;
   1.103     //#endif
   1.104     
   1.105 @@ -579,7 +577,7 @@
   1.106         } //if has suspended slave that needs handling
   1.107        
   1.108           //if slot empty, hand to Assigner to fill with a slave
   1.109 -      if( currSlot->needsSlaveAssigned )
   1.110 +      if( currSlot->needsWorkAssigned )
   1.111         {    //Call plugin's Assigner to give slot a new slave
   1.112                 HOLISTIC__Record_Assigner_start;
   1.113                 
   1.114 @@ -591,12 +589,12 @@
   1.115           if( assignedSlaveVP != NULL )
   1.116            { currSlot->slaveAssignedToSlot = assignedSlaveVP;
   1.117              assignedSlaveVP->animSlotAssignedTo = currSlot;
   1.118 -            currSlot->needsSlaveAssigned  = FALSE;
   1.119 +            currSlot->needsWorkAssigned  = FALSE;
   1.120              numSlotsFilled               += 1;
   1.121            }
   1.122           else
   1.123            {
   1.124 -            currSlot->needsSlaveAssigned  = TRUE; //local write
   1.125 +            currSlot->needsWorkAssigned  = TRUE; //local write
   1.126            }
   1.127                 HOLISTIC__Record_Assigner_end;
   1.128         }//if slot needs slave assigned
   1.129 @@ -618,7 +616,6 @@
   1.130  void animationMaster( void *initData, SlaveVP *masterVP )
   1.131   { 
   1.132     int32           slotIdx;
   1.133 -//   int32           numSlotsFilled;
   1.134     AnimSlot       *currSlot;
   1.135        //Used while scanning and filling animation slots
   1.136     AnimSlot      **animSlots;
   1.137 @@ -661,6 +658,77 @@
   1.138  #endif  //MODE__MULTI_LANG
   1.139  #endif  //MODE__MULTI_PROCESS
   1.140  
   1.141 +
   1.142 +//This version of the master selects one of three loops, depending upon
   1.143 +// whether stand-alone single language (just slaves), or standalone with
   1.144 +// tasks, or multi-lang (implies multi-process)
   1.145 +void animationMaster( void *initData, SlaveVP *masterVP )
   1.146 + { 
   1.147 +   int32           slotIdx;
   1.148 +   AnimSlot       *currSlot;
   1.149 +      //Used while scanning and filling animation slots
   1.150 +   AnimSlot      **animSlots;
   1.151 +   
   1.152 +      //Local copies, for performance
   1.153 +   MasterEnv      *masterEnv;
   1.154 +   int32           thisCoresIdx;
   1.155 +   
   1.156 +   //======================== Initializations ========================
   1.157 +   masterEnv        = (MasterEnv*)_PRTopEnv;
   1.158 +   
   1.159 +   thisCoresIdx     = masterVP->coreAnimatedBy;
   1.160 +   animSlots        = masterEnv->allAnimSlots[thisCoresIdx];
   1.161 +      
   1.162 +      HOLISTIC__Insert_Master_Global_Vars;
   1.163 +   
   1.164 +   //======================== animationMaster ========================
   1.165 +   //Have three different modes, and the master behavior is different for
   1.166 +   // each, so jump to the loop that corresponds to the mode.
   1.167 +   //
   1.168 +   switch(mode)
   1.169 +    { case StandaloneSlavesOnly: 
   1.170 +         while(1)
   1.171 +          {       MEAS__Capture_Pre_Master_Point
   1.172 +            for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
   1.173 +             {
   1.174 +               currSlot = animSlots[ slotIdx ];
   1.175 +
   1.176 +               masterFunction_StandaloneSlavesOnly( currSlot );
   1.177 +             }
   1.178 +                  MEAS__Capture_Post_Master_Point;
   1.179 +            masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
   1.180 +            flushRegisters();
   1.181 +          } 
   1.182 +      case StandaloneWTasks:     
   1.183 +         while(1)
   1.184 +          {       MEAS__Capture_Pre_Master_Point
   1.185 +            for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
   1.186 +             {
   1.187 +               currSlot = animSlots[ slotIdx ];
   1.188 +
   1.189 +               masterFunction_StandaloneWTasks( currSlot );
   1.190 +             }
   1.191 +                  MEAS__Capture_Post_Master_Point;
   1.192 +            masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
   1.193 +            flushRegisters();
   1.194 +          }
   1.195 +      case MultiLang:
   1.196 +         while(1)
   1.197 +          {       MEAS__Capture_Pre_Master_Point
   1.198 +            for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
   1.199 +             {
   1.200 +               currSlot = animSlots[ slotIdx ];
   1.201 +
   1.202 +               masterFunction_multiLang( currSlot );
   1.203 +             }
   1.204 +                  MEAS__Capture_Post_Master_Point;
   1.205 +            masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
   1.206 +            flushRegisters();
   1.207 +          } 
   1.208 +    }
   1.209 + }
   1.210 +
   1.211 +
   1.212  inline
   1.213  void
   1.214  masterFunction_multiLang( AnimSlot  *currSlot )
   1.215 @@ -675,6 +743,7 @@
   1.216           //Check if newly-done slave in slot, which will need request handled
   1.217        if( currSlot->workIsDone )
   1.218         { currSlot->workIsDone = FALSE;
   1.219 +         currSlot->needsWorkAssigned = TRUE;
   1.220         
   1.221                 HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot
   1.222                 MEAS__startReqHdlr;
   1.223 @@ -682,94 +751,56 @@
   1.224           
   1.225              //process the request made by the slave (held inside slave struc)
   1.226           slave = currSlot->slaveAssignedToSlot;
   1.227 -         
   1.228 -            //check if the slave was doing a task..
   1.229 -         //Action depends on both on the request type, and whether it's on
   1.230 -         // a generic slave vs a suspended task
   1.231 -         if( slave->metaTask->taskType == AtomicTask ||
   1.232 -             slave->metaTask->taskType == SuspendedTask )
   1.233 -          { 
   1.234 -            switch( slave->request->reqType )
   1.235 -             { case TaskEnd: 
   1.236 -                { PRHandle_EndTask( slave ); //if free task slave, update count, put into recycle Q -- do handler before lang's handler
   1.237 +         req = slave->request;
   1.238  
   1.239 -                     //do task end handler, which is registered separately
   1.240 -                     //note, end hdlr may use semantic data from reqst..
   1.241 -                     //get end-task handler
   1.242 +            //If the requesting slave is a slot slave, and request is not
   1.243 +            // task-end, then turn it into a free task slave. 
   1.244 +         if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd )
   1.245 +            replaceWithNewSlotSlv( slave );
   1.246  
   1.247 -                  RequestHandler
   1.248 -                  taskEndHandler = slave->request->handler;
   1.249 -                  semanticEnv = PR_int__give_sem_env_for_slave( slave, 
   1.250 -                                              slave->request->langMagicNumber );
   1.251 -                  (*taskEndHandler)( slave, semanticEnv );
   1.252 +         //Handle task create and end first -- they're special cases..
   1.253 +         switch( req->reqType )
   1.254 +          { case TaskEnd: 
   1.255 +             { //do PR handler, which calls lang's hdlr and does recycle of
   1.256 +               // free task slave if needed -- PR handler checks for free task Slv
   1.257 +               PRHandle_EndTask( slave );                               break;
   1.258 +             }
   1.259 +            case TaskCreate:
   1.260 +             { //Do PR's create-task handler, which calls the lang's hdlr
   1.261 +               // PR handler checks for free task Slv
   1.262 +               PRHandle_CreateTask( slave );                            break;
   1.263 +             }
   1.264 +            case SlvCreate:    PRHandle_CreateSlave( slave );           break;
   1.265 +            case SlvDissipate: PRHandle_Dissipate( slave );             break;
   1.266 +            case Service:      PR_int__handle_PRServiceReq( slave );    break; //resume into PR's own semantic env
   1.267 +            case Hardware: //for future expansion
   1.268 +            case IO:       //for future expansion
   1.269 +            case OSCall:   //for future expansion
   1.270 +                PR_int__throw_exception("Not implemented");             break;
   1.271 +            case Language: //normal sem request
   1.272 +              magicNumber = req->langMagicNumber;
   1.273 +              semanticEnv = PR_PI__give_sem_env_for( slave, magicNumber );
   1.274 +              requestHandler = semanticEnv->requestHdlr;
   1.275 +              (*requestHandler)( req->semReq, slave, semanticEnv );
   1.276 +          }
   1.277  
   1.278 -                  goto AssignWork;
   1.279 -                }
   1.280 -               case TaskCreate:
   1.281 -                { PRHandle_CreateTask( slave );
   1.282 -                  RequestHandler
   1.283 -                  taskCreateHandler = slave->request->handler;
   1.284 -                  semanticEnv = PR_int__give_sem_env_for_slave( slave, 
   1.285 -                                              slave->request->langMagicNumber );
   1.286 -                  (*taskCreateHandler)( slave, semanticEnv ); //resumes creating slave
   1.287 -                  goto AssignWork;
   1.288 -                }
   1.289 -               default:  
   1.290 -                {    //is a task, and just suspended, so tied to a free task slave
   1.291 -                     //First turn slot slave into free task slave & make replacement
   1.292 -                  if( slave->typeOfVP == SlotTaskSlv )
   1.293 -                     replaceWithNewSlotSlv( slave, slave->processSlaveIsIn->processEnv );
   1.294 -
   1.295 -                  //goto normal slave request handling
   1.296 -                  goto SlaveReqHandling; 
   1.297 -                }
   1.298 -             }
   1.299 -          }
   1.300 -         else //is a slave that suspended
   1.301 -          {
   1.302 -             
   1.303 -          SlaveReqHandling:
   1.304 -               //Q: put the switch in inline call, to clean up code?
   1.305 -            req = slave->request;
   1.306 -            switch( req->reqType )
   1.307 -             { case SlvCreate:    PRHandle_CreateSlave( slave );    break;
   1.308 -               case SlvDissipate: PRHandle_Dissipate( slave ); break;
   1.309 -               case Service:      PR_int__handle_PRServiceReq( slave );  break; //resume into PR's own semantic env
   1.310 -               case Hardware: //for future expansion
   1.311 -               case IO:       //for future expansion
   1.312 -               case OSCall:   //for future expansion
   1.313 -               case Language: //normal sem request
   1.314 -                  magicNumber = slave->request->langMagicNumber;
   1.315 -                  semanticEnv = PR_PI__give_sem_env_for( slave, magicNumber );
   1.316 -                  requestHandler = semanticEnv->requestHdlr;
   1.317 -                  (*requestHandler)( slave, semanticEnv ); //(note: indirect Fn call more efficient when use fewer params, instead re-fetch from slave)
   1.318 -             }
   1.319 -            
   1.320 -               HOLISTIC__Record_AppResponder_end;
   1.321 -               MEAS__endReqHdlr;
   1.322 -               
   1.323 -            goto AssignWork;
   1.324 -          }
   1.325 -       } //if has suspended slave that needs handling
   1.326 +           HOLISTIC__Record_AppResponder_end;
   1.327 +           MEAS__endReqHdlr;          
   1.328 +       } //if have request to be handled
   1.329        
   1.330 -         //End up here when the slot did not have ended work in it (no req)
   1.331 -         //So, here, if slot empty, look for work to fill the slot
   1.332 -      if( currSlot->needsSlaveAssigned )
   1.333 -       {       HOLISTIC__Record_Assigner_start;
   1.334 -               
   1.335 -       AssignWork:
   1.336 +      if( currSlot->needsWorkAssigned )
   1.337 +       {
   1.338 +               HOLISTIC__Record_Assigner_start;
   1.339 +                  
   1.340              //Scan sem environs, looking for semEnv with ready work.
   1.341              // call the Assigner for that sem Env, to get a slave for the slot
   1.342           assignedSlaveVP = assignWork( semanticEnv, currSlot );
   1.343         
   1.344 -            //put the chosen slave into slot, and adjust flags and state
   1.345 +            //if work found, put into slot, and adjust flags and state
   1.346           if( assignedSlaveVP != NULL )
   1.347            { currSlot->slaveAssignedToSlot = assignedSlaveVP;
   1.348              assignedSlaveVP->animSlotAssignedTo = currSlot;
   1.349 -            currSlot->needsSlaveAssigned  = FALSE;
   1.350 -          }
   1.351 -         else
   1.352 -          { currSlot->needsSlaveAssigned  = TRUE; //local write
   1.353 +            currSlot->needsWorkAssigned  = FALSE;
   1.354            }
   1.355                 HOLISTIC__Record_Assigner_end;
   1.356         }//if slot needs slave assigned
   1.357 @@ -786,6 +817,9 @@
   1.358  replaceWithNewSlotSlv( SlaveVP *requestingSlv, PRProcess *process )
   1.359   { SlaveVP *newSlotSlv;
   1.360  
   1.361 + When slot slave converted to a free task slave, insert the process pointer -- slot slaves are not assigned to any process;
   1.362 + when convert from slot slave to free task slave, check what should do about num (live slaves + live tasks) inside VSs's task stub, and properly update process's count of liveFreeTaskSlaves 
   1.363 +
   1.364        //get a new slave to be the slot slave
   1.365     newSlotSlv     = readPrivQ( process->freeTaskSlvRecycleQ );
   1.366     if( newSlotSlv == NULL )
   1.367 @@ -797,7 +831,7 @@
   1.368        //set slave values to make it the slot slave
   1.369     newSlotSlv->metaTask              = NULL;
   1.370     newSlotSlv->typeOfVP              = SlotTaskSlv;
   1.371 -   newSlotSlv->needsTaskAssigned     = TRUE;
   1.372 +//   newSlotSlv->needsTaskAssigned     = TRUE;
   1.373     
   1.374        //a slot slave is pinned to a particular slot on a particular core
   1.375        //Note, this happens before the request is seen by handler, so nothing
   1.376 @@ -813,7 +847,7 @@
   1.377        //Fix up requester, to be an extra slave now (but not an ended one)
   1.378        // because it's active, doesn't go into freeTaskSlvRecycleQ
   1.379     requestingSlv->typeOfVP = FreeTaskSlv;
   1.380 -   check_if_need_to_change_metaTask_type_or_something;
   1.381 +   requestingSlv->metaTask->taskType = FreeTask;
   1.382   }
   1.383  
   1.384  
   1.385 @@ -841,30 +875,33 @@
   1.386  inline SlaveVP *
   1.387  assignWork( PRProcess *process, AnimSlot *slot )
   1.388   { SlaveVP        *returnSlv;
   1.389 -   //VSsSemEnv      *semEnv;
   1.390 -   //VSsSemData     *semData;
   1.391     int32           coreNum, slotNum;
   1.392 -   PRMetaTask     *newMetaTask, *assignedMetaTask;
   1.393 -   SlaveVP        *freeTaskSlv;
   1.394 +   PRMetaTask     *assignedMetaTask;
   1.395  
   1.396     coreNum = slot->coreSlotIsOn;
   1.397     
   1.398 -   if( _PRTopEnv->overrideAssigner != NULL )
   1.399 -    { assignedMetaTask = (*_PRTopEnv->overrideAssigner)( process, slot );
   1.400 +   if( process->overrideAssigner != NULL )
   1.401 +    { assignedMetaTask = (*process->overrideAssigner)( process, slot );
   1.402        if( assignedMetaTask != NULL )
   1.403         {
   1.404              //have work, so reset Done flag (caused by work generated on other core)
   1.405 -         if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf
   1.406 -            process->coreIsDone[coreNum] = FALSE;   //don't just write always
   1.407 +//         if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf
   1.408 +//            process->coreIsDone[coreNum] = FALSE;   //don't just write always
   1.409           
   1.410 -         switch( assignedMetaTask->taskType )
   1.411 -          { case GenericSlave:  goto AssignSlave;
   1.412 -            case SuspendedTask: goto AssignSlave;
   1.413 -            case AtomicTask:    goto AssignNewTask;
   1.414 -            default:      PR_int__throw_exception( "unknown task type ret by assigner" );
   1.415 -          }
   1.416 +//         switch( assignedMetaTask->taskType )
   1.417 +//          { case GenericSlave:  goto AssignSlave;
   1.418 +//            case FreeTask:      goto AssignSlave;
   1.419 +//            case SlotTask:      goto AssignNewTask;
   1.420 +//            default:      PR_int__throw_exception( "unknown task type ret by assigner" );
   1.421 +//          }
   1.422 +            //If meta task has a slave attached, then goto assign slave,
   1.423 +            // else it's a new task, so goto where assign it to a slot slave
   1.424 +         if( assignedMetaTask->slaveAssignedTo != NULL )
   1.425 +            goto AssignSlave;
   1.426 +         else
   1.427 +            goto AssignNewTask;
   1.428         }
   1.429 -      else
   1.430 +      else //metaTask is NULL, so no work..
   1.431           goto NoWork;
   1.432      }
   1.433     
   1.434 @@ -872,56 +909,60 @@
   1.435     int32 envIdx, numEnvs; PRSemEnv **semEnvs, *semEnv; SlaveAssigner assigner;
   1.436     semEnvs = process->semEnvs;
   1.437     numEnvs = process->numSemEnvs;
   1.438 -   for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep semEnvs in hash AND array
   1.439 +   for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep semEnvs in hash & array
   1.440      { semEnv = semEnvs[envIdx];
   1.441        if( semEnv->hasWork )
   1.442         { assigner = semEnv->slaveAssigner; 
   1.443           assignedMetaTask = (*assigner)( semEnv, slot );
   1.444           
   1.445              //have work, so reset Done flag (caused by work generated on other core)
   1.446 -         if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf
   1.447 -            process->coreIsDone[coreNum] = FALSE;   //don't just write always
   1.448 +//         if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf
   1.449 +//            process->coreIsDone[coreNum] = FALSE;   //don't just write always
   1.450           
   1.451 -         switch( assignedMetaTask->taskType )
   1.452 -          { case GenericSlave:  goto AssignSlave;
   1.453 -            case SuspendedTask: goto AssignSlave;
   1.454 -            case AtomicTask:    goto AssignNewTask;
   1.455 -            default:      PR_int__throw_exception( "unknown task type ret by assigner" );
   1.456 -          }
   1.457 +//         switch( assignedMetaTask->taskType )
   1.458 +//          { case GenericSlave: goto AssignSlave;
   1.459 +//            case FreeTask:     goto AssignSlave;
   1.460 +//            case SlotTask:     goto AssignNewTask;
   1.461 +//            default:      PR_int__throw_exception( "unknown task type ret by assigner" );
   1.462 +//          }
   1.463 +            //If meta task has a slave attached, then goto assign slave,
   1.464 +            // else it's a new task, so goto where assign it to a slot slave
   1.465 +         if( assignedMetaTask->slaveAssignedTo != NULL )
   1.466 +            goto AssignSlave;
   1.467 +         else
   1.468 +            goto AssignNewTask;
   1.469         }
   1.470      }
   1.471 +   //If reach here, then have searched all semEnv's & none have work..
   1.472     
   1.473   NoWork:
   1.474        //No work, if reach here..
   1.475      { goto ReturnTheSlv;
   1.476      }
   1.477   
   1.478 - AssignSlave:     //Have a metaTask attached to a slave, so get the slave out
   1.479 -    {    //get slave pointed to by meta task.
   1.480 -      returnSlv = assignedMetaTask->slaveAssignedTo;
   1.481 -
   1.482 + AssignSlave: //Have a metaTask attached to a slave, so get the slave & ret it
   1.483 +    { returnSlv = assignedMetaTask->slaveAssignedTo;
   1.484        returnSlv->coreAnimatedBy   = coreNum;
   1.485      
   1.486        goto ReturnTheSlv;
   1.487      }
   1.488   
   1.489 - AssignNewTask:
   1.490 + AssignNewTask: //Have a new metaTask that has no slave yet.. assign to slot slv
   1.491      { 
   1.492           //get the slot slave to assign the task to..
   1.493 -      coreNum = slot->coreSlotIsOn;
   1.494        slotNum = slot->slotIdx;
   1.495        returnSlv = process->slotTaskSlvs[coreNum][slotNum];
   1.496  
   1.497 -         //point slave to task's function, and mark slave as having task
   1.498 +         //point slave to task's function
   1.499        PR_int__reset_slaveVP_to_TopLvlFn( returnSlv, 
   1.500                         assignedMetaTask->topLevelFn, assignedMetaTask->initData );
   1.501 -      returnSlv->metaTask          = assignedMetaTask;
   1.502 +      returnSlv->metaTask = assignedMetaTask;
   1.503        assignedMetaTask->slaveAssignedTo = returnSlv;
   1.504 -      returnSlv->needsTaskAssigned = FALSE;  //slot slave is a "Task" slave type
   1.505 +//      returnSlv->needsTaskAssigned = FALSE;  //slot slave is a "Task" slave type
   1.506        
   1.507           //have work, so reset Done flag, if was set
   1.508 -      if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf
   1.509 -         process->coreIsDone[coreNum] = FALSE;   //don't just write always
   1.510 +//      if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf
   1.511 +//         process->coreIsDone[coreNum] = FALSE;   //don't just write always
   1.512        
   1.513        goto ReturnTheSlv;
   1.514      }
   1.515 @@ -1005,12 +1046,12 @@
   1.516     process->numLiveGenericSlvs += 1;
   1.517     metaTask = PR_int__create_slave_meta_task();
   1.518     metaTask->taskID = req->ID;
   1.519 -   metaTask->taskType = GenericSlave;
   1.520 +//   metaTask->taskType = GenericSlave;
   1.521     
   1.522 -   (*req->handler)(newSlv);
   1.523 +   (*req->handler)( req->semReq, newSlv, requestingSlv, semEnv );
   1.524   }
   1.525  
   1.526 -/*The dissipate handler has to update the number of slaves of the type, within
   1.527 +/*The dissipate handler has to, sdate the number of slaves of the type, within
   1.528   * the process, and call the langlet handler linked into the request,
   1.529   * and after that returns, then call the PR function that frees the slave state
   1.530   * (or recycles the slave).
   1.531 @@ -1027,52 +1068,53 @@
   1.532     process = slave->processSlaveIsIn;
   1.533     
   1.534        //do the language's dissipate handler
   1.535 -   semEnv = PR_int__give_sem_env_for( slave, slave->request->langMagicNumber );
   1.536 -   (*slave->request->handler)( slave, semEnv );
   1.537 +   semEnv = PR_int__give_sem_env_for_slave( slave, slave->request->langMagicNumber );
   1.538 +   (*slave->request->handler)( slave->request->semReq, slave, semEnv );
   1.539     
   1.540     process->numLiveGenericSlvs -= 1;
   1.541 -   PR_int__dissipate_slaveVP_multilang( slave ); //recycles and resets semDatas
   1.542 -   
   1.543 +   PR_int__recycle_slave_multilang( requestingSlv );
   1.544 +  
   1.545        //check End Of Process Condition
   1.546     if( process->numLiveTasks == 0 &&
   1.547         process->numLiveGenericSlvs == 0 )
   1.548 -      signalEndOfProcess;
   1.549 +      PR_SS__shutdown_process( process );
   1.550   }
   1.551  
   1.552  /*Create task is a special form, that has PR behavior in addition to plugin
   1.553 - * behavior.  Master calls this first, and this in turn calls the plugin's
   1.554 + * behavior.  Master calls this first, and then calls the plugin's
   1.555   * create task handler.
   1.556 + * 
   1.557 + *Note: the requesting slave must be either generic slave or free task slave
   1.558   */
   1.559 -inline void
   1.560 -PRHandle_CreateTask( TopLevelFn topLevelFn, void *initData, PRReqst *req, 
   1.561 -                                                        SlaveVP *requestingSlv )
   1.562 - { PRMetaTask    *metaTask;
   1.563 -   PRProcess     *process;
   1.564 -   void          *semEnv, _langMetaTask;
   1.565 +inline PRMetaTask *
   1.566 +PRHandle_CreateTask( PRReqst *req, SlaveVP *requestingSlv )
   1.567 + { PRMetaTask     *metaTask;
   1.568 +   PRProcess      *process;
   1.569     PRLangMetaTask *langMetaTask;
   1.570 -                    
   1.571 +   PRSemEnv       *semanticEnv;
   1.572 +                
   1.573     process = requestingSlv->processSlaveIsIn;
   1.574  
   1.575 -   metaTask         = PR_int__create_meta_task( req );
   1.576 -   metaTask->taskID = req->ID; //may be NULL
   1.577 -   metaTask->topLevelFn = topLevelFn;
   1.578 -   metaTask->initData   = initData;
   1.579 +   metaTask             = PR_int__create_meta_task( req );
   1.580 +   metaTask->taskID     = req->ID; //may be NULL
   1.581 +   metaTask->topLevelFn = req->topLevelFn;
   1.582 +   metaTask->initData   = req->initData;
   1.583             
   1.584     process->numLiveTasks += 1;
   1.585 -      
   1.586 -      //plugin tracks tasks ready, and has its own assigner, so task doesn't
   1.587 -      // come back from lang's handler -- it's consumed and stays in semEnv.
   1.588 -      //But handler gives back the language-specific meta-task it creates, and
   1.589 -      // then hook that into the PR meta-task
   1.590 -      //(Could also do PRMetaTask as a prolog -- make a Fn that takes the size
   1.591 -      // of the lang's metaTask, and alloc's that plus the prolog and returns
   1.592 -      // ptr to position just above the prolog)
   1.593 -   semEnv = PR_int__give_semEnv_of_req( req, requestingSlv ); //magic num in req
   1.594 -   _langMetaTask = (*requestingSlv->request->handler)(req, semEnv);
   1.595 -   langMetaTask  = (PRLangMetaTask *)_langMetaTask;
   1.596 +
   1.597 +   semanticEnv = PR_int__give_sem_env_for_slave( slave, 
   1.598 +                                          req->langMagicNumber );
   1.599 +   
   1.600 +   //Do the langlet's create-task handler, which keeps the task
   1.601 +   // inside the langlet's sem env, but returns the langMetaTask
   1.602 +   // so PR can hook it to the PRMetaTask.
   1.603 +   //(Could also do PRMetaTask as a prolog -- make a Fn that takes the size
   1.604 +   // of the lang's metaTask, and alloc's that plus the prolog and returns
   1.605 +   // ptr to position just above the prolog)
   1.606 +   langMetaTask = (*req->handler)(req->semReq, slave, semanticEnv);
   1.607     metaTask->langMetaTask      = langMetaTask;
   1.608     langMetaTask->protoMetaTask = metaTask;
   1.609 -   
   1.610 +
   1.611     return;
   1.612   }
   1.613  
   1.614 @@ -1087,36 +1129,43 @@
   1.615   * decrement the live task count and check end condition.
   1.616   * 
   1.617   *PR has to update count of live tasks, and check end of process condition.
   1.618 - * There are constructs that wait for a process to end, so when end detected,
   1.619 - * have to resume what's waiting..
   1.620 - *Thing is, the wait is used in "main", so it's an OS thread.  That means
   1.621 + * The "main" can invoke constructs that wait for a process to end, so when
   1.622 + * end detected, have to resume what's waiting..
   1.623 + *Thing is, that wait involves the main OS thread.  That means
   1.624   * PR internals have to do OS thread signaling.  Want to do that in the
   1.625 - * core controller, which has the original stack of an OS thread.
   1.626 + * core controller, which has the original stack of an OS thread.  So the
   1.627 + * end process handling happens in the core controller.
   1.628   * 
   1.629   *So here, when detect process end, signal to the core controller, which will
   1.630 - * then do the condition variable notify to the OS thread that's waiting. 
   1.631 + * then do the condition variable notify to the OS thread that's waiting.
   1.632 + * 
   1.633 + *Note: slave may be either a slot slave or a free task slave. 
   1.634   */
   1.635  inline void
   1.636  PRHandle_EndTask( SlaveVP *requestingSlv )
   1.637 - { void *semEnv;
   1.638 -   PRReqst *req;  
   1.639 -   PRMetaTask *metaTask;
   1.640 + { void       *semEnv;
   1.641 +   PRReqst    *req;  
   1.642 +   PRLangMetaTask *langMetaTask;
   1.643     PRProcess  *process;
   1.644 - 
   1.645 +   
   1.646     req = requestingSlv->request;
   1.647 -   semEnv = PR_int__give_semEnv_of_req( req, requestingSlv ); //magic num in req
   1.648 -   metaTask = req->metaTask;
   1.649 -      //Want to keep PRMetaTask hidden from plugin, so extract semReq..
   1.650 -   (*req->handler)( metaTask, req->semReq, semEnv );
   1.651 +   semEnv = PR_int__give_sem_env_of_req( req, requestingSlv ); //magic num in req
   1.652 +   langMetaTask = requestingSlv->metaTask->langMetaTask;
   1.653     
   1.654 -   recycleFreeTaskSlave( requestingSlv );
   1.655 +   //Do the langlet's request handler
   1.656 +   //Want to keep PR structs hidden from plugin, so extract semReq..
   1.657 +   (*req->handler)( langMetaTask, req->semReq, semEnv );
   1.658 +   
   1.659 +   //Now that the langlet's done with it, recycle the slave if it's a freeTaskSlv
   1.660 +   if( requestingSlv->typeOfVP == FreeTaskSlv )
   1.661 +      PR_int__recycle_slave_multilang( requestingSlv );
   1.662     
   1.663     process->numLiveTasks -= 1;
   1.664    
   1.665        //check End Of Process Condition
   1.666     if( process->numLiveTasks == 0 &&
   1.667         process->numLiveGenericSlvs == 0 )
   1.668 -      signalEndOfProcessToCoreCtlr;
   1.669 +      //Tell the core controller to do wakeup of any waiting OS thread
   1.670 +      PR_SS__shutdown_process( process );
   1.671   }
   1.672  
   1.673 - 
   1.674 \ No newline at end of file