changeset 270:292393c6bef1 Dev_ML

about to recover probes, so need to commit current state
author Sean Halle <seanhalle@yahoo.com>
date Wed, 16 Jan 2013 01:50:26 -0800
parents e6a68e7ea63f
children bc5030385120
files AnimationMaster.c CoreController.c PR.h PR__PI.h PR__SS.c PR__WL.c PR__WL.h PR__int.h PR__structs.h
diffstat 9 files changed, 110 insertions(+), 72 deletions(-) [+]
line diff
     1.1 --- a/AnimationMaster.c	Mon Jan 14 16:10:37 2013 -0800
     1.2 +++ b/AnimationMaster.c	Wed Jan 16 01:50:26 2013 -0800
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright 2010  OpenSourceResearchInstitute
     1.6 + * Copyright 2012  OpenSourceResearchInstitute.org
     1.7   * 
     1.8   * Licensed under BSD
     1.9   */
    1.10 @@ -26,9 +26,8 @@
    1.11  
    1.12  
    1.13  //inline void  masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot );
    1.14 -inline void masterFunction( AnimSlot  *slot );
    1.15  inline PRProcess * pickAProcess( AnimSlot *slot );
    1.16 -inline SlaveVP * assignWork( PRProcess *process, AnimSlot *slot );
    1.17 +inline bool32 assignWork( PRProcess *process, AnimSlot *slot );
    1.18  
    1.19  /*The animationMaster embodies most of the animator of the language.  The
    1.20   * animator is what emodies the behavior of language constructs. 
    1.21 @@ -94,7 +93,7 @@
    1.22  
    1.23  
    1.24  inline
    1.25 -void
    1.26 +bool32
    1.27  masterFunction( AnimSlot  *slot )
    1.28   {    //Scan the animation slots
    1.29     int32           magicNumber;
    1.30 @@ -102,6 +101,7 @@
    1.31     PRLangEnv      *langEnv;
    1.32     PRReqst        *req;
    1.33     PRProcess      *process;
    1.34 +   bool32          foundWork;
    1.35  
    1.36        //Check if newly-done slave in slot, which will need request handled
    1.37     if( slot->workIsDone )
    1.38 @@ -160,10 +160,13 @@
    1.39  
    1.40           //Scan lang environs, looking for langEnv with ready work.
    1.41           // call the Assigner for that lang Env, to get a slave for the slot
    1.42 +      foundWork =
    1.43        assignWork( process, slot );
    1.44  
    1.45              HOLISTIC__Record_Assigner_end;
    1.46      }//if slot needs slave assigned
    1.47 +   
    1.48 +   return foundWork;
    1.49   }
    1.50  
    1.51  /*When several processes exist, use some pattern for picking one to give
    1.52 @@ -218,7 +221,7 @@
    1.53   *  but am making it possible.
    1.54   */
    1.55  inline 
    1.56 -SlaveVP *
    1.57 +bool32
    1.58  assignWork( PRProcess *process, AnimSlot *slot )
    1.59   { SlaveVP        *returnSlv;
    1.60     int32           coreNum, slotNum;
    1.61 @@ -242,7 +245,7 @@
    1.62     for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep langEnvs in hash & array
    1.63      { langEnv = langEnvsList[envIdx];
    1.64        if( langEnv->hasWork )
    1.65 -       { (*langEnv->slaveAssigner)( langEnv, slot ); //assigner calls PR to put slave/task into slot
    1.66 +       { (*langEnv->workAssigner)( langEnv, slot ); //assigner calls PR to put slave/task into slot
    1.67           goto ReturnAfterAssigningWork; //quit for-loop, cause found work
    1.68           //NOTE: bad search alg -- should start where left off, then wrap around
    1.69         }
     2.1 --- a/CoreController.c	Mon Jan 14 16:10:37 2013 -0800
     2.2 +++ b/CoreController.c	Wed Jan 16 01:50:26 2013 -0800
     2.3 @@ -72,16 +72,14 @@
     2.4     int32           thisCoresIdx;
     2.5     int32           numRepetitionsWithNoWork;
     2.6     bool32          foundWork;
     2.7 -   SlaveVP        *currVP;
     2.8     AnimSlot       *animSlot;
     2.9 -   int32           currSlotIdx;
    2.10     volatile int32 *addrOfMasterLock; //thing pointed to is volatile, not ptr
    2.11     SlaveVP        *thisCoresMasterVP;
    2.12        //Variables used for pthread related things
    2.13     ThdParams      *thisCoresThdParams;
    2.14     cpu_set_t       coreMask;  //used during pinning pthread to CPU core
    2.15     int32           errorCode;
    2.16 -      //Variables used during measurements
    2.17 +      //Variables used during measurements (inside macro!)
    2.18     TSCountLowHigh  endSusp;
    2.19        //Variables used in random-backoff, for master-lock and waiting for work
    2.20     uint32_t seed1 = rand()%1000; // init random number generator for backoffs
    2.21 @@ -95,7 +93,8 @@
    2.22        //Assembly that saves addr of label of return instr -- label in assmbly
    2.23     recordCoreCtlrReturnLabelAddr((void**)&(_PRTopEnv->coreCtlrReturnPt));
    2.24  
    2.25 -   animSlot = _PRTopEnv->allAnimSlots[ thisCoresIdx ];
    2.26 +   //TODO: DEBUG: check get correct pointer here
    2.27 +   animSlot = _PRTopEnv->allAnimSlots[ thisCoresIdx ][0];
    2.28     numRepetitionsWithNoWork = 0;
    2.29     addrOfMasterLock = &(_PRTopEnv->masterLock);
    2.30     thisCoresMasterVP = _PRTopEnv->masterVPs[ thisCoresIdx ];
    2.31 @@ -123,7 +122,7 @@
    2.32           DEBUG__printf1(TRUE, "started coreCtrlr", thisCoresIdx );
    2.33           
    2.34     //====================== The Core Controller ======================
    2.35 -   while(1)  //An endless loop is just one way of doing the control structure
    2.36 +   while(1)  
    2.37      {        //Assembly code switches the core between animating a VP and
    2.38               // animating this core controller.  The switch is done by
    2.39               // changing the stack-pointer and frame-pointer and then doing
    2.40 @@ -150,9 +149,9 @@
    2.41              MEAS__Capture_Pre_Master_Lock_Point;
    2.42  
    2.43        int numTriesToGetLock = 0; int gotLock = 0;
    2.44 -      while( currVP == NULL ) //keep going until get master lock
    2.45 +      while( gotLock == FALSE ) //keep going until get master lock
    2.46         { 
    2.47 -            //At this point, first thing to do is get lock.  But, want to
    2.48 +            //want to
    2.49              // reduce lock contention from cores with no work, so first
    2.50              // check if this is a core with no work, and busy wait if so.
    2.51              //Then, if it's been way too long without work, yield pthread
    2.52 @@ -162,15 +161,15 @@
    2.53            { numRepetitionsWithNoWork = 0; pthread_yield(); }
    2.54  
    2.55  
    2.56 -            //Now, try to get the lock
    2.57 +            //Try to get the lock
    2.58           gotLock = __sync_bool_compare_and_swap( addrOfMasterLock,
    2.59                                                   UNLOCKED, LOCKED );
    2.60           if( gotLock )
    2.61            {    //At this point, have successfully gotten master lock.
    2.62                 //So, break out of get-lock loop.
    2.63 -            break;  //end while -- have a VP to animate now
    2.64 +            break;
    2.65            }
    2.66 -            //Get here only when failed to get lock
    2.67 +            //Get here only when failed to get lock -- check in should do backoff
    2.68  
    2.69           numTriesToGetLock++;   //if too many, means too much contention
    2.70           if( numTriesToGetLock > NUM_TRIES_BEFORE_DO_BACKOFF ) 
    2.71 @@ -183,20 +182,24 @@
    2.72           //have master lock, perform master function, which manages request
    2.73           // handling and assigning work to this core's slot
    2.74        foundWork =
    2.75 +         
    2.76           masterFunction( animSlot );
    2.77 +      
    2.78 +      PR_int__release_master_lock();
    2.79 +      
    2.80        if( foundWork )
    2.81           numRepetitionsWithNoWork = 0;
    2.82        else
    2.83           numRepetitionsWithNoWork += 1;
    2.84  
    2.85 +      //now that master is done, have work in the slot, so switch to it
    2.86              HOLISTIC__Record_Work_start;
    2.87  
    2.88 -      switchToSlv(currVP); //Slave suspend makes core "return" from this call
    2.89 +      switchToSlv(animSlot->slaveAssignedToSlot); //Slave suspend makes core "return" from this call
    2.90        flushRegisters();    //prevent GCC optimization from doing bad things 
    2.91  
    2.92               MEAS__Capture_End_Susp_in_CoreCtlr_ForSys;
    2.93               HOLISTIC__Record_Work_end;
    2.94 -           
    2.95      }//while(1)
    2.96   }
    2.97  
     3.1 --- a/PR.h	Mon Jan 14 16:10:37 2013 -0800
     3.2 +++ b/PR.h	Wed Jan 16 01:50:26 2013 -0800
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - *  Copyright 2009 OpenSourceResearchInstitute.org
     3.6 + *  Copyright 2012 OpenSourceResearchInstitute.org
     3.7   *  Licensed under GNU General Public License version 2
     3.8   *
     3.9   * Author: seanhalle@yahoo.com
    3.10 @@ -72,6 +72,8 @@
    3.11   * wrapper-library calls!
    3.12   */
    3.13  
    3.14 +inline bool32 masterFunction( AnimSlot  *slot );
    3.15 +
    3.16  //============== include internally used fn prototypes ================
    3.17  
    3.18  //include fn prototypes used internally in the proto-runtime implementation
     4.1 --- a/PR__PI.h	Mon Jan 14 16:10:37 2013 -0800
     4.2 +++ b/PR__PI.h	Wed Jan 16 01:50:26 2013 -0800
     4.3 @@ -49,6 +49,14 @@
     4.4  //PR_PI__take_lang_reqst_from( PRReqst *req );
     4.5  #define PR_PI__take_lang_reqst_from( req ) req->langReqData
     4.6  
     4.7 +//===============  Startup and Shutdown  ================
     4.8 +void
     4.9 +PR_SS__shutdown_OS_threads();
    4.10 + 
    4.11 +void
    4.12 +PR_SS__print_out_measurements();
    4.13 +
    4.14 +
    4.15  //================================================
    4.16  #endif	/* _PR__PI_H */
    4.17  
     5.1 --- a/PR__SS.c	Mon Jan 14 16:10:37 2013 -0800
     5.2 +++ b/PR__SS.c	Wed Jan 16 01:50:26 2013 -0800
     5.3 @@ -104,6 +104,7 @@
     5.4   *-] Counter of num live slaves and num live tasks in the process
     5.5   * 
     5.6   */
     5.7 +/*
     5.8  PRProcess *
     5.9  PR__create_process__SL( TopLevelFnPtr seed_Fn, void *seedData )
    5.10   { SlaveVP    *seedSlv;
    5.11 @@ -170,12 +171,13 @@
    5.12     
    5.13     return process;
    5.14   }
    5.15 + */
    5.16  
    5.17  /*This is only called in multi-lang mode.
    5.18   *It creates a seed slave, from the top-level fn and initial data passed into
    5.19   * this fn.
    5.20   *The only langlet in the created process is the default PRServ.  The rest
    5.21 - * must b e started up via calls  made by the seed VP's top-level fn (passed in
    5.22 + * must be started up via calls  made by the seed VP's top-level fn (passed in
    5.23   * to this call).
    5.24   * 
    5.25   *A process is represented by a structure that holds all the process-specific
    5.26 @@ -193,14 +195,14 @@
    5.27     
    5.28     _PRTopEnv->mode         = MultiLang;
    5.29     
    5.30 -   
    5.31 -   process = malloc( sizeof(PRProcess) );
    5.32 +      //This runs outside of the master lock, so use PR_WL form of malloc
    5.33 +   process = PR_WL__malloc( sizeof(PRProcess) );
    5.34     _PRTopEnv->processes[_PRTopEnv->numProcesses] = process;
    5.35     _PRTopEnv->numProcesses += 1;
    5.36     
    5.37 -   langEnvs     = malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRCollElem *) );
    5.38 +   langEnvs     = PR_WL__malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRCollElem *) );
    5.39     ((int32 *)langEnvs)[0]  = NUM_IN_COLLECTION;
    5.40 -   langEnvsList = malloc( NUM_IN_COLLECTION * sizeof(PRCollElem *) );
    5.41 +   langEnvsList = PR_WL__malloc( NUM_IN_COLLECTION * sizeof(PRCollElem *) );
    5.42     process->langEnvs     = langEnvs;
    5.43     process->langEnvsList = langEnvsList;
    5.44     process->numLangEnvs  = 0;
    5.45 @@ -214,7 +216,8 @@
    5.46     
    5.47     PRServLangEnv *
    5.48     servicesLangEnv = 
    5.49 -    PR_int__create_lang_env_in_process( sizeof(PRServLangEnv), process, PRServ_MAGIC_NUMBER );
    5.50 +    PR_int__create_lang_env_in_process( sizeof(PRServLangEnv), process,
    5.51 +                                        PRServ_MAGIC_NUMBER );
    5.52  
    5.53     servicesLangEnv->slavesReadyToResumeQ = makePrivQ();
    5.54     servicesLangEnv->taskReadyQ           = makePrivQ();
    5.55 @@ -245,8 +248,8 @@
    5.56        pthread_cond_broadcast( &suspendCond );
    5.57      #endif
    5.58      }
    5.59 -   pthread_mutex_init( process->doneLock, NULL );
    5.60 -   pthread_cond_init( process->doneCond, NULL );
    5.61 +   pthread_mutex_init( &(process->doneLock), NULL );
    5.62 +   pthread_cond_init( &(process->doneCond), NULL );
    5.63     process->executionIsComplete = FALSE;
    5.64     
    5.65     return process;
    5.66 @@ -262,14 +265,16 @@
    5.67     
    5.68        //remove process from PR's list of processes..
    5.69     processes = _PRTopEnv->processes;
    5.70 +   //find the process within the list
    5.71     for( i = 0; i < _PRTopEnv->numProcesses; i++ )
    5.72      { if( processes[i] == process )
    5.73         { processIdx = i;
    5.74           break;
    5.75         }
    5.76      }
    5.77 +   //move all the higher processes down, overwriting the target
    5.78     for( i = processIdx +1; i < _PRTopEnv->numProcesses; i++ )
    5.79 -    { processes[i-1] = process[i];
    5.80 +    { processes[i-1] = processes[i];
    5.81      }
    5.82     _PRTopEnv->numProcesses -= 1;
    5.83     
    5.84 @@ -279,12 +284,12 @@
    5.85        //call shutdown on each langlet started in process (which frees any
    5.86        // langlet-allocd data in langEnv);
    5.87        //Then free the lang env
    5.88 -   PRLangEnv *langEnv;
    5.89 +   PRLangEnv *protoLangEnv;
    5.90     for( i = 0; i < process->numLangEnvs; i++ )
    5.91 -    { langEnv = PR_int__give_proto_lang_env(process->langEnvsList[i]);
    5.92 +    { protoLangEnv = PR_int__give_proto_lang_env(process->langEnvsList[i]);
    5.93           //The lang shutdowns should free any slaves or tasks in the langEnv
    5.94 -      (*langEnv->shutdownHdlr)(&(langEnv[1]));
    5.95 -      PR_int__free( langEnv );
    5.96 +      (*protoLangEnv->shutdownHdlr)(&(protoLangEnv[1]));
    5.97 +      PR_int__free( protoLangEnv );
    5.98      }
    5.99     PR_int__free( process->langEnvsList ); //list array
   5.100     PR_int__free( &(((int32 *)process->langEnvs)[-1]) ); //the collection array
   5.101 @@ -308,20 +313,20 @@
   5.102      }
   5.103       
   5.104        //cause resume of "PR__wait_for_process_to_end()" call
   5.105 -   pthread_mutex_lock(     process->doneLock );
   5.106 +   pthread_mutex_lock(     &(process->doneLock) );
   5.107     process->executionIsComplete = TRUE;
   5.108 -   pthread_mutex_unlock(   process->doneLock );
   5.109 -   pthread_cond_broadcast( process->doneCond );
   5.110 +   pthread_mutex_unlock(   &(process->doneLock) );
   5.111 +   pthread_cond_broadcast( &(process->doneCond) );
   5.112        //BUG: process struct can be freed and re-allocated  before waiter sees
   5.113        // executionIsComplete
   5.114  
   5.115        //if last process, cause resume of "PR__wait_for_all_activity_to_end"
   5.116     if( _PRTopEnv->numProcesses == 1 )
   5.117      { implement_me(); //have to ensure that PRServ has no activity -- do later
   5.118 -      pthread_mutex_lock(     _PRTopEnv->activityDoneLock );
   5.119 +      pthread_mutex_lock(     &(_PRTopEnv->activityDoneLock) );
   5.120        _PRTopEnv->allActivityIsDone = TRUE;
   5.121 -      pthread_mutex_unlock(   _PRTopEnv->activityDoneLock );
   5.122 -      pthread_cond_broadcast( _PRTopEnv->activityDoneCond );
   5.123 +      pthread_mutex_unlock(   &(_PRTopEnv->activityDoneLock) );
   5.124 +      pthread_cond_broadcast( &(_PRTopEnv->activityDoneCond) );
   5.125      }
   5.126  
   5.127        //lastly, free the PRProcess struct itself
   5.128 @@ -345,25 +350,25 @@
   5.129  void
   5.130  PR__wait_for_all_activity_to_end()
   5.131   { 
   5.132 -   pthread_mutex_lock( _PRTopEnv->activityDoneLock );
   5.133 +   pthread_mutex_lock( &(_PRTopEnv->activityDoneLock) );
   5.134     while( !(_PRTopEnv->allActivityIsDone) )
   5.135      {
   5.136 -      pthread_cond_wait( _PRTopEnv->activityDoneCond,
   5.137 -                         _PRTopEnv->activityDoneLock );
   5.138 +      pthread_cond_wait( &(_PRTopEnv->activityDoneCond),
   5.139 +                         &(_PRTopEnv->activityDoneLock) );
   5.140      }
   5.141 -   pthread_mutex_unlock( _PRTopEnv->activityDoneLock );
   5.142 +   pthread_mutex_unlock( &(_PRTopEnv->activityDoneLock) );
   5.143   }
   5.144  
   5.145  void
   5.146  PR__wait_for_process_to_end()
   5.147   { 
   5.148 -   pthread_mutex_lock( _PRTopEnv->activityDoneLock );
   5.149 +   pthread_mutex_lock( &(_PRTopEnv->activityDoneLock) );
   5.150     while( !(_PRTopEnv->allActivityIsDone) )
   5.151      {
   5.152 -      pthread_cond_wait( _PRTopEnv->activityDoneCond,
   5.153 -                         _PRTopEnv->activityDoneLock );
   5.154 +      pthread_cond_wait( &(_PRTopEnv->activityDoneCond),
   5.155 +                         &(_PRTopEnv->activityDoneLock) );
   5.156      }
   5.157 -   pthread_mutex_unlock( _PRTopEnv->activityDoneLock );
   5.158 +   pthread_mutex_unlock( &(_PRTopEnv->activityDoneLock) );
   5.159   }
   5.160  
   5.161  /*When all work in the process has completed, then return from this call.
   5.162 @@ -382,14 +387,14 @@
   5.163  PR__give_results_from_process_when_ready( PRProcess *process )
   5.164   { void *result;
   5.165     
   5.166 -   pthread_mutex_lock( process->doneLock );
   5.167 +   pthread_mutex_lock( &(process->doneLock) );
   5.168     while( !(process->executionIsComplete) )
   5.169      {
   5.170 -      pthread_cond_wait( process->doneCond,
   5.171 -                         process->doneLock );
   5.172 +      pthread_cond_wait( &(process->doneCond),
   5.173 +                         &(process->doneLock) );
   5.174      }
   5.175     result = process->resultToReturn;
   5.176 -   pthread_mutex_unlock( process->doneLock );
   5.177 +   pthread_mutex_unlock( &(process->doneLock) );
   5.178        
   5.179     return result;
   5.180   }
   5.181 @@ -407,6 +412,7 @@
   5.182   * found by using magic num to look it up in the process that the seedVP
   5.183   * is inside of.
   5.184   */
   5.185 +/*
   5.186  void
   5.187  PR_SS__register_create_task_handler( RequestHandler createTaskHandler, SlaveVP *seedVP, int32 magicNum )
   5.188   { PRLangEnv *langEnv;
   5.189 @@ -442,15 +448,17 @@
   5.190     langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
   5.191     langEnv->requestHdlr = reqHandler; 
   5.192   }
   5.193 + */
   5.194  void
   5.195  PR_SS__register_assigner( SlaveAssigner assigner, SlaveVP *seedVP, int32 magicNum )
   5.196   { PRLangEnv *langEnv;
   5.197   
   5.198     langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
   5.199 -   langEnv->slaveAssigner = assigner; 
   5.200 +   langEnv->workAssigner = assigner; 
   5.201   }
   5.202  void
   5.203 -PR_SS__register_shutdown_handler( RequestHandler shutdownHdlr, SlaveVP *seedVP, int32 magicNum )
   5.204 +PR_SS__register_shutdown_handler( LangShutdownHdlr shutdownHdlr, SlaveVP *seedVP,
   5.205 +                                  int32 magicNum )
   5.206   { PRLangEnv *langEnv;
   5.207   
   5.208     langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
   5.209 @@ -474,6 +482,14 @@
   5.210     langEnv->langDataInitializer = langDataInitializer; 
   5.211   }
   5.212  */
   5.213 +void
   5.214 +PR_SS__register_lang_data_freer( LangDataFreer langDataFreer, 
   5.215 +                                              SlaveVP *seedVP, int32 magicNum )
   5.216 + { PRLangEnv *langEnv;
   5.217 + 
   5.218 +   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
   5.219 +   langEnv->langDataFreer = langDataFreer; 
   5.220 + }
   5.221  
   5.222  
   5.223  
   5.224 @@ -485,7 +501,7 @@
   5.225   */
   5.226  char *
   5.227  PRServ___give_environment_string()
   5.228 - { char buffer[10000];
   5.229 + { char *buffer = PR_WL__malloc(10000);
   5.230     int32 j;
   5.231     
   5.232     j = sizeof(int32);  //put total num chars here when done
   5.233 @@ -652,8 +668,8 @@
   5.234     _PRTopEnv->firstProcessReady = FALSE;      //use while starting up coreCtlr   
   5.235     
   5.236        //initialize flags for waiting for activity within PR to complete
   5.237 -   pthread_mutex_init( _PRTopEnv->activityDoneLock, NULL );
   5.238 -   pthread_cond_init(  _PRTopEnv->activityDoneCond, NULL );
   5.239 +   pthread_mutex_init( &(_PRTopEnv->activityDoneLock), NULL );
   5.240 +   pthread_cond_init(  &(_PRTopEnv->activityDoneCond), NULL );
   5.241     _PRTopEnv->allActivityIsDone = FALSE;
   5.242  
   5.243     //============================= MEASUREMENT STUFF ========================
     6.1 --- a/PR__WL.c	Mon Jan 14 16:10:37 2013 -0800
     6.2 +++ b/PR__WL.c	Wed Jan 16 01:50:26 2013 -0800
     6.3 @@ -62,12 +62,12 @@
     6.4   * to the plugin.
     6.5   */
     6.6  void
     6.7 -PR_WL__send_create_slaveVP_req( void *langReq, CreateHandler handler, 
     6.8 -                           int32 *slvID, SlaveVP *reqstingSlv, int32 magicNum )
     6.9 +PR_WL__send_create_slaveVP_req( void *langReq, int32 *ID, CreateHandler handler, 
    6.10 +                                SlaveVP *reqstingSlv, int32 magicNum )
    6.11   { PRReqst req;
    6.12  
    6.13     req.reqType          = SlvCreate;
    6.14 -   req.ID               = slvID;
    6.15 +   req.ID               = ID;
    6.16     req.langMagicNumber  = magicNum;
    6.17     req.langReq          = langReq;
    6.18     req.createHdlr       = handler;
     7.1 --- a/PR__WL.h	Mon Jan 14 16:10:37 2013 -0800
     7.2 +++ b/PR__WL.h	Wed Jan 16 01:50:26 2013 -0800
     7.3 @@ -69,14 +69,16 @@
     7.4                                                            SlaveVP *callingSlv );
     7.5  
     7.6  inline void
     7.7 -PR_WL__send_lang_request( void *langReq, SlaveVP *callingSlv, int32 magicNum );
     7.8 +PR_WL__send_lang_request( void *langReq, RequestHandler handler, 
     7.9 +                                          SlaveVP *callingSlv, int32 magicNum );
    7.10  
    7.11  void
    7.12 -PR_WL__send_create_slaveVP_req( void *langReq, CreateHandler handler, 
    7.13 -                           int32 *slvID, SlaveVP *reqstingSlv, int32 magicNum );
    7.14 +PR_WL__send_create_slaveVP_req( void *langReq, int32 *ID, CreateHandler handler, 
    7.15 +                                SlaveVP *reqstingSlv, int32 magicNum );
    7.16  
    7.17  void inline
    7.18 -PR_WL__send_end_slave_req( SlaveVP *prToDissipate, int32 magicNum );
    7.19 +PR_WL__send_end_slave_req( void *langReq, RequestHandler handler, 
    7.20 +                                       SlaveVP *slvToDissipate, int32 magicNum );
    7.21  
    7.22  inline void
    7.23  PR_WL__send_service_request( void *langReqData, SlaveVP *callingSlv );
     8.1 --- a/PR__int.h	Mon Jan 14 16:10:37 2013 -0800
     8.2 +++ b/PR__int.h	Wed Jan 16 01:50:26 2013 -0800
     8.3 @@ -112,7 +112,7 @@
     8.4  
     8.5  inline
     8.6  void *
     8.7 -PR_int__create_lang_env_in_process( int32 size, PRProcess process, int32 magicNum );
     8.8 +PR_int__create_lang_env_in_process( int32 size, PRProcess *process, int32 magicNum );
     8.9  
    8.10  inline
    8.11  void *
     9.1 --- a/PR__structs.h	Mon Jan 14 16:10:37 2013 -0800
     9.2 +++ b/PR__structs.h	Wed Jan 16 01:50:26 2013 -0800
     9.3 @@ -33,6 +33,8 @@
     9.4  typedef SlaveVP *(*SlaveAssigner)  ( void *, AnimSlot* ); //langEnv, slot for HW info
     9.5  typedef void     (*RequestHandler) ( void *, SlaveVP *, void * ); //req, slv, langEnv
     9.6  typedef void    *(*CreateHandler)  ( void *, SlaveVP *, void * ); //req, slv, langEnv
     9.7 +typedef void     (*LangShutdownHdlr)( void * ); //langEnv
     9.8 +typedef void     (*LangDataFreer)  ( void * ); //lang data to free
     9.9  typedef void     (*TopLevelFnPtr)  ( void *, SlaveVP * ); //initData, animSlv
    9.10  typedef void       TopLevelFn      ( void *, SlaveVP * ); //initData, animSlv
    9.11  typedef void     (*ResumeSlvFnPtr) ( SlaveVP *, void * );
    9.12 @@ -65,9 +67,9 @@
    9.13     int32     numEnvsWithWork;
    9.14     void     *resultToReturn;
    9.15      
    9.16 -   PRLangEnv *langEnvs[NUM_IN_COLLECTION];     //used as a hash table
    9.17 -   PRLangEnv *langEnvsList[NUM_IN_COLLECTION]; //for fast linear scan of envs
    9.18 -   int32      numLangEnvs;                     //for fast linear scan of envs
    9.19 +   PRLangEnv **langEnvs;     //used as a hash table
    9.20 +   PRLangEnv **langEnvsList; //for fast linear scan of envs
    9.21 +   int32      numLangEnvs;   //for fast linear scan of envs
    9.22      
    9.23     SlaveVP        *seedSlv;
    9.24     
    9.25 @@ -320,18 +322,20 @@
    9.26     PRLangEnv *chainedLangEnv;   //chains to langEnvs with same hash
    9.27     //=============================================================
    9.28     
    9.29 -   SlaveAssigner   slaveAssigner;
    9.30 -   RequestHandler  requestHdlr; 
    9.31 -   RequestHandler  shutdownHdlr; //called when lang ended or process shutdown
    9.32 +   SlaveAssigner    workAssigner;
    9.33 +//   RequestHandler  requestHdlr; 
    9.34 +   LangShutdownHdlr shutdownHdlr; //called when lang ended or process shutdown
    9.35  
    9.36  /*
    9.37     CreateTaskHdlr  createTaskHdlr;
    9.38     RequestHandler  endTaskHdlr; 
    9.39     CreateSlvHdlr   createSlaveHdlr;
    9.40     RequestHandler  dissipateSlaveHdlr;
    9.41 - */ 
    9.42 -   RequestHandler  langDataCreator;
    9.43 -   RequestHandler  langDataInitializer;
    9.44 +  
    9.45 +   RequestHandler   langDataCreator;
    9.46 +   RequestHandler   langDataInitializer;
    9.47 + */
    9.48 +   LangDataFreer    langDataFreer;
    9.49       
    9.50        //when multi-lang, master polls lang env's to find one with work in it..
    9.51        // in single-lang case, flag ignored, master always asks lang for work