diff AnimationMaster.c @ 268:e5bd470b562b

Checkpoint 2 -- split up header file, and about to delete single lang version of AnimationMaster
author Sean Halle <seanhalle@yahoo.com>
date Mon, 14 Jan 2013 15:31:23 -0800
parents 608833ae2c5d
children e6a68e7ea63f
line diff
     1.1 --- a/AnimationMaster.c	Sun Nov 04 18:39:28 2012 -0800
     1.2 +++ b/AnimationMaster.c	Mon Jan 14 15:31:23 2013 -0800
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright 2010  OpenSourceStewardshipFoundation
     1.6 + * Copyright 2010  OpenSourceResearchInstitute
     1.7   * 
     1.8   * Licensed under BSD
     1.9   */
    1.10 @@ -12,9 +12,23 @@
    1.11  #include "PR.h"
    1.12  #include "VSs_impl/VSs.h"
    1.13  
    1.14 -inline void
    1.15 -replaceWithNewSlotSlv( SlaveVP *slave );
    1.16 +/*
    1.17 +void        PRHandle_CreateTask_SL(SlaveVP *slave);
    1.18  
    1.19 +void        PRHandle_CreateSlave_SL(SlaveVP *slave);
    1.20 +void        PRHandle_Dissipate_SL(SlaveVP *slave);
    1.21 +void        PR_int__handle_PRServiceReq_SL(SlaveVP *slave);
    1.22 +*/
    1.23 +inline void PRHandle_CreateTask( PRReqst *req, SlaveVP *slave );
    1.24 +inline void PRHandle_EndTask(    PRReqst *req, SlaveVP *slave );
    1.25 +inline void PRHandle_CreateSlave(PRReqst *req, SlaveVP *slave );
    1.26 +void        PRHandle_Dissipate(  PRReqst *req, SlaveVP *slave );
    1.27 +
    1.28 +
    1.29 +//inline void  masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot );
    1.30 +inline void masterFunction_MultiLang( AnimSlot  *slot );
    1.31 +inline PRProcess * pickAProcess( AnimSlot *slot );
    1.32 +inline SlaveVP * assignWork( PRProcess *process, AnimSlot *slot );
    1.33  
    1.34  /*The animationMaster embodies most of the animator of the language.  The
    1.35   * animator is what emodies the behavior of language constructs. 
    1.36 @@ -40,6 +54,81 @@
    1.37   *
    1.38   */
    1.39  
    1.40 +//This version of the master selects one of three loops, depending upon
    1.41 +// whether stand-alone single language (just slaves), or standalone with
    1.42 +// tasks, or multi-lang (implies multi-process)
    1.43 +void animationMaster( void *_environment, SlaveVP *masterVP )
    1.44 + { 
    1.45 +   TopEnv         *masterEnv = (TopEnv *)_environment;
    1.46 +   int32           slotIdx;
    1.47 +   AnimSlot       *currSlot;
    1.48 +      //Used while scanning and filling animation slots
    1.49 +   AnimSlot      **animSlots;
    1.50 +   
    1.51 +      //Local copies, for performance
    1.52 +   int32           thisCoresIdx;
    1.53 +   
    1.54 +   //======================== Initializations ========================
    1.55 +   thisCoresIdx     = masterVP->coreAnimatedBy;
    1.56 +   animSlots        = masterEnv->allAnimSlots[thisCoresIdx];
    1.57 +      
    1.58 +      HOLISTIC__Insert_Master_Global_Vars;
    1.59 +   
    1.60 +   //======================== animationMaster ========================
    1.61 +   //Have three different modes, and the master behavior is different for
    1.62 +   // each, so jump to the loop that corresponds to the mode.
    1.63 +   //
    1.64 +   switch(masterEnv->mode)
    1.65 +    {
    1.66 +/*
    1.67 +    { case SingleLang: 
    1.68 +         while(1)
    1.69 +          {       MEAS__Capture_Pre_Master_Point
    1.70 +            for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
    1.71 +             {
    1.72 +               currSlot = animSlots[ slotIdx ];
    1.73 +
    1.74 +               masterFunction_StandaloneSlavesOnly( masterEnv, currSlot );
    1.75 +             }
    1.76 +                  MEAS__Capture_Post_Master_Point;
    1.77 +            masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
    1.78 +            flushRegisters();
    1.79 +          } 
    1.80 +
    1.81 +      case SingleLang:     
    1.82 +       { PRLangEnv  *protoLangEnv =  _PRTopEnv->protoLangEnv;
    1.83 +         while(1)
    1.84 +          {       MEAS__Capture_Pre_Master_Point
    1.85 +            for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
    1.86 +             {
    1.87 +               currSlot = animSlots[ slotIdx ];
    1.88 +
    1.89 +               masterFunction_SingleLang( protoLangEnv, currSlot );
    1.90 +             }
    1.91 +                  MEAS__Capture_Post_Master_Point;
    1.92 +            masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
    1.93 +            flushRegisters();
    1.94 +          }
    1.95 +       }
    1.96 + */
    1.97 +      case MultiLang:
    1.98 +       { while(1)
    1.99 +          {       MEAS__Capture_Pre_Master_Point
   1.100 +            for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
   1.101 +             {
   1.102 +               currSlot = animSlots[ slotIdx ];
   1.103 +
   1.104 +               masterFunction_MultiLang( currSlot );
   1.105 +             }
   1.106 +                  MEAS__Capture_Post_Master_Point;
   1.107 +            masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
   1.108 +            flushRegisters();
   1.109 +          }
   1.110 +       }
   1.111 +    }
   1.112 + }
   1.113 +
   1.114 +
   1.115          
   1.116  //=====================  The versions of the Animation Master  =================
   1.117  //
   1.118 @@ -71,7 +160,7 @@
   1.119   * order that application code in the slaves executes.
   1.120   * 
   1.121   *To control order of animation of slaves, the request handler has a
   1.122 - * semantic environment that holds data structures used to hold slaves
   1.123 + * language environment that holds data structures used to hold slaves
   1.124   * and choose when they're ready to be animated.
   1.125   *
   1.126   *Once a slave is marked as ready to be animated by the request handler,
   1.127 @@ -93,23 +182,23 @@
   1.128   *==========================================================================
   1.129   *In summary, the animationMaster scans the slots, finds slaves
   1.130   * just-finished, which hold requests, pass those to the request handler,
   1.131 - * along with the semantic environment, and the request handler then manages
   1.132 - * the structures in the semantic env, which controls the order of
   1.133 + * along with the language environment, and the request handler then manages
   1.134 + * the structures in the language env, which controls the order of
   1.135   * animation of slaves, and so embodies the behavior of the language
   1.136   * constructs.
   1.137   *The animationMaster then rescans the slots, offering each empty one to
   1.138 - * the Assigner, along with the semantic environment.  The Assigner chooses
   1.139 - * among the ready slaves in the semantic Env, finding the one best suited
   1.140 + * the Assigner, along with the language environment.  The Assigner chooses
   1.141 + * among the ready slaves in the language env, finding the one best suited
   1.142   * to be animated by that slot's associated core.
   1.143   * 
   1.144   *==========================================================================
   1.145   *Implementation Details:
   1.146   * 
   1.147 - *There is a separate masterVP for each core, but a single semantic
   1.148 + *There is a separate masterVP for each core, but a single language
   1.149   * environment shared by all cores.  Each core also has its own scheduling
   1.150   * slots, which are used to communicate slaves between animationMaster and
   1.151   * coreController.  There is only one global variable, _PRTopEnv, which
   1.152 - * holds the semantic env and other things shared by the different
   1.153 + * holds the language env and other things shared by the different
   1.154   * masterVPs.  The request handler and Assigner are registered with
   1.155   * the animationMaster by the language's init function, and a pointer to
   1.156   * each is in the _PRTopEnv. (There are also some pthread related global
   1.157 @@ -128,7 +217,7 @@
   1.158   *The core controllers access _PRTopEnv to get the masterVP, and when
   1.159   * they start, the slots are all empty, so they run their associated core's
   1.160   * masterVP.  The first of those to get the master lock sees the seed slave
   1.161 - * in the shared semantic environment, so when it runs the Assigner, that
   1.162 + * in the shared language environment, so when it runs the Assigner, that
   1.163   * returns the seed slave, which the animationMaster puts into a scheduling
   1.164   * slot then switches to the core controller.  That then switches the core
   1.165   * over to the seed slave, which then proceeds to execute language
   1.166 @@ -148,246 +237,100 @@
   1.167   * executing the animationMaster code, which drives for more than one. In
   1.168   * practice, the best balance should be discovered by profiling.
   1.169   */
   1.170 -void animationMaster( void *initData, SlaveVP *masterVP )
   1.171 +/*
   1.172 +void masterFunction_StandaloneSlavesOnly( AnimSlot  *slot )
   1.173   { 
   1.174 -      //Used while scanning and filling animation slots
   1.175 -   int32           slotIdx, numSlotsFilled;
   1.176 -   AnimSlot      *currSlot, **animSlots;
   1.177 -   SlaveVP        *assignedSlaveVP;  //the slave chosen by the assigner
   1.178 -
   1.179 -      //Local copies, for performance
   1.180 -   MasterEnv      *masterEnv;
   1.181 -   SlaveAssigner   slaveAssigner;
   1.182 -   RequestHandler  requestHandler;
   1.183 -   void           *semanticEnv;
   1.184 -   int32           thisCoresIdx;
   1.185 -  
   1.186 -   //======================== Initializations ========================
   1.187 -   masterEnv        = (MasterEnv*)_PRTopEnv;
   1.188 -   
   1.189 -   thisCoresIdx     = masterVP->coreAnimatedBy;
   1.190 -   animSlots       = masterEnv->allAnimSlots[thisCoresIdx];
   1.191 -
   1.192 -   requestHandler   = masterEnv->requestHandler;
   1.193 -   slaveAssigner    = masterEnv->slaveAssigner;
   1.194 -   semanticEnv      = masterEnv->semanticEnv;
   1.195 -   
   1.196 -      HOLISTIC__Insert_Master_Global_Vars;
   1.197 +   SlaveVP        *slave;
   1.198 +   PRReqst        *req;
   1.199 +   PRLangEnv      *langEnv = _PRTopEnv->langEnv;
   1.200 +    
   1.201     
   1.202     //======================== animationMaster ========================
   1.203 -   while(1){
   1.204 -       
   1.205 -      MEAS__Capture_Pre_Master_Point
   1.206 +      
   1.207 +      //Check if newly-done slave in slot, which will need request handled
   1.208 +   if( slot->workIsDone )
   1.209 +    { slot->workIsDone = FALSE;
   1.210 +      slot->needsWorkAssigned = TRUE;
   1.211  
   1.212 -      //Scan the animation slots
   1.213 -   numSlotsFilled = 0;
   1.214 -   for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
   1.215 -    {
   1.216 -      currSlot = animSlots[ slotIdx ];
   1.217  
   1.218 -         //Check if newly-done slave in slot, which will need request handled
   1.219 -      if( currSlot->workIsDone )
   1.220 -       {
   1.221 -         currSlot->workIsDone         = FALSE;
   1.222 -         currSlot->needsWorkAssigned = TRUE;
   1.223 -         
   1.224 -       HOLISTIC__Record_AppResponder_start;
   1.225 -               MEAS__startReqHdlr;
   1.226 -               
   1.227 -           currSlot->workIsDone         = FALSE;
   1.228 -            currSlot->needsWorkAssigned = TRUE;
   1.229 -            SlaveVP *currSlave = currSlot->slaveAssignedToSlot;
   1.230 -            
   1.231 -	justAddedReqHdlrChg();
   1.232 -			//handle the request, either by PR or by the language
   1.233 -            if( currSlave->requests->reqType != LangReq )
   1.234 -             {    //The request is a standard PR one, not one defined by the
   1.235 -                  // language, so PR handles it, then queues slave to be assigned
   1.236 -               handleReqInPR( currSlave );
   1.237 -               writePrivQ( currSlave, PRReadyQ ); //Q slave to be assigned below
   1.238 -             }
   1.239 -            else
   1.240 -             {       MEAS__startReqHdlr;
   1.241 +            HOLISTIC__Record_AppResponder_start;
   1.242 +            MEAS__startReqHdlr;
   1.243 +         //process the request made by the slave (held inside slave struc)
   1.244 +      slave = slot->slaveAssignedToSlot;
   1.245 +      req = slave->request;
   1.246  
   1.247 -                  //Language handles request, which is held inside slave struc
   1.248 -               (*requestHandler)( currSlave, semanticEnv );
   1.249 -
   1.250 -                     MEAS__endReqHdlr;
   1.251 -             }
   1.252 -          }
   1.253 -
   1.254 -		  //process the requests made by the slave (held inside slave struc)
   1.255 -         (*requestHandler)( currSlot->slaveAssignedToSlot, semanticEnv );
   1.256 -         
   1.257 -         HOLISTIC__Record_AppResponder_end;
   1.258 -               MEAS__endReqHdlr;
   1.259 -       }
   1.260 -         //If slot empty, hand to Assigner to fill with a slave
   1.261 -      if( currSlot->needsWorkAssigned )
   1.262 -       {    //Call plugin's Assigner to give slot a new slave
   1.263 -          HOLISTIC__Record_Assigner_start;
   1.264 -         assignedSlaveVP =
   1.265 -          (*slaveAssigner)( semanticEnv, currSlot );
   1.266 -         
   1.267 -            //put the chosen slave into slot, and adjust flags and state
   1.268 -         if( assignedSlaveVP != NULL )
   1.269 -          { currSlot->slaveAssignedToSlot = assignedSlaveVP;
   1.270 -            assignedSlaveVP->animSlotAssignedTo       = currSlot;
   1.271 -            currSlot->needsWorkAssigned  = FALSE;
   1.272 -            numSlotsFilled               += 1;
   1.273 -            
   1.274 -            HOLISTIC__Record_Assigner_end;
   1.275 +      //Handle task create and end first -- they're special cases..
   1.276 +      switch( req->reqType )
   1.277 +       { case SlvCreate:    PRHandle_CreateSlave( slave );           break;
   1.278 +         case SlvDissipate: PRHandle_Dissipate( slave );             break;
   1.279 +         case Service:      PR_int__handle_PRServiceReq( slave );    break; //resume into PR's own language env
   1.280 +         case Hardware: //for future expansion
   1.281 +         case IO:       //for future expansion
   1.282 +         case OSCall:   //for future expansion
   1.283 +            PR_int__throw_exception("Not implemented");             break;
   1.284 +         case Language: //normal lang request
   1.285 +          { 
   1.286 +            (*langEnv->requestHdlr)( req->langReq, slave, langEnv );
   1.287            }
   1.288         }
   1.289 +            HOLISTIC__Record_AppResponder_end;
   1.290 +            MEAS__endReqHdlr;
   1.291      }
   1.292 +      //If slot empty, hand to Assigner to fill with a slave
   1.293 +   if( slot->needsWorkAssigned )
   1.294 +    {    //Call plugin's Assigner to give slot a new slave
   1.295 +            HOLISTIC__Record_Assigner_start;
   1.296  
   1.297 -         MEAS__Capture_Post_Master_Point;
   1.298 +      if( langEnv->hasWork )
   1.299 +       {  (*langEnv->slaveAssigner)( langEnv, slot ); //calls PR fn that inserts work into slot
   1.300 +         goto ReturnAfterAssigningWork; //quit for-loop, cause found work
   1.301 +       }
   1.302 +      else
   1.303 +         goto NoWork;
   1.304 +    }
   1.305     
   1.306 -   masterSwitchToCoreCtlr( masterVP );
   1.307 -   flushRegisters();
   1.308 -         DEBUG__printf(FALSE,"came back after switch to core -- so lock released!");
   1.309 -   }//while(1) 
   1.310 + NoWork:
   1.311 +      //No work, if reach here..
   1.312 +    { 
   1.313 +   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   1.314 +      coreNum = slot->coreSlotIsOn;
   1.315 +      returnSlv = process->idleSlv[coreNum][slotNum]; 
   1.316 +    
   1.317 +         //things that would normally happen in resume(), but idle VPs
   1.318 +         // never go there
   1.319 +      returnSlv->numTimesAssignedToASlot++; //gives each idle unit a unique ID
   1.320 +      Unit newU;
   1.321 +      newU.vp = returnSlv->slaveNum;
   1.322 +      newU.task = returnSlv->numTimesAssignedToASlot;
   1.323 +      addToListOfArrays(Unit,newU,process->unitList);
   1.324 +
   1.325 +      if (returnSlv->numTimesAssignedToASlot > 1) //make a dependency from prev idle unit
   1.326 +       { Dependency newD;             // to this one
   1.327 +         newD.from_vp = returnSlv->slaveNum;
   1.328 +         newD.from_task = returnSlv->numTimesAssignedToASlot - 1;
   1.329 +         newD.to_vp = returnSlv->slaveNum;
   1.330 +         newD.to_task = returnSlv->numTimesAssignedToASlot;
   1.331 +         addToListOfArrays(Dependency, newD ,process->ctlDependenciesList);  
   1.332 +       }
   1.333 +   #endif
   1.334 +            HOLISTIC__Record_Assigner_end;
   1.335 +      return;
   1.336 +    }
   1.337 + 
   1.338 + ReturnAfterAssigningWork:  //All paths goto here.. to provide single point for holistic..
   1.339 +    {
   1.340 +            HOLISTIC__Record_Assigner_end;
   1.341 +      return;
   1.342 +    }
   1.343   }
   1.344 -
   1.345 -
   1.346 -/* 2)  This version is for a single language that has only tasks, which 
   1.347 - *     cannot be suspended.
   1.348 - */
   1.349 -void animationMaster( void *initData, SlaveVP *masterVP )
   1.350 - { 
   1.351 -      //Used while scanning and filling animation slots
   1.352 -   int32           slotIdx, numSlotsFilled;
   1.353 -   AnimSlot       *currSlot, **animSlots;
   1.354 -   SlaveVP        *assignedSlaveVP;  //the slave chosen by the assigner
   1.355 -   
   1.356 -      //Local copies, for performance
   1.357 -   MasterEnv      *masterEnv;
   1.358 -   SlaveAssigner   slaveAssigner;
   1.359 -   RequestHandler  requestHandler;
   1.360 -   PRSemEnv       *semanticEnv;
   1.361 -   int32           thisCoresIdx;
   1.362 -
   1.363 -   //#ifdef  MODE__MULTI_LANG
   1.364 -   SlaveVP        *slave;
   1.365 -   PRProcess      *process;
   1.366 -   int32           langMagicNumber;
   1.367 -   //#endif
   1.368 -   
   1.369 -   //======================== Initializations ========================
   1.370 -   masterEnv        = (MasterEnv*)_PRTopEnv;
   1.371 -   
   1.372 -   thisCoresIdx     = masterVP->coreAnimatedBy;
   1.373 -   animSlots        = masterEnv->allAnimSlots[thisCoresIdx];
   1.374 -
   1.375 -   requestHandler   = masterEnv->requestHandler;
   1.376 -   slaveAssigner    = masterEnv->slaveAssigner;
   1.377 -   semanticEnv      = masterEnv->semanticEnv;
   1.378 -   
   1.379 -      //initialize, for non-multi-lang, non multi-proc case
   1.380 -      // default handler gets put into master env by a registration call by lang
   1.381 -   endTaskHandler   = masterEnv->defaultTaskHandler;
   1.382 -   
   1.383 -      HOLISTIC__Insert_Master_Global_Vars;
   1.384 -   
   1.385 -   //======================== animationMaster ========================
   1.386 -   //Do loop gets requests handled and work assigned to slots..
   1.387 -   // work can either be a task or a resumed slave
   1.388 -   //Having two cases makes this logic complex.. can be finishing either, and 
   1.389 -   // then the next available work may be either.. so really have two distinct
   1.390 -   // loops that are inter-twined.. 
   1.391 -   while(1){
   1.392 -       
   1.393 -      MEAS__Capture_Pre_Master_Point
   1.394 -
   1.395 -      //Scan the animation slots
   1.396 -   numSlotsFilled = 0;
   1.397 -   for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
   1.398 -    {
   1.399 -      currSlot = animSlots[ slotIdx ];
   1.400 -
   1.401 -         //Check if newly-done slave in slot, which will need request handled
   1.402 -      if( currSlot->workIsDone )
   1.403 -       { currSlot->workIsDone = FALSE;
   1.404 -       
   1.405 -               HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot
   1.406 -               MEAS__startReqHdlr;
   1.407 -               
   1.408 -         
   1.409 -            //process the request made by the slave (held inside slave struc)
   1.410 -         slave = currSlot->slaveAssignedToSlot;
   1.411 -         
   1.412 -            //check if the completed work was a task..
   1.413 -         if( slave->metaTask->isATask )
   1.414 -          {
   1.415 -             if( slave->request->type == TaskEnd ) 
   1.416 -              {    //do task end handler, which is registered separately
   1.417 -                   //note, end hdlr may use semantic data from reqst..
   1.418 -                //#ifdef  MODE__MULTI_LANG
   1.419 -                   //get end-task handler
   1.420 -                //taskEndHandler = lookup( slave->reqst->langMagicNumber, processEnv );
   1.421 -                taskEndHandler = slave->metaTask->endTaskHandler;
   1.422 -                //#endif
   1.423 -                (*taskEndHandler)( slave, semanticEnv );
   1.424 -                
   1.425 -                goto AssignWork;
   1.426 -              }
   1.427 -             else  //is a task, and just suspended
   1.428 -              {    //turn slot slave into free task slave & make replacement
   1.429 -                if( slave->typeOfVP == SlotTaskSlv ) changeSlvType();
   1.430 -                
   1.431 -                //goto normal slave request handling
   1.432 -                goto SlaveReqHandling; 
   1.433 -              }
   1.434 -          }
   1.435 -         else //is a slave that suspended
   1.436 -          {
   1.437 -          SlaveReqHandling:
   1.438 -            (*requestHandler)( slave, semanticEnv ); //(note: indirect Fn call more efficient when use fewer params, instead re-fetch from slave)
   1.439 -         
   1.440 -               HOLISTIC__Record_AppResponder_end;
   1.441 -               MEAS__endReqHdlr;
   1.442 -               
   1.443 -            goto AssignWork;
   1.444 -          }
   1.445 -       } //if has suspended slave that needs handling
   1.446 -      
   1.447 -         //if slot empty, hand to Assigner to fill with a slave
   1.448 -      if( currSlot->needsWorkAssigned )
   1.449 -       {    //Call plugin's Assigner to give slot a new slave
   1.450 -               HOLISTIC__Record_Assigner_start;
   1.451 -               
   1.452 -       AssignWork:
   1.453 -     
   1.454 -         assignedSlaveVP = assignWork( semanticEnv, currSlot );
   1.455 -       
   1.456 -            //put the chosen slave into slot, and adjust flags and state
   1.457 -         if( assignedSlaveVP != NULL )
   1.458 -          { currSlot->slaveAssignedToSlot = assignedSlaveVP;
   1.459 -            assignedSlaveVP->animSlotAssignedTo = currSlot;
   1.460 -            currSlot->needsWorkAssigned  = FALSE;
   1.461 -            numSlotsFilled               += 1;
   1.462 -          }
   1.463 -         else
   1.464 -          {
   1.465 -            currSlot->needsWorkAssigned  = TRUE; //local write
   1.466 -          }
   1.467 -               HOLISTIC__Record_Assigner_end;
   1.468 -       }//if slot needs slave assigned
   1.469 -    }//for( slotIdx..
   1.470 -
   1.471 -         MEAS__Capture_Post_Master_Point;
   1.472 -   
   1.473 -   masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
   1.474 -   flushRegisters();
   1.475 -   }//while(1) 
   1.476 - }
   1.477 +*/
   1.478  
   1.479  
   1.480  /*This is the master when just multi-lang, but not multi-process mode is on.
   1.481   * This version has to handle both tasks and slaves, and do extra work of 
   1.482 - * looking up the semantic env and handlers to use, for each completed bit of 
   1.483 + * looking up the language env and handlers to use, for each completed bit of 
   1.484   * work.
   1.485 - *It also has to search through the semantic envs to find one with work,
   1.486 + *It also has to search through the language envs to find one with work,
   1.487   * then ask that env's assigner to return a unit of that work.
   1.488   * 
   1.489   *The language is written to startup in the same way as if it were the only
   1.490 @@ -429,9 +372,9 @@
   1.491   * 
   1.492   *The multi-lang thing complicates matters..  
   1.493   *
   1.494 - *For request handling, it means have to first fetch the semantic environment
   1.495 + *For request handling, it means have to first fetch the language environment
   1.496   * of the language, and then do the request handler pointed to by that
   1.497 - * semantic env.
   1.498 + * language env.
   1.499   *For assigning, things get more complex because of competing goals..  One
   1.500   * goal is for language specific stuff to be used during assignment, so
   1.501   * assigner can make higher quality decisions..  but with multiple languages,
   1.502 @@ -452,9 +395,9 @@
   1.503   * queue at a time..  but this is quite hack-like.. or perhaps HWSim supplies
   1.504   * a task-end handler that kicks the next unit of work from HWSim internal
   1.505   * priority queue, over to PR readyQ)
   1.506 - *2) can have each language have its own semantic env, that holds its own
   1.507 + *2) can have each language have its own language env, that holds its own
   1.508   * work, which is assigned by its own assigner.. then the master searches
   1.509 - * through all the semantic envs to find one with work and asks it give work..
   1.510 + * through all the language envs to find one with work and asks it give work..
   1.511   * (this has downside of blinding assigners to each other.. but does work
   1.512   * for HWSim case)
   1.513   *3) could make PR have a different readyQ for each core, and ask the lang
   1.514 @@ -477,383 +420,217 @@
   1.515   * the languages in a unified way..  Don't really expect this to happen, 
   1.516   * but making it possible.
   1.517   */
   1.518 -#ifdef  MODE__MULTI_LANG
   1.519 -void animationMaster( void *initData, SlaveVP *masterVP )
   1.520 - { 
   1.521 -      //Used while scanning and filling animation slots
   1.522 -   int32           slotIdx, numSlotsFilled;
   1.523 -   AnimSlot       *currSlot, **animSlots;
   1.524 -   SlaveVP        *assignedSlaveVP;  //the slave chosen by the assigner
   1.525 +/*
   1.526 +inline
   1.527 +void 
   1.528 +masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot )
   1.529 + {    //Scan the animation slots
   1.530 +   SlaveVP        *slave;
   1.531 +   PRReqst        *req;
   1.532 +
   1.533 +      //Check if newly-done slave in slot, which will need request handled
   1.534 +   if( slot->workIsDone )
   1.535 +    { slot->workIsDone = FALSE;
   1.536 +      slot->needsWorkAssigned = TRUE;
   1.537 +
   1.538 +            HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot
   1.539 +            MEAS__startReqHdlr;
   1.540 +
   1.541 +
   1.542 +         //process the request made by the slave (held inside slave struc)
   1.543 +      slave = slot->slaveAssignedToSlot;
   1.544 +      req = slave->request;
   1.545 +
   1.546 +         //If the requesting slave is a slot slave, and request is not
   1.547 +         // task-end, then turn it into a free task slave. 
   1.548 +      if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd )
   1.549 +         PR_int__replace_with_new_slot_slv( slave );
   1.550 +
   1.551 +      //Handle task create and end first -- they're special cases..
   1.552 +      switch( req->reqType )
   1.553 +       { case TaskEnd: 
   1.554 +          { //do PR handler, which calls lang's hdlr and does recycle of
   1.555 +            // free task slave if needed -- PR handler checks for free task Slv
   1.556 +            PRHandle_EndTask_SL( slave );                            break;
   1.557 +          }
   1.558 +         case TaskCreate:
   1.559 +          { //Do PR's create-task handler, which calls the lang's hdlr
   1.560 +            // PR handler checks for free task Slv
   1.561 +            PRHandle_CreateTask_SL( slave );                         break;
   1.562 +          }
   1.563 +         case SlvCreate:    PRHandle_CreateSlave_SL( slave );        break;
   1.564 +         case SlvDissipate: PRHandle_Dissipate_SL( slave );          break;
   1.565 +         case Service:      PR_int__handle_PRServiceReq_SL( slave ); break; //resume into PR's own language env
   1.566 +         case Hardware: //for future expansion
   1.567 +         case IO:       //for future expansion
   1.568 +         case OSCall:   //for future expansion
   1.569 +            PR_int__throw_exception("Not implemented", slave, NULL); break;
   1.570 +         case Language: //normal lang request
   1.571 +          { 
   1.572 +            (*protoLangEnv->requestHdlr)( req->langReq, slave, (void*)PR_int__give_lang_env(protoLangEnv ));
   1.573 +          }
   1.574 +       }
   1.575 +              
   1.576 +            MEAS__endReqHdlr;          
   1.577 +            HOLISTIC__Record_AppResponder_end;
   1.578 +    } //if have request to be handled
   1.579 +
   1.580 +      //If slot empty, hand to Assigner to fill with a slave
   1.581 +   if( slot->needsWorkAssigned )
   1.582 +    {    //Call plugin's Assigner to give slot a new slave
   1.583 +            HOLISTIC__Record_Assigner_start;
   1.584 +
   1.585 +      if( protoLangEnv->hasWork )
   1.586 +       {  (*protoLangEnv->slaveAssigner)( protoLangEnv, slot ); //calls PR fn that inserts work into slot
   1.587 +         goto ReturnAfterAssigningWork; //quit for-loop, cause found work
   1.588 +       }
   1.589 +      else
   1.590 +         goto NoWork;
   1.591 +    }
   1.592     
   1.593 -      //Local copies, for performance
   1.594 -   MasterEnv      *masterEnv;
   1.595 -   SlaveAssigner   slaveAssigner;
   1.596 -   RequestHandler  requestHandler;
   1.597 -   PRSemEnv       *semanticEnv;
   1.598 -   int32           thisCoresIdx;
   1.599 + NoWork:
   1.600 +      //No work, if reach here..
   1.601 +    { 
   1.602 +   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   1.603 +      coreNum = slot->coreSlotIsOn;
   1.604 +      returnSlv = process->idleSlv[coreNum][slotNum]; 
   1.605 +    
   1.606 +         //things that would normally happen in resume(), but idle VPs
   1.607 +         // never go there
   1.608 +      returnSlv->numTimesAssignedToASlot++; //gives each idle unit a unique ID
   1.609 +      Unit newU;
   1.610 +      newU.vp = returnSlv->slaveNum;
   1.611 +      newU.task = returnSlv->numTimesAssignedToASlot;
   1.612 +      addToListOfArrays(Unit,newU,process->unitList);
   1.613  
   1.614 -   //#ifdef  MODE__MULTI_LANG
   1.615 -   SlaveVP        *slave;
   1.616 -   PRProcess      *process;
   1.617 -   int32           langMagicNumber;
   1.618 -   //#endif
   1.619 -   
   1.620 -   //======================== Initializations ========================
   1.621 -   masterEnv        = (MasterEnv*)_PRTopEnv;
   1.622 -   
   1.623 -   thisCoresIdx     = masterVP->coreAnimatedBy;
   1.624 -   animSlots        = masterEnv->allAnimSlots[thisCoresIdx];
   1.625 -
   1.626 -   requestHandler   = masterEnv->requestHandler;
   1.627 -   slaveAssigner    = masterEnv->slaveAssigner;
   1.628 -   semanticEnv      = masterEnv->semanticEnv;
   1.629 -   
   1.630 -      //initialize, for non-multi-lang, non multi-proc case
   1.631 -      // default handler gets put into master env by a registration call by lang
   1.632 -   endTaskHandler   = masterEnv->defaultTaskHandler;
   1.633 -   
   1.634 -      HOLISTIC__Insert_Master_Global_Vars;
   1.635 -   
   1.636 -   //======================== animationMaster ========================
   1.637 -   //Do loop gets requests handled and work assigned to slots..
   1.638 -   // work can either be a task or a resumed slave
   1.639 -   //Having two cases makes this logic complex.. can be finishing either, and 
   1.640 -   // then the next available work may be either.. so really have two distinct
   1.641 -   // loops that are inter-twined.. 
   1.642 -   while(1){
   1.643 -       
   1.644 -      MEAS__Capture_Pre_Master_Point
   1.645 -
   1.646 -      //Scan the animation slots
   1.647 -   numSlotsFilled = 0;
   1.648 -   for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
   1.649 +      if (returnSlv->numTimesAssignedToASlot > 1) //make a dependency from prev idle unit
   1.650 +       { Dependency newD;             // to this one
   1.651 +         newD.from_vp = returnSlv->slaveNum;
   1.652 +         newD.from_task = returnSlv->numTimesAssignedToASlot - 1;
   1.653 +         newD.to_vp = returnSlv->slaveNum;
   1.654 +         newD.to_task = returnSlv->numTimesAssignedToASlot;
   1.655 +         addToListOfArrays(Dependency, newD ,process->ctlDependenciesList);  
   1.656 +       }
   1.657 +   #endif
   1.658 +            HOLISTIC__Record_Assigner_end;
   1.659 +      return;
   1.660 +    }
   1.661 + 
   1.662 + ReturnAfterAssigningWork:  //All paths goto here.. to provide single point for holistic..
   1.663      {
   1.664 -      currSlot = animSlots[ slotIdx ];
   1.665 -
   1.666 -         //Check if newly-done slave in slot, which will need request handled
   1.667 -      if( currSlot->workIsDone )
   1.668 -       { currSlot->workIsDone = FALSE;
   1.669 -       
   1.670 -               HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot
   1.671 -               MEAS__startReqHdlr;
   1.672 -               
   1.673 -         
   1.674 -            //process the request made by the slave (held inside slave struc)
   1.675 -         slave = currSlot->slaveAssignedToSlot;
   1.676 -         
   1.677 -            //check if the completed work was a task..
   1.678 -         if( slave->taskMetaInfo->isATask )
   1.679 -          {
   1.680 -             if( slave->reqst->type == TaskEnd ) 
   1.681 -              {    //do task end handler, which is registered separately
   1.682 -                   //note, end hdlr may use semantic data from reqst..
   1.683 -                //#ifdef  MODE__MULTI_LANG
   1.684 -                   //get end-task handler
   1.685 -                //taskEndHandler = lookup( slave->reqst->langMagicNumber, processEnv );
   1.686 -                taskEndHandler = slave->taskMetaInfo->endTaskHandler;
   1.687 -                //#endif
   1.688 -                (*taskEndHandler)( slave, semanticEnv );
   1.689 -                
   1.690 -                goto AssignWork;
   1.691 -              }
   1.692 -             else  //is a task, and just suspended
   1.693 -              {    //turn slot slave into free task slave & make replacement
   1.694 -                if( slave->typeOfVP == SlotTaskSlv ) changeSlvType();
   1.695 -                
   1.696 -                //goto normal slave request handling
   1.697 -                goto SlaveReqHandling; 
   1.698 -              }
   1.699 -          }
   1.700 -         else //is a slave that suspended
   1.701 -          {
   1.702 -          SlaveReqHandling:
   1.703 -            (*requestHandler)( slave, semanticEnv ); //(note: indirect Fn call more efficient when use fewer params, instead re-fetch from slave)
   1.704 -         
   1.705 -               HOLISTIC__Record_AppResponder_end;
   1.706 -               MEAS__endReqHdlr;
   1.707 -               
   1.708 -            goto AssignWork;
   1.709 -          }
   1.710 -       } //if has suspended slave that needs handling
   1.711 -      
   1.712 -         //if slot empty, hand to Assigner to fill with a slave
   1.713 -      if( currSlot->needsWorkAssigned )
   1.714 -       {    //Call plugin's Assigner to give slot a new slave
   1.715 -               HOLISTIC__Record_Assigner_start;
   1.716 -               
   1.717 -       AssignWork:
   1.718 -     
   1.719 -         assignedSlaveVP = assignWork( semanticEnv, currSlot );
   1.720 -       
   1.721 -            //put the chosen slave into slot, and adjust flags and state
   1.722 -         if( assignedSlaveVP != NULL )
   1.723 -          { currSlot->slaveAssignedToSlot = assignedSlaveVP;
   1.724 -            assignedSlaveVP->animSlotAssignedTo = currSlot;
   1.725 -            currSlot->needsWorkAssigned  = FALSE;
   1.726 -            numSlotsFilled               += 1;
   1.727 -          }
   1.728 -         else
   1.729 -          {
   1.730 -            currSlot->needsWorkAssigned  = TRUE; //local write
   1.731 -          }
   1.732 -               HOLISTIC__Record_Assigner_end;
   1.733 -       }//if slot needs slave assigned
   1.734 -    }//for( slotIdx..
   1.735 -
   1.736 -         MEAS__Capture_Post_Master_Point;
   1.737 -   
   1.738 -   masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
   1.739 -   flushRegisters();
   1.740 -   }//while(1) 
   1.741 - }
   1.742 -#endif //MODE__MULTI_LANG
   1.743 -
   1.744 -
   1.745 -
   1.746 -//This is the master when both multi-lang and multi-process modes are turned on
   1.747 -//#ifdef MODE__MULTI_LANG
   1.748 -//#ifdef MODE__MULTI_PROCESS
   1.749 -void animationMaster( void *initData, SlaveVP *masterVP )
   1.750 - { 
   1.751 -   int32           slotIdx;
   1.752 -   AnimSlot       *currSlot;
   1.753 -      //Used while scanning and filling animation slots
   1.754 -   AnimSlot      **animSlots;
   1.755 -   
   1.756 -      //Local copies, for performance
   1.757 -   MasterEnv      *masterEnv;
   1.758 -   int32           thisCoresIdx;
   1.759 -   
   1.760 -   //======================== Initializations ========================
   1.761 -   masterEnv        = (MasterEnv*)_PRTopEnv;
   1.762 -   
   1.763 -   thisCoresIdx     = masterVP->coreAnimatedBy;
   1.764 -   animSlots        = masterEnv->allAnimSlots[thisCoresIdx];
   1.765 -      
   1.766 -      HOLISTIC__Insert_Master_Global_Vars;
   1.767 -   
   1.768 -   //======================== animationMaster ========================
   1.769 -   //Do loop gets requests handled and work assigned to slots..
   1.770 -   // work can either be a task or a resumed slave
   1.771 -   //Having two cases makes this logic complex.. can be finishing either, and 
   1.772 -   // then the next available work may be either.. so really have two distinct
   1.773 -   // loops that are inter-twined.. 
   1.774 -   while(1)
   1.775 -    {  
   1.776 -            MEAS__Capture_Pre_Master_Point
   1.777 -      
   1.778 -      for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
   1.779 -       {
   1.780 -         currSlot = animSlots[ slotIdx ];
   1.781 -
   1.782 -         masterFunction_multiLang( currSlot );
   1.783 -       }
   1.784 -            
   1.785 -            MEAS__Capture_Post_Master_Point;
   1.786 -    
   1.787 -      masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
   1.788 -      flushRegisters();
   1.789 -    } 
   1.790 - }
   1.791 -#endif  //MODE__MULTI_LANG
   1.792 -#endif  //MODE__MULTI_PROCESS
   1.793 -
   1.794 -
   1.795 -//This version of the master selects one of three loops, depending upon
   1.796 -// whether stand-alone single language (just slaves), or standalone with
   1.797 -// tasks, or multi-lang (implies multi-process)
   1.798 -void animationMaster( void *initData, SlaveVP *masterVP )
   1.799 - { 
   1.800 -   int32           slotIdx;
   1.801 -   AnimSlot       *currSlot;
   1.802 -      //Used while scanning and filling animation slots
   1.803 -   AnimSlot      **animSlots;
   1.804 -   
   1.805 -      //Local copies, for performance
   1.806 -   MasterEnv      *masterEnv;
   1.807 -   int32           thisCoresIdx;
   1.808 -   
   1.809 -   //======================== Initializations ========================
   1.810 -   masterEnv        = (MasterEnv*)_PRTopEnv;
   1.811 -   
   1.812 -   thisCoresIdx     = masterVP->coreAnimatedBy;
   1.813 -   animSlots        = masterEnv->allAnimSlots[thisCoresIdx];
   1.814 -      
   1.815 -      HOLISTIC__Insert_Master_Global_Vars;
   1.816 -   
   1.817 -   //======================== animationMaster ========================
   1.818 -   //Have three different modes, and the master behavior is different for
   1.819 -   // each, so jump to the loop that corresponds to the mode.
   1.820 -   //
   1.821 -   switch(mode)
   1.822 -    { case StandaloneSlavesOnly: 
   1.823 -         while(1)
   1.824 -          {       MEAS__Capture_Pre_Master_Point
   1.825 -            for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
   1.826 -             {
   1.827 -               currSlot = animSlots[ slotIdx ];
   1.828 -
   1.829 -               masterFunction_StandaloneSlavesOnly( currSlot );
   1.830 -             }
   1.831 -                  MEAS__Capture_Post_Master_Point;
   1.832 -            masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
   1.833 -            flushRegisters();
   1.834 -          } 
   1.835 -      case StandaloneWTasks:     
   1.836 -         while(1)
   1.837 -          {       MEAS__Capture_Pre_Master_Point
   1.838 -            for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
   1.839 -             {
   1.840 -               currSlot = animSlots[ slotIdx ];
   1.841 -
   1.842 -               masterFunction_StandaloneWTasks( currSlot );
   1.843 -             }
   1.844 -                  MEAS__Capture_Post_Master_Point;
   1.845 -            masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
   1.846 -            flushRegisters();
   1.847 -          }
   1.848 -      case MultiLang:
   1.849 -         while(1)
   1.850 -          {       MEAS__Capture_Pre_Master_Point
   1.851 -            for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
   1.852 -             {
   1.853 -               currSlot = animSlots[ slotIdx ];
   1.854 -
   1.855 -               masterFunction_multiLang( currSlot );
   1.856 -             }
   1.857 -                  MEAS__Capture_Post_Master_Point;
   1.858 -            masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
   1.859 -            flushRegisters();
   1.860 -          } 
   1.861 +            HOLISTIC__Record_Assigner_end;
   1.862 +      return;
   1.863      }
   1.864   }
   1.865 -
   1.866 +*/
   1.867  
   1.868  inline
   1.869  void
   1.870 -masterFunction_multiLang( AnimSlot  *currSlot )
   1.871 +masterFunction_MultiLang( AnimSlot  *slot )
   1.872   {    //Scan the animation slots
   1.873     int32           magicNumber;
   1.874     SlaveVP        *slave;
   1.875 -   SlaveVP        *assignedSlaveVP;
   1.876 -   PRSemEnv       *semanticEnv;
   1.877 +   PRLangEnv      *langEnv;
   1.878     PRReqst        *req;
   1.879     RequestHandler  requestHandler;
   1.880 +   PRProcess      *process;
   1.881  
   1.882 -         //Check if newly-done slave in slot, which will need request handled
   1.883 -      if( currSlot->workIsDone )
   1.884 -       { currSlot->workIsDone = FALSE;
   1.885 -         currSlot->needsWorkAssigned = TRUE;
   1.886 -       
   1.887 -               HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot
   1.888 -               MEAS__startReqHdlr;
   1.889 -               
   1.890 -         
   1.891 -            //process the request made by the slave (held inside slave struc)
   1.892 -         slave = currSlot->slaveAssignedToSlot;
   1.893 -         req = slave->request;
   1.894 +      //Check if newly-done slave in slot, which will need request handled
   1.895 +   if( slot->workIsDone )
   1.896 +    { slot->workIsDone = FALSE;
   1.897 +      slot->needsWorkAssigned = TRUE;
   1.898  
   1.899 -            //If the requesting slave is a slot slave, and request is not
   1.900 -            // task-end, then turn it into a free task slave. 
   1.901 -         if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd )
   1.902 -            replaceWithNewSlotSlv( slave );
   1.903 +            HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot
   1.904 +            MEAS__startReqHdlr;
   1.905  
   1.906 -         //Handle task create and end first -- they're special cases..
   1.907 -         switch( req->reqType )
   1.908 -          { case TaskEnd: 
   1.909 -             { //do PR handler, which calls lang's hdlr and does recycle of
   1.910 -               // free task slave if needed -- PR handler checks for free task Slv
   1.911 -               PRHandle_EndTask( slave );                               break;
   1.912 -             }
   1.913 -            case TaskCreate:
   1.914 -             { //Do PR's create-task handler, which calls the lang's hdlr
   1.915 -               // PR handler checks for free task Slv
   1.916 -               PRHandle_CreateTask( slave );                            break;
   1.917 -             }
   1.918 -            case SlvCreate:    PRHandle_CreateSlave( slave );           break;
   1.919 -            case SlvDissipate: PRHandle_Dissipate( slave );             break;
   1.920 -            case Service:      PR_int__handle_PRServiceReq( slave );    break; //resume into PR's own semantic env
   1.921 -            case Hardware: //for future expansion
   1.922 -            case IO:       //for future expansion
   1.923 -            case OSCall:   //for future expansion
   1.924 -                PR_int__throw_exception("Not implemented");             break;
   1.925 -            case Language: //normal sem request
   1.926 -              magicNumber = req->langMagicNumber;
   1.927 -              semanticEnv = PR_PI__give_sem_env_for( slave, magicNumber );
   1.928 -              requestHandler = semanticEnv->requestHdlr;
   1.929 -              (*requestHandler)( req->semReq, slave, semanticEnv );
   1.930 +
   1.931 +         //process the request made by the slave (held inside slave struc)
   1.932 +      slave = slot->slaveAssignedToSlot;
   1.933 +      req = slave->request;
   1.934 +
   1.935 +         //If the requesting slave is a slot slave, and request is not
   1.936 +         // task-end, then turn it into a free task slave. 
   1.937 +      if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd )
   1.938 +         PR_int__replace_with_new_slot_slv( slave );
   1.939 +
   1.940 +      //Handle task create and end first -- they're special cases..
   1.941 +      switch( req->reqType )
   1.942 +       { case TaskEnd: 
   1.943 +          { //do PR handler, which calls lang's hdlr and does recycle of
   1.944 +            // free task slave if needed -- PR handler checks for free task Slv
   1.945 +            PRHandle_EndTask( req, slave );                          break;
   1.946            }
   1.947 +         case TaskCreate:
   1.948 +          { //Do PR's create-task handler, which calls the lang's hdlr
   1.949 +            // PR handler checks for free task Slv
   1.950 +            PRHandle_CreateTask( req, slave );                       break;
   1.951 +          }
   1.952 +         case SlvCreate:    PRHandle_CreateSlave( req, slave );      break;
   1.953 +         case SlvDissipate: PRHandle_Dissipate( req, slave );        break;
   1.954 +         case Service:      PR_int__handle_PRServiceReq( slave );    break; //resume into PR's own language env
   1.955 +         case Hardware: //for future expansion
   1.956 +         case IO:       //for future expansion
   1.957 +         case OSCall:   //for future expansion
   1.958 +            PR_int__throw_exception("Not implemented", slave, NULL); break;
   1.959 +         case Language: //normal lang request
   1.960 +          { magicNumber = req->langMagicNumber;
   1.961 +            langEnv = PR_PI__give_lang_env_for( slave, magicNumber );
   1.962 +            (*req->handler)( req->langReq, slave, langEnv );
   1.963 +          }
   1.964 +       }
   1.965  
   1.966 +           MEAS__endReqHdlr;          
   1.967             HOLISTIC__Record_AppResponder_end;
   1.968 -           MEAS__endReqHdlr;          
   1.969 -       } //if have request to be handled
   1.970 -      
   1.971 -      if( currSlot->needsWorkAssigned )
   1.972 -       {
   1.973 -               HOLISTIC__Record_Assigner_start;
   1.974 -                  
   1.975 -            //Scan sem environs, looking for semEnv with ready work.
   1.976 -            // call the Assigner for that sem Env, to get a slave for the slot
   1.977 -         assignedSlaveVP = assignWork( semanticEnv, currSlot );
   1.978 -       
   1.979 -            //if work found, put into slot, and adjust flags and state
   1.980 -         if( assignedSlaveVP != NULL )
   1.981 -          { currSlot->slaveAssignedToSlot = assignedSlaveVP;
   1.982 -            assignedSlaveVP->animSlotAssignedTo = currSlot;
   1.983 -            currSlot->needsWorkAssigned  = FALSE;
   1.984 -          }
   1.985 -               HOLISTIC__Record_Assigner_end;
   1.986 -       }//if slot needs slave assigned
   1.987 +    } //if have request to be handled
   1.988 +
   1.989 +   if( slot->needsWorkAssigned )
   1.990 +    {
   1.991 +            HOLISTIC__Record_Assigner_start;
   1.992 +
   1.993 +         //Pick a process to get this slot
   1.994 +      process = pickAProcess( slot );
   1.995 +
   1.996 +         //Scan lang environs, looking for langEnv with ready work.
   1.997 +         // call the Assigner for that lang Env, to get a slave for the slot
   1.998 +      assignWork( process, slot );
   1.999 +
  1.1000 +            HOLISTIC__Record_Assigner_end;
  1.1001 +    }//if slot needs slave assigned
  1.1002   }
  1.1003  
  1.1004 -//==========================================================================
  1.1005 -/*When a task in a slot slave suspends, the slot slave has to be changed to
  1.1006 - * a free task slave, then the slot slave replaced.  The replacement can be
  1.1007 - * either a recycled free task slave that finished it's task and has been
  1.1008 - * idle in the recycle queue, or else create a new slave to be the slot slave.
  1.1009 - *The master only calls this with a slot slave that needs to be replaced.
  1.1010 +/*When several processes exist, use some pattern for picking one to give
  1.1011 + * the animation slot to.
  1.1012 + *First, it has to be a process that has work available.
  1.1013 + *For now, just do a round-robin
  1.1014   */
  1.1015 -inline void
  1.1016 -replaceWithNewSlotSlv( SlaveVP *requestingSlv, PRProcess *process )
  1.1017 - { SlaveVP *newSlotSlv;
  1.1018 -
  1.1019 - When slot slave converted to a free task slave, insert the process pointer -- slot slaves are not assigned to any process;
  1.1020 - 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.1021 -
  1.1022 -      //get a new slave to be the slot slave
  1.1023 -   newSlotSlv     = readPrivQ( process->freeTaskSlvRecycleQ );
  1.1024 -   if( newSlotSlv == NULL )
  1.1025 -    { newSlotSlv  = PR_int__create_slaveVP( &idle_fn, NULL, process, 0);
  1.1026 -         //just made a new free task slave, so count it
  1.1027 -      process->numLiveFreeTaskSlvs += 1;
  1.1028 +inline
  1.1029 +PRProcess *
  1.1030 +pickAProcess( AnimSlot *slot )
  1.1031 + { int32 idx;
  1.1032 +   PRProcess *process;
  1.1033 + 
  1.1034 +   for( idx = _PRTopEnv->currProcessIdx; idx < _PRTopEnv->numProcesses; idx++)
  1.1035 +    {
  1.1036 +      process = _PRTopEnv->processes[ idx ];
  1.1037 +      if( process->numEnvsWithWork != 0 )
  1.1038 +       { _PRTopEnv->currProcessIdx = idx;
  1.1039 +         return process;
  1.1040 +       }
  1.1041      }
  1.1042 -   
  1.1043 -      //set slave values to make it the slot slave
  1.1044 -   newSlotSlv->metaTask              = NULL;
  1.1045 -   newSlotSlv->typeOfVP              = SlotTaskSlv;
  1.1046 -//   newSlotSlv->needsTaskAssigned     = TRUE;
  1.1047 -   
  1.1048 -      //a slot slave is pinned to a particular slot on a particular core
  1.1049 -      //Note, this happens before the request is seen by handler, so nothing
  1.1050 -      // has had a chance to change the coreAnimatedBy or anything else..
  1.1051 -   newSlotSlv->animSlotAssignedTo = requestingSlv->animSlotAssignedTo;
  1.1052 -   newSlotSlv->coreAnimatedBy     = requestingSlv->coreAnimatedBy;
  1.1053 -    
  1.1054 -      //put it into the slot slave matrix
  1.1055 -   int32 slotNum = requestingSlv->animSlotAssignedTo->slotIdx;
  1.1056 -   int32 coreNum = requestingSlv->coreAnimatedBy;
  1.1057 -   process->slotTaskSlvs[coreNum][slotNum] = newSlotSlv;
  1.1058 -
  1.1059 -      //Fix up requester, to be an extra slave now (but not an ended one)
  1.1060 -      // because it's active, doesn't go into freeTaskSlvRecycleQ
  1.1061 -   requestingSlv->typeOfVP = FreeTaskSlv;
  1.1062 -   requestingSlv->metaTask->taskType = FreeTask;
  1.1063 +   for( idx = 0; idx < _PRTopEnv->currProcessIdx; idx++)
  1.1064 +    {
  1.1065 +      process = _PRTopEnv->processes[ idx ];
  1.1066 +      if( process->numEnvsWithWork != 0 )
  1.1067 +       { _PRTopEnv->currProcessIdx = idx;
  1.1068 +         return process;
  1.1069 +       }
  1.1070 +    }
  1.1071 +      //none found
  1.1072 +   return NULL;
  1.1073   }
  1.1074  
  1.1075 -
  1.1076 -
  1.1077  /*This does:
  1.1078 - * 1) searches the semantic environments for one with work ready
  1.1079 + * 1) searches the language environments for one with work ready
  1.1080   *    if finds one, asks its assigner to return work
  1.1081   * 2) checks what kind of work: new task, resuming task, resuming slave
  1.1082   *    if new task, gets the slot slave and assigns task to it and returns slave
  1.1083 @@ -861,10 +638,10 @@
  1.1084   * 3) if no work found, then prune former task slaves waiting to be recycled.
  1.1085   *    If no work and no slaves to prune, check for shutdown conditions.
  1.1086   * 
  1.1087 - * Semantic env keeps its own work in its own structures, and has its own
  1.1088 + * language env keeps its own work in its own structures, and has its own
  1.1089   *  assigner.  It chooses 
  1.1090   * However, include a switch that switches-in an override assigner, which
  1.1091 - *  sees all the work in all the semantic env's.  This is most likely  
  1.1092 + *  sees all the work in all the language env's.  This is most likely  
  1.1093   *  generated by static tools and included in the executable.  That means it
  1.1094   *  has to be called via a registered pointer from here.  The idea is that
  1.1095   *  the static tools know which languages are grouped together.. and the
  1.1096 @@ -872,7 +649,8 @@
  1.1097   *  all the languages in a unified way..  Don't really expect this to happen,
  1.1098   *  but am making it possible.
  1.1099   */
  1.1100 -inline SlaveVP *
  1.1101 +inline 
  1.1102 +SlaveVP *
  1.1103  assignWork( PRProcess *process, AnimSlot *slot )
  1.1104   { SlaveVP        *returnSlv;
  1.1105     int32           coreNum, slotNum;
  1.1106 @@ -881,147 +659,75 @@
  1.1107     coreNum = slot->coreSlotIsOn;
  1.1108     
  1.1109     if( process->overrideAssigner != NULL )
  1.1110 -    { assignedMetaTask = (*process->overrideAssigner)( process, slot );
  1.1111 -      if( assignedMetaTask != NULL )
  1.1112 -       {
  1.1113 -            //have work, so reset Done flag (caused by work generated on other core)
  1.1114 -//         if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf
  1.1115 -//            process->coreIsDone[coreNum] = FALSE;   //don't just write always
  1.1116 -         
  1.1117 -//         switch( assignedMetaTask->taskType )
  1.1118 -//          { case GenericSlave:  goto AssignSlave;
  1.1119 -//            case FreeTask:      goto AssignSlave;
  1.1120 -//            case SlotTask:      goto AssignNewTask;
  1.1121 -//            default:      PR_int__throw_exception( "unknown task type ret by assigner" );
  1.1122 -//          }
  1.1123 -            //If meta task has a slave attached, then goto assign slave,
  1.1124 -            // else it's a new task, so goto where assign it to a slot slave
  1.1125 -         if( assignedMetaTask->slaveAssignedTo != NULL )
  1.1126 -            goto AssignSlave;
  1.1127 -         else
  1.1128 -            goto AssignNewTask;
  1.1129 +    { if( process->numEnvsWithWork != 0 )
  1.1130 +       {  (*process->overrideAssigner)( process, slot ); //calls PR fn that inserts work into slot
  1.1131 +         goto ReturnAfterAssigningWork; //quit for-loop, cause found work
  1.1132         }
  1.1133 -      else //metaTask is NULL, so no work..
  1.1134 +      else
  1.1135           goto NoWork;
  1.1136      }
  1.1137     
  1.1138 -      //If here, then no override assigner, so search semantic envs for work
  1.1139 -   int32 envIdx, numEnvs; PRSemEnv **semEnvs, *semEnv; SlaveAssigner assigner;
  1.1140 -   semEnvs = process->semEnvs;
  1.1141 -   numEnvs = process->numSemEnvs;
  1.1142 -   for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep semEnvs in hash & array
  1.1143 -    { semEnv = semEnvs[envIdx];
  1.1144 -      if( semEnv->hasWork )
  1.1145 -       { assigner = semEnv->slaveAssigner; 
  1.1146 -         assignedMetaTask = (*assigner)( semEnv, slot );
  1.1147 -         
  1.1148 -            //have work, so reset Done flag (caused by work generated on other core)
  1.1149 -//         if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf
  1.1150 -//            process->coreIsDone[coreNum] = FALSE;   //don't just write always
  1.1151 -         
  1.1152 -//         switch( assignedMetaTask->taskType )
  1.1153 -//          { case GenericSlave: goto AssignSlave;
  1.1154 -//            case FreeTask:     goto AssignSlave;
  1.1155 -//            case SlotTask:     goto AssignNewTask;
  1.1156 -//            default:      PR_int__throw_exception( "unknown task type ret by assigner" );
  1.1157 -//          }
  1.1158 -            //If meta task has a slave attached, then goto assign slave,
  1.1159 -            // else it's a new task, so goto where assign it to a slot slave
  1.1160 -         if( assignedMetaTask->slaveAssignedTo != NULL )
  1.1161 -            goto AssignSlave;
  1.1162 -         else
  1.1163 -            goto AssignNewTask;
  1.1164 +      //If here, then no override assigner, so search language envs for work
  1.1165 +   int32 envIdx, numEnvs; PRLangEnv **langEnvsList, *langEnv;
  1.1166 +   langEnvsList = process->langEnvsList;
  1.1167 +   numEnvs = process->numLangEnvs;
  1.1168 +   for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep langEnvs in hash & array
  1.1169 +    { langEnv = langEnvsList[envIdx];
  1.1170 +      if( langEnv->hasWork )
  1.1171 +       { (*langEnv->slaveAssigner)( langEnv, slot ); //assigner calls PR to put slave/task into slot
  1.1172 +         goto ReturnAfterAssigningWork; //quit for-loop, cause found work
  1.1173 +         //NOTE: bad search alg -- should start where left off, then wrap around
  1.1174         }
  1.1175      }
  1.1176 -   //If reach here, then have searched all semEnv's & none have work..
  1.1177 +   //If reach here, then have searched all langEnv's & none have work..
  1.1178     
  1.1179 - NoWork:
  1.1180 -      //No work, if reach here..
  1.1181 -    { goto ReturnTheSlv;
  1.1182 -    }
  1.1183 - 
  1.1184 - AssignSlave: //Have a metaTask attached to a slave, so get the slave & ret it
  1.1185 -    { returnSlv = assignedMetaTask->slaveAssignedTo;
  1.1186 -      returnSlv->coreAnimatedBy   = coreNum;
  1.1187 -    
  1.1188 -      goto ReturnTheSlv;
  1.1189 -    }
  1.1190 - 
  1.1191 - AssignNewTask: //Have a new metaTask that has no slave yet.. assign to slot slv
  1.1192 + NoWork:     //No work, if end up here..
  1.1193      { 
  1.1194 -         //get the slot slave to assign the task to..
  1.1195 -      slotNum = slot->slotIdx;
  1.1196 -      returnSlv = process->slotTaskSlvs[coreNum][slotNum];
  1.1197 -
  1.1198 -         //point slave to task's function
  1.1199 -      PR_int__reset_slaveVP_to_TopLvlFn( returnSlv, 
  1.1200 -                       assignedMetaTask->topLevelFn, assignedMetaTask->initData );
  1.1201 -      returnSlv->metaTask = assignedMetaTask;
  1.1202 -      assignedMetaTask->slaveAssignedTo = returnSlv;
  1.1203 -//      returnSlv->needsTaskAssigned = FALSE;  //slot slave is a "Task" slave type
  1.1204 -      
  1.1205 -         //have work, so reset Done flag, if was set
  1.1206 -//      if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf
  1.1207 -//         process->coreIsDone[coreNum] = FALSE;   //don't just write always
  1.1208 -      
  1.1209 -      goto ReturnTheSlv;
  1.1210 -    }
  1.1211 - 
  1.1212 -
  1.1213 - ReturnTheSlv:  //All paths goto here.. to provide single point for holistic..
  1.1214 -
  1.1215     #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  1.1216 -   if( returnSlv == NULL )
  1.1217 -    { returnSlv = process->idleSlv[coreNum][slotNum]; 
  1.1218 +      returnSlv = process->idleSlv[coreNum][slotNum]; 
  1.1219      
  1.1220           //things that would normally happen in resume(), but idle VPs
  1.1221           // never go there
  1.1222        returnSlv->numTimesAssignedToASlot++; //gives each idle unit a unique ID
  1.1223        Unit newU;
  1.1224 -      newU.vp = returnSlv->slaveID;
  1.1225 +      newU.vp = returnSlv->slaveNum;
  1.1226        newU.task = returnSlv->numTimesAssignedToASlot;
  1.1227        addToListOfArrays(Unit,newU,process->unitList);
  1.1228  
  1.1229        if (returnSlv->numTimesAssignedToASlot > 1) //make a dependency from prev idle unit
  1.1230         { Dependency newD;             // to this one
  1.1231 -         newD.from_vp = returnSlv->slaveID;
  1.1232 +         newD.from_vp = returnSlv->slaveNum;
  1.1233           newD.from_task = returnSlv->numTimesAssignedToASlot - 1;
  1.1234 -         newD.to_vp = returnSlv->slaveID;
  1.1235 +         newD.to_vp = returnSlv->slaveNum;
  1.1236           newD.to_task = returnSlv->numTimesAssignedToASlot;
  1.1237           addToListOfArrays(Dependency, newD ,process->ctlDependenciesList);  
  1.1238         }
  1.1239 +   #endif
  1.1240 +            HOLISTIC__Record_Assigner_end;
  1.1241 +      return;
  1.1242      }
  1.1243 -   else //have a slave will be assigned to the slot
  1.1244 -    { //assignSlv->numTimesAssigned++;
  1.1245 -         //get previous occupant of the slot
  1.1246 -      Unit prev_in_slot = 
  1.1247 -         process->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum];
  1.1248 -      if(prev_in_slot.vp != 0) //if not first slave in slot, make dependency
  1.1249 -       { Dependency newD;      // is a hardware dependency
  1.1250 -         newD.from_vp = prev_in_slot.vp;
  1.1251 -         newD.from_task = prev_in_slot.task;
  1.1252 -         newD.to_vp = returnSlv->slaveID;
  1.1253 -         newD.to_task = returnSlv->numTimesAssignedToASlot;
  1.1254 -         addToListOfArrays(Dependency,newD,process->hwArcs);   
  1.1255 -       }
  1.1256 -      prev_in_slot.vp = returnSlv->slaveID; //make new slave the new previous
  1.1257 -      prev_in_slot.task = returnSlv->numTimesAssignedToASlot;
  1.1258 -      process->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum] =
  1.1259 -         prev_in_slot;        
  1.1260 + 
  1.1261 + ReturnAfterAssigningWork:  //All paths goto here.. to provide single point for holistic..
  1.1262 +    {
  1.1263 +            HOLISTIC__Record_Assigner_end;
  1.1264 +      return;
  1.1265      }
  1.1266 -   #endif
  1.1267 -
  1.1268 -   return( returnSlv );
  1.1269   }
  1.1270  
  1.1271  
  1.1272 -/*In creator, only PR related things happen, and things in the langlet whose
  1.1273 +
  1.1274 +/*This is first thing called when creating a slave..  it hands off to the 
  1.1275 + * langlet's creator, then adds updates of its own..
  1.1276 + * 
  1.1277 + *There's a question of things like lang data, meta tasks, and such..
  1.1278 + *In creator, only PR related things happen, and things for the langlet whose
  1.1279   * creator construct was used.
  1.1280 - *Other langlet still gets a chance to create semData -- but by registering a
  1.1281 - * "createSemData" handler in the semEnv.  When a construct  of the langlet
  1.1282 - * calls "PR__give_sem_data()", if there is no semData for that langlet,
  1.1283 - * the PR will call the creator in the langlet's semEnv, place whatever it
  1.1284 - * makes as the semData in that slave for that langlet, and return that semData
  1.1285 + * 
  1.1286 + *Other langlets still get a chance to create langData -- but by registering a
  1.1287 + * "createLangData" handler in the langEnv.  When a construct  of the langlet
  1.1288 + * calls "PR__give_lang_data()", if there is no langData for that langlet,
  1.1289 + * the PR will call the creator in the langlet's langEnv, place whatever it
  1.1290 + * makes as the langData in that slave for that langlet, and return that langData
  1.1291   *
  1.1292   *So, as far as counting things, a langlet is only allowed to count creation
  1.1293   * of slaves it creates itself..  may have to change this later.. add a way for
  1.1294 @@ -1034,87 +740,92 @@
  1.1295   *PR itself needs to create the slave, then update numLiveSlaves in process,
  1.1296   * copy processID from requestor to newly created
  1.1297   */
  1.1298 -PRHandle_CreateSlave( PRReqst *req, SlaveVP *requestingSlv )
  1.1299 - { SlaveVP *newSlv;
  1.1300 -   PRMetaTask metaTask;
  1.1301 +inline
  1.1302 +void
  1.1303 +PRHandle_CreateSlave( PRReqst *req, SlaveVP *slave )
  1.1304 + { SlaveVP   *newSlv;
  1.1305     PRProcess *process;
  1.1306 +   PRLangEnv *protoLangEnv;
  1.1307   
  1.1308 -   process = requestingSlv->processSlaveIsIn;
  1.1309 -   newSlv = PR_int__create_slaveVP();
  1.1310 +   process = slave->processSlaveIsIn;
  1.1311 +   protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, req->langMagicNumber );
  1.1312 +   
  1.1313 +//   newSlv  = PR_int__create_slave( req->topLevelFn, req->initData );
  1.1314 +   
  1.1315 +   //create slv has diff prototype than standard reqst hdlr
  1.1316 +   newSlv = 
  1.1317 +      (*req->createHdlr)(req->langReq, slave, PR_int__give_lang_env(protoLangEnv)); 
  1.1318 +   
  1.1319     newSlv->typeOfVP = GenericSlv;
  1.1320     newSlv->processSlaveIsIn = process;
  1.1321 +   newSlv->ID = req->ID;
  1.1322     process->numLiveGenericSlvs += 1;
  1.1323 -   metaTask = PR_int__create_slave_meta_task();
  1.1324 -   metaTask->taskID = req->ID;
  1.1325 -//   metaTask->taskType = GenericSlave;
  1.1326 -   
  1.1327 -   (*req->handler)( req->semReq, newSlv, requestingSlv, semEnv );
  1.1328   }
  1.1329  
  1.1330 -/*The dissipate handler has to, sdate the number of slaves of the type, within
  1.1331 +/*The dissipate handler has to, update the number of slaves of the type, within
  1.1332   * the process, and call the langlet handler linked into the request,
  1.1333   * and after that returns, then call the PR function that frees the slave state
  1.1334   * (or recycles the slave).
  1.1335   * 
  1.1336   *The PR function that frees the slave state has to also free all of the
  1.1337 - * semData in the slave..  or else reset all of the semDatas.. by, say, marking
  1.1338 - * them, then in PR__give_semData( magicNum ) call the langlet registered
  1.1339 - * "resetSemData" Fn.
  1.1340 + * langData in the slave..  or else reset all of the langDatas.. by, say, marking
  1.1341 + * them, then in PR__give_langData( magicNum ) call the langlet registered
  1.1342 + * "resetLangData" Fn.
  1.1343   */
  1.1344 -PRHandle_Dissipate( SlaveVP *slave )
  1.1345 +inline
  1.1346 +void
  1.1347 +PRHandle_Dissipate( PRReqst *req, SlaveVP *slave )
  1.1348   { PRProcess *process;
  1.1349 -   void      *semEnv;
  1.1350 +   PRLangEnv *protoLangEnv;
  1.1351     
  1.1352     process = slave->processSlaveIsIn;
  1.1353     
  1.1354        //do the language's dissipate handler
  1.1355 -   semEnv = PR_int__give_sem_env_for_slave( slave, slave->request->langMagicNumber );
  1.1356 -   (*slave->request->handler)( slave->request->semReq, slave, semEnv );
  1.1357 +   protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, slave->request->langMagicNumber );
  1.1358 +   
  1.1359 +   if(req->handler != NULL)
  1.1360 +      (*req->handler)( req->langReq, slave, PR_int__give_lang_env(protoLangEnv) );
  1.1361     
  1.1362     process->numLiveGenericSlvs -= 1;
  1.1363 -   PR_int__recycle_slave_multilang( requestingSlv );
  1.1364 +   PR_int__recycle_slave__ML( slave );
  1.1365    
  1.1366        //check End Of Process Condition
  1.1367     if( process->numLiveTasks == 0 &&
  1.1368         process->numLiveGenericSlvs == 0 )
  1.1369 -      PR_SS__shutdown_process( process );
  1.1370 +      PR_SS__shutdown_process__ML( process );
  1.1371   }
  1.1372  
  1.1373  /*Create task is a special form, that has PR behavior in addition to plugin
  1.1374 - * behavior.  Master calls this first, and then calls the plugin's
  1.1375 + * behavior.  Master calls this first, and it then calls the plugin's
  1.1376   * create task handler.
  1.1377   * 
  1.1378   *Note: the requesting slave must be either generic slave or free task slave
  1.1379   */
  1.1380 -inline PRMetaTask *
  1.1381 -PRHandle_CreateTask( PRReqst *req, SlaveVP *requestingSlv )
  1.1382 +inline
  1.1383 +void
  1.1384 +PRHandle_CreateTask( PRReqst *req, SlaveVP *slave )
  1.1385   { PRMetaTask     *metaTask;
  1.1386     PRProcess      *process;
  1.1387 -   PRLangMetaTask *langMetaTask;
  1.1388 -   PRSemEnv       *semanticEnv;
  1.1389 +   PRLangEnv      *protoLangEnv;
  1.1390 +   void           *task;
  1.1391                  
  1.1392 -   process = requestingSlv->processSlaveIsIn;
  1.1393 -
  1.1394 -   metaTask             = PR_int__create_meta_task( req );
  1.1395 -   metaTask->taskID     = req->ID; //may be NULL
  1.1396 +   process = slave->processSlaveIsIn;
  1.1397 +   
  1.1398 +   protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, 
  1.1399 +                                                        req->langMagicNumber );
  1.1400 +   
  1.1401 +   //Do the langlet's create-task handler, which keeps the task
  1.1402 +   // inside the langlet's lang env, but returns the langMetaTask
  1.1403 +   // so PR can put stuff into the prolog
  1.1404 +   task = 
  1.1405 +      (*req->createHdlr)(req->langReq, slave, PR_int__give_lang_env(protoLangEnv) );
  1.1406 +   metaTask = PR_int__give_prolog_of_task( task );
  1.1407 +   metaTask->ID         = req->ID; //may be NULL
  1.1408     metaTask->topLevelFn = req->topLevelFn;
  1.1409     metaTask->initData   = req->initData;
  1.1410             
  1.1411     process->numLiveTasks += 1;
  1.1412  
  1.1413 -   semanticEnv = PR_int__give_sem_env_for_slave( slave, 
  1.1414 -                                          req->langMagicNumber );
  1.1415 -   
  1.1416 -   //Do the langlet's create-task handler, which keeps the task
  1.1417 -   // inside the langlet's sem env, but returns the langMetaTask
  1.1418 -   // so PR can hook it to the PRMetaTask.
  1.1419 -   //(Could also do PRMetaTask as a prolog -- make a Fn that takes the size
  1.1420 -   // of the lang's metaTask, and alloc's that plus the prolog and returns
  1.1421 -   // ptr to position just above the prolog)
  1.1422 -   langMetaTask = (*req->handler)(req->semReq, slave, semanticEnv);
  1.1423 -   metaTask->langMetaTask      = langMetaTask;
  1.1424 -   langMetaTask->protoMetaTask = metaTask;
  1.1425 -
  1.1426     return;
  1.1427   }
  1.1428  
  1.1429 @@ -1125,7 +836,7 @@
  1.1430   * so, here, don't worry about assigning a new task to the slot slave.
  1.1431   *For 2, the task's slot slave has been converted to a free task slave, which
  1.1432   * now has nothing more to do, so send it to the recycle Q (which includes
  1.1433 - * freeing all the semData and meta task structs alloc'd for it).  Then
  1.1434 + * freeing all the langData and meta task structs alloc'd for it).  Then
  1.1435   * decrement the live task count and check end condition.
  1.1436   * 
  1.1437   *PR has to update count of live tasks, and check end of process condition.
  1.1438 @@ -1141,31 +852,31 @@
  1.1439   * 
  1.1440   *Note: slave may be either a slot slave or a free task slave. 
  1.1441   */
  1.1442 -inline void
  1.1443 -PRHandle_EndTask( SlaveVP *requestingSlv )
  1.1444 - { void       *semEnv;
  1.1445 -   PRReqst    *req;  
  1.1446 -   PRLangMetaTask *langMetaTask;
  1.1447 +inline 
  1.1448 +void
  1.1449 +PRHandle_EndTask( PRReqst *req, SlaveVP *requestingSlv )
  1.1450 + { void       *langEnv;
  1.1451     PRProcess  *process;
  1.1452 +   void       *langMetaTask;
  1.1453     
  1.1454 -   req = requestingSlv->request;
  1.1455 -   semEnv = PR_int__give_sem_env_of_req( req, requestingSlv ); //magic num in req
  1.1456 -   langMetaTask = requestingSlv->metaTask->langMetaTask;
  1.1457 +   langEnv = PR_int__give_lang_env_of_req__ML( req, requestingSlv ); //magic num in req
  1.1458 +   langMetaTask = PR_int__give_lang_meta_task_from_slave__ML( requestingSlv, req->langMagicNumber);
  1.1459     
  1.1460     //Do the langlet's request handler
  1.1461 -   //Want to keep PR structs hidden from plugin, so extract semReq..
  1.1462 -   (*req->handler)( langMetaTask, req->semReq, semEnv );
  1.1463 +   //Want to keep PR structs hidden from plugin, so extract langReq..
  1.1464 +   (*req->handler)( req->langReq, requestingSlv, langEnv );
  1.1465     
  1.1466     //Now that the langlet's done with it, recycle the slave if it's a freeTaskSlv
  1.1467     if( requestingSlv->typeOfVP == FreeTaskSlv )
  1.1468 -      PR_int__recycle_slave_multilang( requestingSlv );
  1.1469 +      PR_int__recycle_slave__ML( requestingSlv );
  1.1470     
  1.1471     process->numLiveTasks -= 1;
  1.1472    
  1.1473        //check End Of Process Condition
  1.1474     if( process->numLiveTasks == 0 &&
  1.1475         process->numLiveGenericSlvs == 0 )
  1.1476 -      //Tell the core controller to do wakeup of any waiting OS thread
  1.1477 -      PR_SS__shutdown_process( process );
  1.1478 +    { //Tell the core controller to do wakeup of any waiting OS thread
  1.1479 +      PR_SS__shutdown_process__ML( process );
  1.1480 +    }
  1.1481   }
  1.1482