diff AnimationMaster.c @ 269:e6a68e7ea63f

Removed the extra level of core controller -- now only one anim slot and master called after every work unit
author Sean Halle <seanhalle@yahoo.com>
date Mon, 14 Jan 2013 16:10:37 -0800
parents e5bd470b562b
children 292393c6bef1
line diff
     1.1 --- a/AnimationMaster.c	Mon Jan 14 15:31:23 2013 -0800
     1.2 +++ b/AnimationMaster.c	Mon Jan 14 16:10:37 2013 -0800
     1.3 @@ -22,11 +22,11 @@
     1.4  inline void PRHandle_CreateTask( PRReqst *req, SlaveVP *slave );
     1.5  inline void PRHandle_EndTask(    PRReqst *req, SlaveVP *slave );
     1.6  inline void PRHandle_CreateSlave(PRReqst *req, SlaveVP *slave );
     1.7 -void        PRHandle_Dissipate(  PRReqst *req, SlaveVP *slave );
     1.8 +void        PRHandle_EndSlave(  PRReqst *req, SlaveVP *slave );
     1.9  
    1.10  
    1.11  //inline void  masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot );
    1.12 -inline void masterFunction_MultiLang( AnimSlot  *slot );
    1.13 +inline void masterFunction( AnimSlot  *slot );
    1.14  inline PRProcess * pickAProcess( AnimSlot *slot );
    1.15  inline SlaveVP * assignWork( PRProcess *process, AnimSlot *slot );
    1.16  
    1.17 @@ -78,461 +78,29 @@
    1.18     //Have three different modes, and the master behavior is different for
    1.19     // each, so jump to the loop that corresponds to the mode.
    1.20     //
    1.21 -   switch(masterEnv->mode)
    1.22 -    {
    1.23 -/*
    1.24 -    { case SingleLang: 
    1.25 -         while(1)
    1.26 -          {       MEAS__Capture_Pre_Master_Point
    1.27 -            for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
    1.28 -             {
    1.29 -               currSlot = animSlots[ slotIdx ];
    1.30 +   while(1)
    1.31 +    {       MEAS__Capture_Pre_Master_Point
    1.32 +      for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
    1.33 +       {
    1.34 +         currSlot = animSlots[ slotIdx ];
    1.35  
    1.36 -               masterFunction_StandaloneSlavesOnly( masterEnv, currSlot );
    1.37 -             }
    1.38 -                  MEAS__Capture_Post_Master_Point;
    1.39 -            masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
    1.40 -            flushRegisters();
    1.41 -          } 
    1.42 -
    1.43 -      case SingleLang:     
    1.44 -       { PRLangEnv  *protoLangEnv =  _PRTopEnv->protoLangEnv;
    1.45 -         while(1)
    1.46 -          {       MEAS__Capture_Pre_Master_Point
    1.47 -            for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
    1.48 -             {
    1.49 -               currSlot = animSlots[ slotIdx ];
    1.50 -
    1.51 -               masterFunction_SingleLang( protoLangEnv, currSlot );
    1.52 -             }
    1.53 -                  MEAS__Capture_Post_Master_Point;
    1.54 -            masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
    1.55 -            flushRegisters();
    1.56 -          }
    1.57 +         masterFunction( currSlot );
    1.58         }
    1.59 - */
    1.60 -      case MultiLang:
    1.61 -       { while(1)
    1.62 -          {       MEAS__Capture_Pre_Master_Point
    1.63 -            for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++)
    1.64 -             {
    1.65 -               currSlot = animSlots[ slotIdx ];
    1.66 -
    1.67 -               masterFunction_MultiLang( currSlot );
    1.68 -             }
    1.69 -                  MEAS__Capture_Post_Master_Point;
    1.70 -            masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
    1.71 -            flushRegisters();
    1.72 -          }
    1.73 -       }
    1.74 +            MEAS__Capture_Post_Master_Point;
    1.75 +      masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master
    1.76 +      flushRegisters();
    1.77      }
    1.78   }
    1.79  
    1.80  
    1.81 -        
    1.82 -//=====================  The versions of the Animation Master  =================
    1.83 -//
    1.84 -//==============================================================================
    1.85 -
    1.86 -/* 1) This version is for a single language, that has only slaves, no tasks,
    1.87 - *    such as Vthread or SSR.
    1.88 - *This version is for when an application has only a single language, and
    1.89 - * that language exposes slaves explicitly (as opposed to a task based 
    1.90 - * language like pure dataflow).
    1.91 - * 
    1.92 - *
    1.93 - *It scans the animation slots for just-completed slaves.
    1.94 - * Each completed slave has a request in it.  So, the master hands each to
    1.95 - * the plugin's request handler (there is only one plugin, because only one
    1.96 - * lang).
    1.97 - *Each request represents a language construct that has been encountered
    1.98 - * by the application code in the slave. Passing the request to the
    1.99 - * request handler is how that language construct's behavior gets invoked.
   1.100 - * The request handler then performs the actions of the construct's
   1.101 - * behavior. So, the request handler encodes the behavior of the 
   1.102 - * language's parallelism constructs, and performs that when the master
   1.103 - * hands it a slave containing a request to perform that construct.
   1.104 - * 
   1.105 - *On a shared-memory machine, the behavior of parallelism constructs
   1.106 - * equals control, over order of execution of code.  Hence, the behavior
   1.107 - * of the language constructs performed by the request handler is to 
   1.108 - * choose the order that slaves get animated, and thereby control the
   1.109 - * order that application code in the slaves executes.
   1.110 - * 
   1.111 - *To control order of animation of slaves, the request handler has a
   1.112 - * language environment that holds data structures used to hold slaves
   1.113 - * and choose when they're ready to be animated.
   1.114 - *
   1.115 - *Once a slave is marked as ready to be animated by the request handler,
   1.116 - * it is the second plugin function, the Assigner, which chooses the core
   1.117 - * the slave gets assigned to for animation.  Hence, the Assigner doesn't
   1.118 - * perform any of the semantic behavior of language constructs, rather
   1.119 - * it gives the language a chance to improve performance. The performance
   1.120 - * of application code is strongly related to communication between
   1.121 - * cores. On shared-memory machines, communication is caused during
   1.122 - * execution of code, by memory accesses, and how much depends on contents
   1.123 - * of caches connected to the core executing the code.  So, the placement
   1.124 - * of slaves determines the communication caused during execution of the
   1.125 - * slave's code.
   1.126 - *The point of the Assigner, then, is to use application information during
   1.127 - * execution of the program, to make choices about slave placement onto
   1.128 - * cores, with the aim to put slaves close to caches containing the data
   1.129 - * used by the slave's code.
   1.130 - * 
   1.131 - *==========================================================================
   1.132 - *In summary, the animationMaster scans the slots, finds slaves
   1.133 - * just-finished, which hold requests, pass those to the request handler,
   1.134 - * along with the language environment, and the request handler then manages
   1.135 - * the structures in the language env, which controls the order of
   1.136 - * animation of slaves, and so embodies the behavior of the language
   1.137 - * constructs.
   1.138 - *The animationMaster then rescans the slots, offering each empty one to
   1.139 - * the Assigner, along with the language environment.  The Assigner chooses
   1.140 - * among the ready slaves in the language env, finding the one best suited
   1.141 - * to be animated by that slot's associated core.
   1.142 - * 
   1.143 - *==========================================================================
   1.144 - *Implementation Details:
   1.145 - * 
   1.146 - *There is a separate masterVP for each core, but a single language
   1.147 - * environment shared by all cores.  Each core also has its own scheduling
   1.148 - * slots, which are used to communicate slaves between animationMaster and
   1.149 - * coreController.  There is only one global variable, _PRTopEnv, which
   1.150 - * holds the language env and other things shared by the different
   1.151 - * masterVPs.  The request handler and Assigner are registered with
   1.152 - * the animationMaster by the language's init function, and a pointer to
   1.153 - * each is in the _PRTopEnv. (There are also some pthread related global
   1.154 - * vars, but they're only used during init of PR).
   1.155 - *PR gains control over the cores by essentially "turning off" the OS's
   1.156 - * scheduler, using pthread pin-to-core commands.
   1.157 - *
   1.158 - *The masterVPs are created during init, with this animationMaster as their
   1.159 - * top level function.  The masterVPs use the same SlaveVP data structure,
   1.160 - * even though they're not slave VPs.
   1.161 - *A "seed slave" is also created during init -- this is equivalent to the
   1.162 - * "main" function in C, and acts as the entry-point to the PR-language-
   1.163 - * based application.
   1.164 - *The masterVPs share a single system-wide master-lock, so only one
   1.165 - * masterVP may be animated at a time.
   1.166 - *The core controllers access _PRTopEnv to get the masterVP, and when
   1.167 - * they start, the slots are all empty, so they run their associated core's
   1.168 - * masterVP.  The first of those to get the master lock sees the seed slave
   1.169 - * in the shared language environment, so when it runs the Assigner, that
   1.170 - * returns the seed slave, which the animationMaster puts into a scheduling
   1.171 - * slot then switches to the core controller.  That then switches the core
   1.172 - * over to the seed slave, which then proceeds to execute language
   1.173 - * constructs to create more slaves, and so on.  Each of those constructs
   1.174 - * causes the seed slave to suspend, switching over to the core controller,
   1.175 - * which eventually switches to the masterVP, which executes the 
   1.176 - * request handler, which uses PR primitives to carry out the creation of
   1.177 - * new slave VPs, which are marked as ready for the Assigner, and so on..
   1.178 - * 
   1.179 - *On animation slots, and system behavior:
   1.180 - * A request may linger in an animation slot for a long time while
   1.181 - * the slaves in the other slots are animated.  This only becomes a problem
   1.182 - * when such a request is a choke-point in the constraints, and is needed
   1.183 - * to free work for *other* cores.  To reduce this occurrence, the number
   1.184 - * of animation slots should be kept low.  In balance, having multiple
   1.185 - * animation slots amortizes the overhead of switching to the masterVP and
   1.186 - * executing the animationMaster code, which drives for more than one. In
   1.187 - * practice, the best balance should be discovered by profiling.
   1.188 - */
   1.189 -/*
   1.190 -void masterFunction_StandaloneSlavesOnly( AnimSlot  *slot )
   1.191 - { 
   1.192 -   SlaveVP        *slave;
   1.193 -   PRReqst        *req;
   1.194 -   PRLangEnv      *langEnv = _PRTopEnv->langEnv;
   1.195 -    
   1.196 -   
   1.197 -   //======================== animationMaster ========================
   1.198 -      
   1.199 -      //Check if newly-done slave in slot, which will need request handled
   1.200 -   if( slot->workIsDone )
   1.201 -    { slot->workIsDone = FALSE;
   1.202 -      slot->needsWorkAssigned = TRUE;
   1.203 -
   1.204 -
   1.205 -            HOLISTIC__Record_AppResponder_start;
   1.206 -            MEAS__startReqHdlr;
   1.207 -         //process the request made by the slave (held inside slave struc)
   1.208 -      slave = slot->slaveAssignedToSlot;
   1.209 -      req = slave->request;
   1.210 -
   1.211 -      //Handle task create and end first -- they're special cases..
   1.212 -      switch( req->reqType )
   1.213 -       { case SlvCreate:    PRHandle_CreateSlave( slave );           break;
   1.214 -         case SlvDissipate: PRHandle_Dissipate( slave );             break;
   1.215 -         case Service:      PR_int__handle_PRServiceReq( slave );    break; //resume into PR's own language env
   1.216 -         case Hardware: //for future expansion
   1.217 -         case IO:       //for future expansion
   1.218 -         case OSCall:   //for future expansion
   1.219 -            PR_int__throw_exception("Not implemented");             break;
   1.220 -         case Language: //normal lang request
   1.221 -          { 
   1.222 -            (*langEnv->requestHdlr)( req->langReq, slave, langEnv );
   1.223 -          }
   1.224 -       }
   1.225 -            HOLISTIC__Record_AppResponder_end;
   1.226 -            MEAS__endReqHdlr;
   1.227 -    }
   1.228 -      //If slot empty, hand to Assigner to fill with a slave
   1.229 -   if( slot->needsWorkAssigned )
   1.230 -    {    //Call plugin's Assigner to give slot a new slave
   1.231 -            HOLISTIC__Record_Assigner_start;
   1.232 -
   1.233 -      if( langEnv->hasWork )
   1.234 -       {  (*langEnv->slaveAssigner)( langEnv, slot ); //calls PR fn that inserts work into slot
   1.235 -         goto ReturnAfterAssigningWork; //quit for-loop, cause found work
   1.236 -       }
   1.237 -      else
   1.238 -         goto NoWork;
   1.239 -    }
   1.240 -   
   1.241 - NoWork:
   1.242 -      //No work, if reach here..
   1.243 -    { 
   1.244 -   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   1.245 -      coreNum = slot->coreSlotIsOn;
   1.246 -      returnSlv = process->idleSlv[coreNum][slotNum]; 
   1.247 -    
   1.248 -         //things that would normally happen in resume(), but idle VPs
   1.249 -         // never go there
   1.250 -      returnSlv->numTimesAssignedToASlot++; //gives each idle unit a unique ID
   1.251 -      Unit newU;
   1.252 -      newU.vp = returnSlv->slaveNum;
   1.253 -      newU.task = returnSlv->numTimesAssignedToASlot;
   1.254 -      addToListOfArrays(Unit,newU,process->unitList);
   1.255 -
   1.256 -      if (returnSlv->numTimesAssignedToASlot > 1) //make a dependency from prev idle unit
   1.257 -       { Dependency newD;             // to this one
   1.258 -         newD.from_vp = returnSlv->slaveNum;
   1.259 -         newD.from_task = returnSlv->numTimesAssignedToASlot - 1;
   1.260 -         newD.to_vp = returnSlv->slaveNum;
   1.261 -         newD.to_task = returnSlv->numTimesAssignedToASlot;
   1.262 -         addToListOfArrays(Dependency, newD ,process->ctlDependenciesList);  
   1.263 -       }
   1.264 -   #endif
   1.265 -            HOLISTIC__Record_Assigner_end;
   1.266 -      return;
   1.267 -    }
   1.268 - 
   1.269 - ReturnAfterAssigningWork:  //All paths goto here.. to provide single point for holistic..
   1.270 -    {
   1.271 -            HOLISTIC__Record_Assigner_end;
   1.272 -      return;
   1.273 -    }
   1.274 - }
   1.275 -*/
   1.276 -
   1.277 -
   1.278 -/*This is the master when just multi-lang, but not multi-process mode is on.
   1.279 - * This version has to handle both tasks and slaves, and do extra work of 
   1.280 - * looking up the language env and handlers to use, for each completed bit of 
   1.281 - * work.
   1.282 - *It also has to search through the language envs to find one with work,
   1.283 - * then ask that env's assigner to return a unit of that work.
   1.284 - * 
   1.285 - *The language is written to startup in the same way as if it were the only
   1.286 - * language in the app, and it operates in the same way,
   1.287 - * the only difference between single language and multi-lang is here, in the
   1.288 - * master.
   1.289 - *This invisibility to mode is why the language has to use registration calls
   1.290 - * for everything during startup -- those calls do different things depending
   1.291 - * on whether it's single-language or multi-language mode.
   1.292 - * 
   1.293 - *In this version of the master, work can either be a task or a resumed slave
   1.294 - *Having two cases makes this logic complex.. can be finishing either, and
   1.295 - * then the next available work may be either.. so really have two distinct 
   1.296 - * loops that are inter-twined.. 
   1.297 - * 
   1.298 - *Some special cases:
   1.299 - * A task-end is a special case for a few reasons (below).
   1.300 - * A task-end can't block a slave (can't cause it to "logically suspend")
   1.301 - * A task available for work can only be assigned to a special slave, which 
   1.302 - *   has been set aside for doing tasks, one such task-slave is always 
   1.303 - *   assigned to each slot. So, when a task ends, a new task is assigned to
   1.304 - *   that slot's task-slave right away.  
   1.305 - * But if no tasks are available, then have to switch over to looking at
   1.306 - *   slaves to find one ready to resume, to find work for the slot.
   1.307 - * If a task just suspends, not ends, then its task-slave is no longer 
   1.308 - *   available to take new tasks, so a new task-slave has to be assigned to
   1.309 - *   that slot.  Then the slave of the suspended task is turned into a free
   1.310 - *   task-slave and request handling is done on it as if it were a slave 
   1.311 - *   that suspended.
   1.312 - * After request handling, do the same sequence of looking for a task to be
   1.313 - *   work, and if none, look for a slave ready to resume, as work for the slot.
   1.314 - * If a slave suspends, handle its request, then look for work.. first for a
   1.315 - *   task to assign, and if none, slaves ready to resume.
   1.316 - * Another special case is when task-end is done on a free task-slave.. in
   1.317 - *   that case, the slave has no more work and no way to get more.. so place
   1.318 - *   it into a recycle queue.
   1.319 - * If no work is found of either type, then do a special thing to prune down
   1.320 - *   the extra slaves in the recycle queue, just so don't get too many..
   1.321 - * 
   1.322 - *The multi-lang thing complicates matters..  
   1.323 - *
   1.324 - *For request handling, it means have to first fetch the language environment
   1.325 - * of the language, and then do the request handler pointed to by that
   1.326 - * language env.
   1.327 - *For assigning, things get more complex because of competing goals..  One
   1.328 - * goal is for language specific stuff to be used during assignment, so
   1.329 - * assigner can make higher quality decisions..  but with multiple languages,
   1.330 - * which only get mixed in the application, the assigners can't be written
   1.331 - * with knowledge of each other.  So, they can only make localized decisions,
   1.332 - * and so different language's assigners may interfere with each other..
   1.333 - * 
   1.334 - *So, have some possibilities available:
   1.335 - *1) can have a fixed scheduler in the proto-runtime, that all the
   1.336 - * languages give their work to..  (but then lose language-specific info, 
   1.337 - * there is a standard PR format for assignment info, and the langauge 
   1.338 - * attaches this to the work-unit when it gives it to PR.. also have issue
   1.339 - * with HWSim, which uses a priority Q instead of FIFO, and requests can 
   1.340 - * "undo" previous work put in, so request handlers need way to manipulate
   1.341 - * the work-holding Q..) (this might be fudgeable with
   1.342 - * HWSim, if the master did a lang-supplied callback each time it assigns a
   1.343 - * unit to a slot..  then HWSim can keep exactly one unit of work in PR's
   1.344 - * queue at a time..  but this is quite hack-like.. or perhaps HWSim supplies
   1.345 - * a task-end handler that kicks the next unit of work from HWSim internal
   1.346 - * priority queue, over to PR readyQ)
   1.347 - *2) can have each language have its own language env, that holds its own
   1.348 - * work, which is assigned by its own assigner.. then the master searches
   1.349 - * through all the language envs to find one with work and asks it give work..
   1.350 - * (this has downside of blinding assigners to each other.. but does work
   1.351 - * for HWSim case)
   1.352 - *3) could make PR have a different readyQ for each core, and ask the lang
   1.353 - * to put work to the core it prefers.. but the work may be moved by PR if
   1.354 - * needed, say if one core idles for too long. This is a hybrid approach, 
   1.355 - * letting the language decide which core, but PR keeps the work and does it
   1.356 - * FIFO style.. (this might als be fudgeable with HWSim, in similar fashion, 
   1.357 - * but it would be complicated by having to track cores separately) 
   1.358 - *
   1.359 - *Choosing 2, to keep compatibility with single-lang mode..  it allows the same
   1.360 - * assigner to be used for single-lang as for multi-lang..  the overhead of
   1.361 - * the extra master search for work is part of the price of the flexibility,
   1.362 - * but should be fairly small.. takes the first env that has work available, 
   1.363 - * and whatever it returns is assigned to the slot..
   1.364 - * 
   1.365 - *As a hybrid, giving an option for a unified override assigner to be registered
   1.366 - * and used..  This allows something like a static analysis to detect
   1.367 - * which languages are grouped together, and then analyze the pattern of 
   1.368 - * construct calls, and generate a custom assigner that uses info from all
   1.369 - * the languages in a unified way..  Don't really expect this to happen, 
   1.370 - * but making it possible.
   1.371 - */
   1.372 -/*
   1.373 -inline
   1.374 -void 
   1.375 -masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot )
   1.376 - {    //Scan the animation slots
   1.377 -   SlaveVP        *slave;
   1.378 -   PRReqst        *req;
   1.379 -
   1.380 -      //Check if newly-done slave in slot, which will need request handled
   1.381 -   if( slot->workIsDone )
   1.382 -    { slot->workIsDone = FALSE;
   1.383 -      slot->needsWorkAssigned = TRUE;
   1.384 -
   1.385 -            HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot
   1.386 -            MEAS__startReqHdlr;
   1.387 -
   1.388 -
   1.389 -         //process the request made by the slave (held inside slave struc)
   1.390 -      slave = slot->slaveAssignedToSlot;
   1.391 -      req = slave->request;
   1.392 -
   1.393 -         //If the requesting slave is a slot slave, and request is not
   1.394 -         // task-end, then turn it into a free task slave. 
   1.395 -      if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd )
   1.396 -         PR_int__replace_with_new_slot_slv( slave );
   1.397 -
   1.398 -      //Handle task create and end first -- they're special cases..
   1.399 -      switch( req->reqType )
   1.400 -       { case TaskEnd: 
   1.401 -          { //do PR handler, which calls lang's hdlr and does recycle of
   1.402 -            // free task slave if needed -- PR handler checks for free task Slv
   1.403 -            PRHandle_EndTask_SL( slave );                            break;
   1.404 -          }
   1.405 -         case TaskCreate:
   1.406 -          { //Do PR's create-task handler, which calls the lang's hdlr
   1.407 -            // PR handler checks for free task Slv
   1.408 -            PRHandle_CreateTask_SL( slave );                         break;
   1.409 -          }
   1.410 -         case SlvCreate:    PRHandle_CreateSlave_SL( slave );        break;
   1.411 -         case SlvDissipate: PRHandle_Dissipate_SL( slave );          break;
   1.412 -         case Service:      PR_int__handle_PRServiceReq_SL( slave ); break; //resume into PR's own language env
   1.413 -         case Hardware: //for future expansion
   1.414 -         case IO:       //for future expansion
   1.415 -         case OSCall:   //for future expansion
   1.416 -            PR_int__throw_exception("Not implemented", slave, NULL); break;
   1.417 -         case Language: //normal lang request
   1.418 -          { 
   1.419 -            (*protoLangEnv->requestHdlr)( req->langReq, slave, (void*)PR_int__give_lang_env(protoLangEnv ));
   1.420 -          }
   1.421 -       }
   1.422 -              
   1.423 -            MEAS__endReqHdlr;          
   1.424 -            HOLISTIC__Record_AppResponder_end;
   1.425 -    } //if have request to be handled
   1.426 -
   1.427 -      //If slot empty, hand to Assigner to fill with a slave
   1.428 -   if( slot->needsWorkAssigned )
   1.429 -    {    //Call plugin's Assigner to give slot a new slave
   1.430 -            HOLISTIC__Record_Assigner_start;
   1.431 -
   1.432 -      if( protoLangEnv->hasWork )
   1.433 -       {  (*protoLangEnv->slaveAssigner)( protoLangEnv, slot ); //calls PR fn that inserts work into slot
   1.434 -         goto ReturnAfterAssigningWork; //quit for-loop, cause found work
   1.435 -       }
   1.436 -      else
   1.437 -         goto NoWork;
   1.438 -    }
   1.439 -   
   1.440 - NoWork:
   1.441 -      //No work, if reach here..
   1.442 -    { 
   1.443 -   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   1.444 -      coreNum = slot->coreSlotIsOn;
   1.445 -      returnSlv = process->idleSlv[coreNum][slotNum]; 
   1.446 -    
   1.447 -         //things that would normally happen in resume(), but idle VPs
   1.448 -         // never go there
   1.449 -      returnSlv->numTimesAssignedToASlot++; //gives each idle unit a unique ID
   1.450 -      Unit newU;
   1.451 -      newU.vp = returnSlv->slaveNum;
   1.452 -      newU.task = returnSlv->numTimesAssignedToASlot;
   1.453 -      addToListOfArrays(Unit,newU,process->unitList);
   1.454 -
   1.455 -      if (returnSlv->numTimesAssignedToASlot > 1) //make a dependency from prev idle unit
   1.456 -       { Dependency newD;             // to this one
   1.457 -         newD.from_vp = returnSlv->slaveNum;
   1.458 -         newD.from_task = returnSlv->numTimesAssignedToASlot - 1;
   1.459 -         newD.to_vp = returnSlv->slaveNum;
   1.460 -         newD.to_task = returnSlv->numTimesAssignedToASlot;
   1.461 -         addToListOfArrays(Dependency, newD ,process->ctlDependenciesList);  
   1.462 -       }
   1.463 -   #endif
   1.464 -            HOLISTIC__Record_Assigner_end;
   1.465 -      return;
   1.466 -    }
   1.467 - 
   1.468 - ReturnAfterAssigningWork:  //All paths goto here.. to provide single point for holistic..
   1.469 -    {
   1.470 -            HOLISTIC__Record_Assigner_end;
   1.471 -      return;
   1.472 -    }
   1.473 - }
   1.474 -*/
   1.475 -
   1.476  inline
   1.477  void
   1.478 -masterFunction_MultiLang( AnimSlot  *slot )
   1.479 +masterFunction( AnimSlot  *slot )
   1.480   {    //Scan the animation slots
   1.481     int32           magicNumber;
   1.482     SlaveVP        *slave;
   1.483     PRLangEnv      *langEnv;
   1.484     PRReqst        *req;
   1.485 -   RequestHandler  requestHandler;
   1.486     PRProcess      *process;
   1.487  
   1.488        //Check if newly-done slave in slot, which will need request handled
   1.489 @@ -566,8 +134,8 @@
   1.490              PRHandle_CreateTask( req, slave );                       break;
   1.491            }
   1.492           case SlvCreate:    PRHandle_CreateSlave( req, slave );      break;
   1.493 -         case SlvDissipate: PRHandle_Dissipate( req, slave );        break;
   1.494 -         case Service:      PR_int__handle_PRServiceReq( slave );    break; //resume into PR's own language env
   1.495 +         case SlvDissipate: PRHandle_EndSlave( req, slave );         break;
   1.496 +         case Service:      PR_int__handle_PRServiceReq( slave );    break; //resumes into Service lang env
   1.497           case Hardware: //for future expansion
   1.498           case IO:       //for future expansion
   1.499           case OSCall:   //for future expansion
   1.500 @@ -704,13 +272,13 @@
   1.501         }
   1.502     #endif
   1.503              HOLISTIC__Record_Assigner_end;
   1.504 -      return;
   1.505 +      return FALSE;
   1.506      }
   1.507   
   1.508   ReturnAfterAssigningWork:  //All paths goto here.. to provide single point for holistic..
   1.509      {
   1.510              HOLISTIC__Record_Assigner_end;
   1.511 -      return;
   1.512 +      return TRUE;
   1.513      }
   1.514   }
   1.515  
   1.516 @@ -774,7 +342,7 @@
   1.517   */
   1.518  inline
   1.519  void
   1.520 -PRHandle_Dissipate( PRReqst *req, SlaveVP *slave )
   1.521 +PRHandle_EndSlave( PRReqst *req, SlaveVP *slave )
   1.522   { PRProcess *process;
   1.523     PRLangEnv *protoLangEnv;
   1.524