changeset 273:40e7625e57bd Dev_ML

Compiles and runs, up to end of process, working on end process and shutdown
author Sean Halle <seanhalle@yahoo.com>
date Sat, 02 Mar 2013 09:43:45 -0800
parents bc5030385120
children 43b0a2585dc3
files AnimationMaster.c CoreController.c Defines/MEAS__macros_to_be_moved_to_langs.h HW_Dependent_Primitives/PR__primitives.h HW_Dependent_Primitives/PR__primitives_asm.s PR.c PR.h PR__PI.c PR__PI.h PR__SS.c PR__WL.c PR__WL.h PR__int.c PR__int.h PR__structs.h Services_Offered_by_PR/Measurement_and_Stats/MEAS__macros.h Services_Offered_by_PR/Measurement_and_Stats/probes.c Services_Offered_by_PR/Measurement_and_Stats/probes.h Services_Offered_by_PR/Memory_Handling/vmalloc.h Services_Offered_by_PR/Services_Language/Measurement/PRServ_Measurement.h Services_Offered_by_PR/Services_Language/PRServ.c Services_Offered_by_PR/Services_Language/PRServ.h Services_Offered_by_PR/Services_Language/PRServ_PluginFns.c Services_Offered_by_PR/Services_Language/PRServ_Request_Handlers.c Services_Offered_by_PR/Services_Language/PRServ_Request_Handlers.h Services_Offered_by_PR/Services_Language/PRServ_SS.c Services_Offered_by_PR/Services_Language/PRServ_singleton_asm.s
diffstat 27 files changed, 2118 insertions(+), 2747 deletions(-) [+]
line diff
     1.1 --- a/AnimationMaster.c	Tue Feb 05 20:23:27 2013 -0800
     1.2 +++ b/AnimationMaster.c	Sat Mar 02 09:43:45 2013 -0800
     1.3 @@ -12,23 +12,30 @@
     1.4  #include "PR.h"
     1.5  #include "VSs_impl/VSs.h"
     1.6  
     1.7 -/*
     1.8 -void        PRHandle_CreateTask_SL(SlaveVP *slave);
     1.9 +//=========================  Local Declarations  ========================
    1.10 +inline PRProcess * 
    1.11 +pickAProcess( AnimSlot *slot );
    1.12 +inline bool32      
    1.13 +assignWork( PRProcess *process, AnimSlot *slot );
    1.14  
    1.15 -void        PRHandle_CreateSlave_SL(SlaveVP *slave);
    1.16 -void        PRHandle_Dissipate_SL(SlaveVP *slave);
    1.17 -void        PR_int__handle_PRServiceReq_SL(SlaveVP *slave);
    1.18 -*/
    1.19 -inline void PRHandle__CreateTask( PRReqst *req, SlaveVP *slave );
    1.20 -inline void PRHandle__EndTask(    PRReqst *req, SlaveVP *slave );
    1.21 -inline void PRHandle__CreateSlave(PRReqst *req, SlaveVP *slave );
    1.22 -void        PRHandle__EndSlave(  PRReqst *req, SlaveVP *slave );
    1.23 +inline void 
    1.24 +PRHandle__CreateTask( PRReqst *req, SlaveVP *slave );
    1.25 +inline void 
    1.26 +PRHandle__EndTask(    PRReqst *req, SlaveVP *slave );
    1.27 +inline void 
    1.28 +PRHandle__CreateSlave(PRReqst *req, SlaveVP *slave );
    1.29 +inline void        
    1.30 +PRHandle__EndSlave(   PRReqst *req, SlaveVP *slave );
    1.31  
    1.32 +inline void
    1.33 +PRHandle__LangShutdown( PRReqst *req, SlaveVP *requestingSlv );
    1.34  
    1.35 -//inline void  masterFunction_SingleLang( PRLangEnv *protoLangEnv, AnimSlot *slot );
    1.36 -inline PRProcess * pickAProcess( AnimSlot *slot );
    1.37 -inline bool32 assignWork( PRProcess *process, AnimSlot *slot );
    1.38 +inline void
    1.39 +handleMakeProbe( PRServiceReq *langReq, PRLangEnv *protoLangEnv );
    1.40 +inline void
    1.41 +handleThrowException( PRServiceReq *langReq, PRLangEnv *protoLangEnv );
    1.42  
    1.43 +//===========================================================================
    1.44  
    1.45  /*Note: there used to be a coreController that was another animation 
    1.46   * layer below both the masterVP and the slaveVPs.. in that case, the
    1.47 @@ -59,7 +66,7 @@
    1.48     PRLangEnv      *langEnv;
    1.49     PRReqst        *req;
    1.50     PRProcess      *process;
    1.51 -   bool32          foundWork;
    1.52 +   bool32          didAssignWork;
    1.53  
    1.54        //Check if newly-done slave in slot, which will need request handled
    1.55        //NOTE: left over from when had a coreController & MasterVP managed
    1.56 @@ -67,53 +74,58 @@
    1.57     if( slot->workIsDone )
    1.58      { slot->workIsDone = FALSE;
    1.59        slot->needsWorkAssigned = TRUE;
    1.60 +      
    1.61 +         //An Idle VP has no request to handle, so skip to assign..
    1.62 +      if( slot->slaveAssignedToSlot->typeOfVP != IdleVP )
    1.63 +       {
    1.64 +               HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot
    1.65 +               MEAS__startReqHdlr;
    1.66  
    1.67 -            HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot
    1.68 -            MEAS__startReqHdlr;
    1.69  
    1.70 +            //process the request made by the slave (held inside slave struc)
    1.71 +         slave = slot->slaveAssignedToSlot;
    1.72 +         req = slave->request;
    1.73  
    1.74 -         //process the request made by the slave (held inside slave struc)
    1.75 -      slave = slot->slaveAssignedToSlot;
    1.76 -      req = slave->request;
    1.77 +            //If the requesting slave is a slot slave, and request is not
    1.78 +            // task-end, then turn it into a free task slave & continue
    1.79 +         if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd )
    1.80 +            PR_int__replace_with_new_slot_slv( slave );
    1.81  
    1.82 -         //If the requesting slave is a slot slave, and request is not
    1.83 -         // task-end, then turn it into a free task slave. 
    1.84 -      if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd )
    1.85 -         PR_int__replace_with_new_slot_slv( slave );
    1.86 -
    1.87 -      //Handle task create and end first -- they're special cases..
    1.88 -      switch( req->reqType )
    1.89 -       { case TaskEnd: 
    1.90 -          { //do PR handler, which calls lang's hdlr and does recycle of
    1.91 -            // free task slave if needed -- PR handler checks for free task Slv
    1.92 -            PRHandle__EndTask( req, slave );                          break;
    1.93 +         //Handle task create and end first -- they're special cases..
    1.94 +         switch( req->reqType )
    1.95 +          { case TaskEnd: 
    1.96 +             { //do PR handler, which calls lang's hdlr and does recycle of
    1.97 +               // free task slave if needed -- PR handler checks for free task Slv
    1.98 +               PRHandle__EndTask( req, slave );                          break;
    1.99 +             }
   1.100 +            case TaskCreate:
   1.101 +             { //Do PR's create-task handler, which calls the lang's hdlr
   1.102 +               // PR handler checks for free task Slv
   1.103 +               PRHandle__CreateTask( req, slave );                       break;
   1.104 +             }
   1.105 +            case SlvCreate:    PRHandle__CreateSlave( req, slave );      break;
   1.106 +            case SlvDissipate: PRHandle__EndSlave( req, slave );         break;
   1.107 +            case Service:      PRHandle__ServiceReq( slave );    break; //resumes into Service lang env
   1.108 +            case Hardware: //for future expansion
   1.109 +            case IO:       //for future expansion
   1.110 +            case OSCall:   //for future expansion
   1.111 +               PR_int__throw_exception("Not implemented", slave, NULL); break;
   1.112 +            case LangShutdown: PRHandle__LangShutdown( req, slave ); break;
   1.113 +            case Language: //normal lang request
   1.114 +             { magicNumber = req->langMagicNumber;
   1.115 +               langEnv = PR_PI__give_lang_env_for_slave( slave, magicNumber );
   1.116 +               (*req->handler)( req->langReq, slave, langEnv );
   1.117 +             }
   1.118            }
   1.119 -         case TaskCreate:
   1.120 -          { //Do PR's create-task handler, which calls the lang's hdlr
   1.121 -            // PR handler checks for free task Slv
   1.122 -            PRHandle__CreateTask( req, slave );                       break;
   1.123 -          }
   1.124 -         case SlvCreate:    PRHandle__CreateSlave( req, slave );      break;
   1.125 -         case SlvDissipate: PRHandle__EndSlave( req, slave );         break;
   1.126 -         case Service:      PRHandle__ServiceReq( slave );    break; //resumes into Service lang env
   1.127 -         case Hardware: //for future expansion
   1.128 -         case IO:       //for future expansion
   1.129 -         case OSCall:   //for future expansion
   1.130 -            PR_int__throw_exception("Not implemented", slave, NULL); break;
   1.131 -         case Language: //normal lang request
   1.132 -          { magicNumber = req->langMagicNumber;
   1.133 -            langEnv = PR_PI__give_lang_env_for( slave, magicNumber );
   1.134 -            (*req->handler)( req->langReq, slave, langEnv );
   1.135 -          }
   1.136 -       }
   1.137 -
   1.138 +      
   1.139             MEAS__endReqHdlr;          
   1.140             HOLISTIC__Record_AppResponder_end;
   1.141 +       }//if not idleVP
   1.142      } //if have request to be handled
   1.143  
   1.144        //NOTE: IF statement is leftover from when master managed many slots
   1.145 -   foundWork = FALSE;
   1.146 -   if( slot->needsWorkAssigned ) //can probably remove IF, not that only one slot
   1.147 +   didAssignWork = FALSE;
   1.148 +   if( slot->needsWorkAssigned ) //can probably remove IF, now that only one slot
   1.149      {
   1.150              HOLISTIC__Record_Assigner_start;
   1.151        
   1.152 @@ -122,15 +134,19 @@
   1.153  
   1.154           //Scan lang environs, looking for langEnv with ready work.
   1.155           // call the Assigner for that lang Env, to get a slave for the slot
   1.156 -      foundWork =
   1.157 -      assignWork( process, slot );
   1.158 -
   1.159 +      if( process != NULL )
   1.160 +       { didAssignWork =
   1.161 +           assignWork( process, slot );
   1.162 +       }
   1.163              HOLISTIC__Record_Assigner_end;
   1.164  
   1.165 -//      fixme; //make this a while loop that tries a different process if this one fails
   1.166 +      if( !didAssignWork ) //if no work assigned, be sure idle slave is in slot
   1.167 +       { slot->slaveAssignedToSlot = _PRTopEnv->idleSlv[slot->coreSlotIsOn][0];
   1.168 +       }
   1.169 +//      fixme; //make into a loop that tries more processes if fails to assign
   1.170      }//if slot needs slave assigned
   1.171     
   1.172 -   return foundWork;
   1.173 +   return didAssignWork;
   1.174   }
   1.175  
   1.176  /*When several processes exist, use some pattern for picking one to give
   1.177 @@ -201,19 +217,19 @@
   1.178      }
   1.179     
   1.180        //If here, then no override assigner, so search language envs for work
   1.181 -   int32 envIdx, numEnvs; PRLangEnv **langEnvsList, *langEnv;
   1.182 -   langEnvsList = process->langEnvsList;
   1.183 +   int32 envIdx, numEnvs; PRLangEnv **protoLangEnvsList, *protoLangEnv;
   1.184 +   protoLangEnvsList = process->protoLangEnvsList;
   1.185     numEnvs = process->numLangEnvs;
   1.186     for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep langEnvs in hash & array
   1.187 -    { langEnv = langEnvsList[envIdx];
   1.188 -      if( langEnv->numReadyWork > 0 )
   1.189 +    { protoLangEnv = protoLangEnvsList[envIdx];
   1.190 +      if( protoLangEnv->numReadyWork > 0 )
   1.191         { bool32 
   1.192           didAssignWork =
   1.193 -          (*langEnv->workAssigner)( langEnv, slot ); //assigner calls PR to put slave/task into slot
   1.194 +          (*protoLangEnv->workAssigner)( PR_int__give_lang_env(protoLangEnv), slot ); //assigner calls PR to put slave/task into slot
   1.195  
   1.196           if(didAssignWork)
   1.197 -          { langEnv->numReadyWork -= 1;
   1.198 -            if( langEnv->numReadyWork == 0 )
   1.199 +          { protoLangEnv->numReadyWork -= 1;
   1.200 +            if( protoLangEnv->numReadyWork == 0 )
   1.201               { process->numEnvsWithWork -= 1;
   1.202               }
   1.203              goto ReturnAfterAssigningWork; //quit for-loop, 'cause found work
   1.204 @@ -260,6 +276,124 @@
   1.205   }
   1.206  
   1.207  
   1.208 +//=================================
   1.209 +//===
   1.210 +//=
   1.211 +/*Create task is a special form, that has PR behavior in addition to plugin
   1.212 + * behavior.  Master calls this first, and it then calls the plugin's
   1.213 + * create task handler.
   1.214 + * 
   1.215 + *Note: the requesting slave must be either generic slave or free task slave
   1.216 + */
   1.217 +inline
   1.218 +void
   1.219 +PRHandle__CreateTask( PRReqst *req, SlaveVP *slave )
   1.220 + { PRMetaTask     *protoMetaTask;
   1.221 +   PRProcess      *process;
   1.222 +   PRLangEnv      *protoLangEnv;
   1.223 +   void           *task;
   1.224 +                
   1.225 +   process = slave->processSlaveIsIn;
   1.226 +   
   1.227 +   protoLangEnv = PR_int__give_proto_lang_env_for_slave( slave, 
   1.228 +                                                        req->langMagicNumber );
   1.229 +   
   1.230 +   //Do the langlet's create-task handler, which keeps the task
   1.231 +   // inside the langlet's lang env, but returns the langMetaTask
   1.232 +   // so that PR can then put stuff into the prolog
   1.233 +   //typedef void * (*CreateHandler)( void *, SlaveVP *, void * ); //req, slv, langEnv
   1.234 +   //
   1.235 +   task = 
   1.236 +      (*req->createHdlr)(req->langReq, slave, PR_int__give_lang_env(protoLangEnv) );
   1.237 +   protoMetaTask = PR_int__give_prolog_of_lang_meta_task( task );
   1.238 +   protoMetaTask->ID         = req->ID; //may be NULL
   1.239 +   protoMetaTask->topLevelFn = req->topLevelFn;
   1.240 +   protoMetaTask->initData   = req->initData;
   1.241 +   protoMetaTask->processTaskIsIn = process;
   1.242 +           
   1.243 +   process->numLiveTasks += 1;
   1.244 +   protoLangEnv->numLiveWork += 1;  //used in wait statements -- small added overhead
   1.245 +   
   1.246 +   return;
   1.247 + }
   1.248 +
   1.249 +/*When a task ends, have two scenarios: 1) task ran to completion, or 2) task
   1.250 + * has been suspended at some point in its code.
   1.251 + *For 1, just decr count of live tasks (and check for end condition) -- the
   1.252 + * master loop will decide what goes into the slot freed up by this task end,
   1.253 + * so, here, don't worry about assigning a new task to the slot slave.
   1.254 + *For 2, the task's slot slave has been converted to a free task slave, which
   1.255 + * now has nothing more to do, so send it to the recycle Q (which includes
   1.256 + * freeing all the langData and meta task structs alloc'd for it).  Then
   1.257 + * decrement the live task count and check end condition.
   1.258 + * 
   1.259 + *PR has to update count of live tasks, and check end of process condition.
   1.260 + * The "main" can invoke constructs that wait for a process to end, so when
   1.261 + * end detected, have to resume what's waiting..
   1.262 + *Thing is, that wait involves the main OS thread.  That means
   1.263 + * PR internals have to do OS thread signaling.  Want to do that in the
   1.264 + * core controller, which has the original stack of an OS thread.  So the
   1.265 + * end process handling happens in the core controller.
   1.266 + * 
   1.267 + *So here, when detect process end, signal to the core controller, which will
   1.268 + * then do the condition variable notify to the OS thread that's waiting.
   1.269 + * 
   1.270 + *Note: slave may be either a slot slave or a free task slave. 
   1.271 + */
   1.272 +inline 
   1.273 +void
   1.274 +PRHandle__EndTask( PRReqst *req, SlaveVP *requestingSlv )
   1.275 + { void       *langEnv;
   1.276 +   PRLangEnv  *protoLangEnv;
   1.277 +   PRProcess  *process;
   1.278 +   void       *langMetaTask;
   1.279 +   
   1.280 +   process = requestingSlv->processSlaveIsIn;
   1.281 +   langEnv = PR_int__give_lang_env_of_req( req, requestingSlv ); //magic num in req
   1.282 +   protoLangEnv = PR_int__give_proto_lang_env( langEnv );
   1.283 +   
   1.284 +   langMetaTask = PR_int__give_lang_meta_task_from_slave( requestingSlv, req->langMagicNumber);
   1.285 +   
   1.286 +   //Do the langlet's request handler
   1.287 +   //Want to keep PR structs hidden from plugin, so extract langReq..
   1.288 +   //This is supposed to free any langlet-malloc'd mem, including meta task 
   1.289 +   (*req->handler)( req->langReq, requestingSlv, langEnv );
   1.290 +
   1.291 +   protoLangEnv->numLiveWork -= 1;  //used in wait statements -- small added overhead
   1.292 +   if( protoLangEnv->numLiveWork == 0 &&
   1.293 +       numInPrivQ( protoLangEnv->waitingForWorkToEndQ ) > 0 )
   1.294 +    { SlaveVP *
   1.295 +      waitingSlave = readPrivQ( protoLangEnv->waitingForWorkToEndQ );
   1.296 +         //can't resume into langlet that just ended its last work!
   1.297 +         // and don't have env that the waiter was created in, so resume
   1.298 +         // into PRServ env..
   1.299 +      void *
   1.300 +      resumeEnv = PR_PI__give_lang_env_from_process( process, PRServ_MAGIC_NUMBER );
   1.301 +      while( waitingSlave != NULL )
   1.302 +       {    //resume a slave that was waiting for work in this env to finish
   1.303 +         PR_PI__make_slave_ready( waitingSlave, resumeEnv );
   1.304 +            //get next waiting slave, repeat..
   1.305 +         waitingSlave = readPrivQ( protoLangEnv->waitingForWorkToEndQ );
   1.306 +       }
   1.307 +    }
   1.308 +   
   1.309 +
   1.310 +   //Now that the langlet's done with it, recycle the slave if it's a freeTaskSlv
   1.311 +   if( requestingSlv->typeOfVP == FreeTaskSlv )
   1.312 +      PR_int__recycle_slaveVP( requestingSlv ); //Doesn't decr num live slaves
   1.313 +   
   1.314 +   process->numLiveTasks -= 1;
   1.315 +   //NOTE: end-task is unrelated to work available (just in case wondering)
   1.316 +  
   1.317 +      //check End Of Process Condition
   1.318 +   if( process->numLiveTasks == 0 &&
   1.319 +       process->numLiveGenericSlvs == 0 )
   1.320 +    { //Tell the core controller to do wakeup of any waiting OS thread
   1.321 +      PR_SS__end_process_normally( process );
   1.322 +    }
   1.323 + }
   1.324 +
   1.325 +
   1.326  
   1.327  /*This is first thing called when creating a slave..  it hands off to the 
   1.328   * langlet's creator, then adds updates of its own..
   1.329 @@ -293,7 +427,7 @@
   1.330     PRLangEnv *protoLangEnv;
   1.331   
   1.332     process = slave->processSlaveIsIn;
   1.333 -   protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, req->langMagicNumber );
   1.334 +   protoLangEnv = PR_int__give_proto_lang_env_for_slave( slave, req->langMagicNumber );
   1.335        
   1.336     //create handler, or a future request handler will call PR_PI__make_slave_ready
   1.337     // which will in turn handle updating which langlets and which processes have
   1.338 @@ -306,6 +440,7 @@
   1.339     newSlv->processSlaveIsIn = process;
   1.340     newSlv->ID = req->ID;
   1.341     process->numLiveGenericSlvs += 1; //not same as work ready!
   1.342 +   protoLangEnv->numLiveWork += 1;  //used in wait statements -- small added overhead
   1.343   }
   1.344  
   1.345  /*The dissipate handler has to, update the number of slaves of the type, within
   1.346 @@ -327,105 +462,60 @@
   1.347     process = slave->processSlaveIsIn;
   1.348     
   1.349        //do the language's dissipate handler
   1.350 -   protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, slave->request->langMagicNumber );
   1.351 +   protoLangEnv = PR_int__give_proto_lang_env_for_slave( slave, slave->request->langMagicNumber );
   1.352     
   1.353     if(req->handler != NULL)
   1.354        (*req->handler)( req->langReq, slave, PR_int__give_lang_env(protoLangEnv) );
   1.355     
   1.356 +   protoLangEnv->numLiveWork -= 1;  //used in wait statements -- small added overhead
   1.357 +   if( protoLangEnv->numLiveWork == 0 &&
   1.358 +       numInPrivQ( protoLangEnv->waitingForWorkToEndQ ) > 0 )
   1.359 +    { SlaveVP *
   1.360 +      waitingSlave = readPrivQ( protoLangEnv->waitingForWorkToEndQ );
   1.361 +         //can't resume into langlet that just ended its last work!
   1.362 +         // and don't have env that the waiter was created in, so resume
   1.363 +         // into PRServ env..
   1.364 +      void *
   1.365 +      resumeEnv = PR_PI__give_lang_env_from_process( process, PRServ_MAGIC_NUMBER );
   1.366 +      while( waitingSlave != NULL )
   1.367 +       {    //resume a slave that was waiting for work in this env to finish
   1.368 +         PR_PI__make_slave_ready( waitingSlave, resumeEnv );
   1.369 +            //get next waiting slave, repeat..
   1.370 +         waitingSlave = readPrivQ( protoLangEnv->waitingForWorkToEndQ );
   1.371 +       }
   1.372 +    }
   1.373 +   
   1.374     process->numLiveGenericSlvs -= 1; 
   1.375 -   PR_int__recycle_slave( slave );
   1.376 +   PR_int__recycle_slaveVP( slave );
   1.377     //NOTE: dissipate is unrelated to work available (just in case wondering)
   1.378  
   1.379        //check End Of Process Condition
   1.380     if( process->numLiveTasks == 0 &&
   1.381         process->numLiveGenericSlvs == 0 )
   1.382 -      PR_SS__shutdown_process( process );
   1.383 +      PR_SS__end_process_normally( process );
   1.384   }
   1.385  
   1.386 -/*Create task is a special form, that has PR behavior in addition to plugin
   1.387 - * behavior.  Master calls this first, and it then calls the plugin's
   1.388 - * create task handler.
   1.389 - * 
   1.390 - *Note: the requesting slave must be either generic slave or free task slave
   1.391 +//=======================
   1.392 +//===
   1.393 +//=
   1.394 +/*Langlet shutdown triggers this, which calls the registered shutdown 
   1.395 + * handler for the langlet, and removes the lang's env from the process
   1.396   */
   1.397  inline
   1.398  void
   1.399 -PRHandle__CreateTask( PRReqst *req, SlaveVP *slave )
   1.400 - { PRMetaTask     *metaTask;
   1.401 -   PRProcess      *process;
   1.402 -   PRLangEnv      *protoLangEnv;
   1.403 -   void           *task;
   1.404 -                
   1.405 -   process = slave->processSlaveIsIn;
   1.406 +PRHandle__LangShutdown( PRReqst *req, SlaveVP *requestingSlv )
   1.407 + { void       *langEnv;
   1.408 +   PRLangEnv  *protoLangEnv;
   1.409 +   PRProcess  *process;
   1.410     
   1.411 -   protoLangEnv = PR_int__give_proto_lang_env_for_slave__ML( slave, 
   1.412 -                                                        req->langMagicNumber );
   1.413 +   process = requestingSlv->processSlaveIsIn;
   1.414 +   protoLangEnv = PR_int__give_proto_lang_env_from_process( process, req->langMagicNumber );
   1.415 +   langEnv = PR_int__give_lang_env( protoLangEnv );
   1.416     
   1.417 -   //Do the langlet's create-task handler, which keeps the task
   1.418 -   // inside the langlet's lang env, but returns the langMetaTask
   1.419 -   // so PR can put stuff into the prolog
   1.420 -   task = 
   1.421 -      (*req->createHdlr)(req->langReq, slave, PR_int__give_lang_env(protoLangEnv) );
   1.422 -   metaTask = PR_int__give_prolog_of_task( task );
   1.423 -   metaTask->ID         = req->ID; //may be NULL
   1.424 -   metaTask->topLevelFn = req->topLevelFn;
   1.425 -   metaTask->initData   = req->initData;
   1.426 -           
   1.427 -   process->numLiveTasks += 1;
   1.428 -
   1.429 -   return;
   1.430 - }
   1.431 -
   1.432 -/*When a task ends, have two scenarios: 1) task ran to completion, or 2) task
   1.433 - * has been suspended at some point in its code.
   1.434 - *For 1, just decr count of live tasks (and check for end condition) -- the
   1.435 - * master loop will decide what goes into the slot freed up by this task end,
   1.436 - * so, here, don't worry about assigning a new task to the slot slave.
   1.437 - *For 2, the task's slot slave has been converted to a free task slave, which
   1.438 - * now has nothing more to do, so send it to the recycle Q (which includes
   1.439 - * freeing all the langData and meta task structs alloc'd for it).  Then
   1.440 - * decrement the live task count and check end condition.
   1.441 - * 
   1.442 - *PR has to update count of live tasks, and check end of process condition.
   1.443 - * The "main" can invoke constructs that wait for a process to end, so when
   1.444 - * end detected, have to resume what's waiting..
   1.445 - *Thing is, that wait involves the main OS thread.  That means
   1.446 - * PR internals have to do OS thread signaling.  Want to do that in the
   1.447 - * core controller, which has the original stack of an OS thread.  So the
   1.448 - * end process handling happens in the core controller.
   1.449 - * 
   1.450 - *So here, when detect process end, signal to the core controller, which will
   1.451 - * then do the condition variable notify to the OS thread that's waiting.
   1.452 - * 
   1.453 - *Note: slave may be either a slot slave or a free task slave. 
   1.454 - */
   1.455 -inline 
   1.456 -void
   1.457 -PRHandle__EndTask( PRReqst *req, SlaveVP *requestingSlv )
   1.458 - { void       *langEnv;
   1.459 -   PRProcess  *process;
   1.460 -   void       *langMetaTask;
   1.461 +      //call the langlet's registered handler
   1.462 +   (*protoLangEnv->shutdownHdlr)( langEnv );
   1.463     
   1.464 -   langEnv = PR_int__give_lang_env_of_req( req, requestingSlv ); //magic num in req
   1.465 -   langMetaTask = PR_int__give_lang_meta_task_from_slave( requestingSlv, req->langMagicNumber);
   1.466 -   
   1.467 -   //Do the langlet's request handler
   1.468 -   //Want to keep PR structs hidden from plugin, so extract langReq..
   1.469 -   (*req->handler)( req->langReq, requestingSlv, langEnv );
   1.470 -   
   1.471 -   //Now that the langlet's done with it, recycle the slave if it's a freeTaskSlv
   1.472 -   if( requestingSlv->typeOfVP == FreeTaskSlv )
   1.473 -      PR_int__recycle_slave( requestingSlv ); //Doesn't decr num live slaves
   1.474 -   
   1.475 -   process->numLiveTasks -= 1;
   1.476 -   //NOTE: end-task is unrelated to work available (just in case wondering)
   1.477 -  
   1.478 -      //check End Of Process Condition
   1.479 -   if( process->numLiveTasks == 0 &&
   1.480 -       process->numLiveGenericSlvs == 0 )
   1.481 -    { //Tell the core controller to do wakeup of any waiting OS thread
   1.482 -      PR_SS__shutdown_process( process );
   1.483 -    }
   1.484 +   PR_int__remove_lang_env_from_process_and_free( langEnv ); //removes from process and frees
   1.485   }
   1.486  
   1.487  
   1.488 @@ -438,24 +528,58 @@
   1.489   */
   1.490  void inline
   1.491  PRHandle__ServiceReq( SlaveVP *requestingSlv )
   1.492 - { PRReqst   *req;
   1.493 -   PRServReq *langReq;
   1.494 -   void      *langEnv;
   1.495 -   int32      magicNumber;
   1.496 + { PRReqst      *req;
   1.497 +   PRServiceReq *langReq;
   1.498 +   PRLangEnv    *protoLangEnv;
   1.499 +   int32         magicNumber;
   1.500     
   1.501   
   1.502     req = requestingSlv->request;
   1.503   
   1.504     magicNumber = req->langMagicNumber;
   1.505 -   langEnv = PR_PI__give_lang_env_for( slave, magicNumber );
   1.506 +   protoLangEnv = PR_int__give_proto_lang_env_for_slave( requestingSlv, magicNumber );
   1.507  
   1.508     langReq = PR_PI__take_lang_reqst_from(req);
   1.509     if( langReq == NULL ) return;
   1.510     switch( langReq->reqType )  //lang handlers are all in other file
   1.511      {
   1.512 -      case make_probe:      handleMakeProbe(   langReq, langEnv );
   1.513 +      case make_probe:      handleMakeProbe(   langReq, protoLangEnv );
   1.514           break;
   1.515 -      case throw_excp:  handleThrowException(  langReq, langEnv );
   1.516 +      case throw_excp:  handleThrowException(  langReq, protoLangEnv );
   1.517           break;
   1.518      }
   1.519   }
   1.520 +
   1.521 +
   1.522 +/*These handlers are special -- they don't belong to a language, because they
   1.523 + * deal with things internal to PR, so put them here..
   1.524 + */
   1.525 +inline
   1.526 +void
   1.527 +handleMakeProbe( PRServiceReq *langReq, PRLangEnv *protoLangEnv )
   1.528 + { IntervalProbe *newProbe;
   1.529 +
   1.530 +   newProbe          = PR_int__malloc( sizeof(IntervalProbe) );
   1.531 +   newProbe->nameStr = PR_int__strDup( langReq->nameStr );
   1.532 +   newProbe->hist    = NULL;
   1.533 +   newProbe->schedChoiceWasRecorded = FALSE;
   1.534 +
   1.535 +      //This runs in masterVP, so no race-condition worries
   1.536 +      //BUG: move to process
   1.537 +   newProbe->probeID =
   1.538 +            addToDynArray( newProbe, _PRTopEnv->dynIntervalProbesInfo );
   1.539 +
   1.540 +   langReq->requestingSlv->dataRetFromReq = newProbe;
   1.541 +
   1.542 +   (*protoLangEnv->makeSlaveReadyFn)( langReq->requestingSlv, PR_int__give_lang_env(protoLangEnv) );
   1.543 + }
   1.544 +
   1.545 +inline
   1.546 +void
   1.547 +handleThrowException( PRServiceReq *langReq, PRLangEnv *protoLangEnv )
   1.548 + {
   1.549 +   PR_int__throw_exception(  langReq->msgStr, langReq->requestingSlv, langReq->exceptionData );
   1.550 +   
   1.551 +   (*protoLangEnv->makeSlaveReadyFn)( langReq->requestingSlv, PR_int__give_lang_env(protoLangEnv) );
   1.552 + }
   1.553 +
     2.1 --- a/CoreController.c	Tue Feb 05 20:23:27 2013 -0800
     2.2 +++ b/CoreController.c	Sat Mar 02 09:43:45 2013 -0800
     2.3 @@ -74,7 +74,7 @@
     2.4     bool32          foundWork;
     2.5     AnimSlot       *animSlot;
     2.6     volatile int32 *addrOfMasterLock; //thing pointed to is volatile, not ptr
     2.7 -   SlaveVP        *thisCoresMasterVP;
     2.8 +//   SlaveVP        *thisCoresMasterVP;
     2.9        //Variables used for pthread related things
    2.10     ThdParams      *thisCoresThdParams;
    2.11     cpu_set_t       coreMask;  //used during pinning pthread to CPU core
    2.12 @@ -95,9 +95,11 @@
    2.13  
    2.14     //TODO: DEBUG: check get correct pointer here
    2.15     animSlot = _PRTopEnv->allAnimSlots[ thisCoresIdx ][0];
    2.16 +   animSlot->slaveAssignedToSlot =  _PRTopEnv->idleSlv[thisCoresIdx][ZERO];
    2.17 +
    2.18     numRepetitionsWithNoWork = 0;
    2.19     addrOfMasterLock = &(_PRTopEnv->masterLock);
    2.20 -   thisCoresMasterVP = _PRTopEnv->masterVPs[ thisCoresIdx ];
    2.21 +//   thisCoresMasterVP = _PRTopEnv->masterVPs[ thisCoresIdx ];
    2.22     
    2.23     //==================== pthread related stuff ======================
    2.24        //pin the pthread to the core -- takes away Linux control
    2.25 @@ -135,7 +137,7 @@
    2.26               //Alternatively, the VP suspend primitive could just not bother
    2.27               // returning from switchToSlv, and instead jmp directly to here.
    2.28              
    2.29 -      if(animSlot->slaveAssignedToSlot->typeOfVP == Idle)
    2.30 +      if(animSlot->slaveAssignedToSlot->typeOfVP == IdleVP)
    2.31         { //The Holistic stuff turns on idle slaves..  but can also be in mode
    2.32           // where have no idle slaves..  so, this IF statement can only be true
    2.33           // executed when HOLISTIC is turned on..
    2.34 @@ -212,7 +214,7 @@
    2.35  terminateCoreCtlr(SlaveVP *currSlv)
    2.36   {
    2.37     //first, free shutdown Slv that jumped here, then end the pthread
    2.38 -   PR_int__dissipate_slaveVP__SL( currSlv );
    2.39 +   PR_int__recycle_slaveVP( currSlv );
    2.40     pthread_exit( NULL );
    2.41   }
    2.42  
    2.43 @@ -275,60 +277,141 @@
    2.44   */
    2.45  void *
    2.46  coreCtlr_Seq( void *paramsIn )
    2.47 - {
    2.48 + { 
    2.49     int32           thisCoresIdx;
    2.50     int32           numRepetitionsWithNoWork;
    2.51 -   SlaveVP        *currVP;
    2.52 -   AnimSlot       *currSlot, **animSlots;
    2.53 -   int32           currSlotIdx;
    2.54 -   int32          *addrOfMasterLock;
    2.55 -   SlaveVP        *thisCoresMasterVP;
    2.56 +   bool32          foundWork;
    2.57 +   AnimSlot       *animSlot;
    2.58 +   volatile int32 *addrOfMasterLock; //thing pointed to is volatile, not ptr
    2.59 +      //Variables used for pthread related things
    2.60 +   ThdParams      *thisCoresThdParams;
    2.61 +   cpu_set_t       coreMask;  //used during pinning pthread to CPU core
    2.62 +   int32           errorCode;
    2.63 +      //Variables used during measurements (inside macro!)
    2.64 +   TSCountLowHigh  endSusp;
    2.65 +      //Variables used in random-backoff, for master-lock and waiting for work
    2.66 +   uint32_t seed1 = rand()%1000; // init random number generator for backoffs
    2.67 +   uint32_t seed2 = rand()%1000;
    2.68 +
    2.69     
    2.70     //===============  Initializations ===================
    2.71 -   thisCoresIdx = 0; //sequential version
    2.72 -   animSlots = _PRTopEnv->allAnimSlots[thisCoresIdx];
    2.73 -   currSlotIdx = 0; //start at slot 0, go up until one empty, then do master
    2.74 +//   thisCoresThdParams = (ThdParams *)paramsIn;
    2.75 +//   thisCoresIdx = thisCoresThdParams->coreNum;
    2.76 +   thisCoresIdx = 0;
    2.77 +
    2.78 +      //Assembly that saves addr of label of return instr -- addr used in assmbly
    2.79 +   recordCoreCtlrReturnLabelAddr((void**)&(_PRTopEnv->coreCtlrReturnPt));
    2.80 +
    2.81 +   //TODO: DEBUG: check get correct pointer here
    2.82 +   animSlot = _PRTopEnv->allAnimSlots[ thisCoresIdx ][0];
    2.83 +   animSlot->slaveAssignedToSlot =  _PRTopEnv->idleSlv[thisCoresIdx][ZERO];
    2.84 +
    2.85     numRepetitionsWithNoWork = 0;
    2.86     addrOfMasterLock = &(_PRTopEnv->masterLock);
    2.87 -   thisCoresMasterVP = _PRTopEnv->masterVPs[thisCoresIdx];
    2.88     
    2.89 -      //Assembly that saves addr of label of return instr -- label in assmbly
    2.90 -   recordCoreCtlrReturnLabelAddr((void**)&(_PRTopEnv->coreCtlrReturnPt));
    2.91 +   //==================== pthread related stuff ======================
    2.92 +      //pin the pthread to the core -- takes away Linux control
    2.93 +      //Linux requires pinning to be done inside the thread-function
    2.94 +      //Designate a core by a 1 in bit-position corresponding to the core
    2.95 +/*
    2.96 +   CPU_ZERO(&coreMask); //initialize mask bits to zero
    2.97 +   CPU_SET(thisCoresThdParams->coreNum,&coreMask); //set bit repr the coreNum
    2.98 +   pthread_t selfThd = pthread_self();
    2.99 +   errorCode =
   2.100 +   pthread_setaffinity_np( selfThd, sizeof(coreMask), &coreMask);
   2.101 +   if(errorCode){ printf("\n pinning thd to core failed \n"); exit(0); }
   2.102  
   2.103 +      //make sure the controllers all start at same time, by making them wait
   2.104 +   pthread_mutex_lock(  &suspendLock );
   2.105 +   while( !(_PRTopEnv->firstProcessReady) )
   2.106 +    { pthread_cond_wait( &suspendCond, &suspendLock );
   2.107 +    }
   2.108 +   pthread_mutex_unlock( &suspendLock );
   2.109     
   2.110 +         HOLISTIC__CoreCtrl_Setup;
   2.111 +   
   2.112 +         DEBUG__printf1(TRUE, "started coreCtrlr", thisCoresIdx );
   2.113 + */
   2.114     //====================== The Core Controller ======================
   2.115 -   while(1)
   2.116 -    {
   2.117 -      if( currSlotIdx >= NUM_ANIM_SLOTS ) goto switchToMaster;
   2.118 -      currSlot = animSlots[ currSlotIdx ];
   2.119 +   while(1)  
   2.120 +    {        //Assembly code switches the core between animating a VP and
   2.121 +             // animating this core controller.  The switch is done by
   2.122 +             // changing the stack-pointer and frame-pointer and then doing
   2.123 +             // an assembly jmp.  When reading this code, the effect is 
   2.124 +             // that the "switchToSlv()" at the end of the loop is sort of a
   2.125 +             // "warp in time" -- the core disappears inside this, jmps to
   2.126 +             // animating a VP, and when that VP suspends, the suspend
   2.127 +             // jmps back. This has the effect of "returning" from the
   2.128 +             // switchToSlv() call. Then control loops back to here.
   2.129 +             //Alternatively, the VP suspend primitive could just not bother
   2.130 +             // returning from switchToSlv, and instead jmp directly to here.
   2.131 +      //core controller top of loop
   2.132 +      if(animSlot->slaveAssignedToSlot->typeOfVP == IdleVP)
   2.133 +       { //The Holistic stuff turns on idle slaves..  but can also be in mode
   2.134 +         // where have no idle slaves..  so, this IF statement can only be true
   2.135 +         // executed when HOLISTIC is turned on..
   2.136 +         numRepetitionsWithNoWork ++;
   2.137 +               HOLISTIC__Record_last_work;
   2.138 +       } 
   2.139 +      
   2.140  
   2.141 -      if( ! currSlot->needsSlaveAssigned ) //slot does have slave assigned
   2.142 -       { numRepetitionsWithNoWork = 0;     //reset B2B master count
   2.143 -         currSlotIdx ++;
   2.144 -         currVP = currSlot->slaveAssignedToSlot;
   2.145 -       }
   2.146 -      else //slot is empty, so switch to master
   2.147 -       {
   2.148 -       switchToMaster:
   2.149 -         currSlotIdx = 0; //doing switch to master, so start over at slot 0
   2.150 +
   2.151 +            HOLISTIC__Record_AppResponderInvocation_start;
   2.152 +            MEAS__Capture_Pre_Master_Lock_Point;
   2.153 +
   2.154 +      int numTriesToGetLock = 0; int gotLock = 0;
   2.155 +      while( gotLock == FALSE ) //keep going until get master lock
   2.156 +       { 
   2.157 +            //want to
   2.158 +            // reduce lock contention from cores with no work, so first
   2.159 +            // check if this is a core with no work, and busy wait if so.
   2.160 +            //Then, if it's been way too long without work, yield pthread
   2.161 +         if( numRepetitionsWithNoWork > NUM_REPS_W_NO_WORK_BEFORE_BACKOFF)
   2.162 +            doBackoff_for_TooLongWithNoWork( numRepetitionsWithNoWork, &seed1, &seed2 );
   2.163 +         if( numRepetitionsWithNoWork > NUM_REPS_W_NO_WORK_BEFORE_YIELD )
   2.164 +          { numRepetitionsWithNoWork = 0; pthread_yield(); }
   2.165 +
   2.166 +
   2.167 +            //Try to get the lock
   2.168 +         gotLock = __sync_bool_compare_and_swap( addrOfMasterLock,
   2.169 +                                                 UNLOCKED, LOCKED );
   2.170 +         if( gotLock )
   2.171 +          {    //At this point, have successfully gotten master lock.
   2.172 +               //So, break out of get-lock loop.
   2.173 +            break;
   2.174 +          }
   2.175 +            //Get here only when failed to get lock -- check in should do backoff
   2.176 +
   2.177 +         numTriesToGetLock++;   //if too many, means too much contention
   2.178 +         if( numTriesToGetLock > NUM_TRIES_BEFORE_DO_BACKOFF ) 
   2.179 +            doBackoff_for_TooLongToGetLock( numTriesToGetLock, &seed1, &seed2 );
   2.180 +         if( numTriesToGetLock > MASTERLOCK_RETRIES_BEFORE_YIELD ) 
   2.181 +          { numTriesToGetLock = 0; pthread_yield(); }
   2.182 +       } //while( currVP == NULL )
   2.183 +            MEAS__Capture_Post_Master_Lock_Point;
   2.184 +
   2.185 +         //have master lock, perform master function, which manages request
   2.186 +         // handling and assigning work to this core's slot
   2.187 +      foundWork =
   2.188           
   2.189 -         currVP = thisCoresMasterVP;
   2.190 -         
   2.191 -               MEAS__Capture_Pre_Master_Lock_Point;  //back to back because
   2.192 -               MEAS__Capture_Post_Master_Lock_Point; // sequential version
   2.193 -         
   2.194 -         if( numRepetitionsWithNoWork > NUM_REPS_W_NO_WORK_BEFORE_YIELD )
   2.195 -          { printf("Lots of reps w/o work\n");
   2.196 -            exit(0); //if no work, no way to ever get it in sequential!
   2.197 -          }
   2.198 +         masterFunction( animSlot );
   2.199 +      
   2.200 +      PR_int__release_master_lock();
   2.201 +      
   2.202 +      if( foundWork )
   2.203 +         numRepetitionsWithNoWork = 0;
   2.204 +      else
   2.205           numRepetitionsWithNoWork += 1;
   2.206 -       }
   2.207  
   2.208 -      switchToSlv(currVP); //Slave suspend makes core "return" from this call
   2.209 +      //now that master is done, have work in the slot, so switch to it
   2.210 +            HOLISTIC__Record_Work_start;
   2.211 +
   2.212 +      switchToSlv(animSlot->slaveAssignedToSlot); //Slave suspend makes core "return" from this call
   2.213        flushRegisters();    //prevent GCC optimization from doing bad things 
   2.214  
   2.215               MEAS__Capture_End_Susp_in_CoreCtlr_ForSys;
   2.216 -             
   2.217 -    } //while(1)
   2.218 +             HOLISTIC__Record_Work_end;
   2.219 +    }//while(1)
   2.220   }
   2.221 +
   2.222  #endif
     3.1 --- a/Defines/MEAS__macros_to_be_moved_to_langs.h	Tue Feb 05 20:23:27 2013 -0800
     3.2 +++ b/Defines/MEAS__macros_to_be_moved_to_langs.h	Sat Mar 02 09:43:45 2013 -0800
     3.3 @@ -22,30 +22,37 @@
     3.4  
     3.5  #ifdef VCILK
     3.6  
     3.7 +/*These defines are used in the macros below*/
     3.8  #define spawnHistIdx      1 //note: starts at 1
     3.9  #define syncHistIdx       2
    3.10  
    3.11 -#define MEAS__Make_Meas_Hists_for_Language() \
    3.12 -   _PRTopEnv->measHistsInfo = \
    3.13 +#define MEAS__Make_Meas_Hists_for_VCilk( slave, magicNum ) \
    3.14 + do \
    3.15 + { VCilkLangEnv * \
    3.16 +   langEnv = PR_PI__get_lang_env_from_slave( slave, magicNum ); \ 
    3.17 +   langEnv->measHistsInfo = \
    3.18            makePrivDynArrayOfSize( (void***)&(_PRTopEnv->measHists), 200); \
    3.19 -    makeAMeasHist( spawnHistIdx,      "Spawn",        50, 0, 200 ) \
    3.20 -    makeAMeasHist( syncHistIdx,       "Sync",         50, 0, 200 )
    3.21 +   histInfo = langEnv->measHistsInfo;
    3.22 +    makeAMeasHist( histInfo, spawnHistIdx,      "Spawn",        50, 0, 200 ) \
    3.23 +    makeAMeasHist( histInfo, syncHistIdx,       "Sync",         50, 0, 200 ) \
    3.24 + }while(FALSE); /* macro magic to protect local vars from name collision */
    3.25  
    3.26 -
    3.27 -#define Meas_startSpawn \
    3.28 +#define Meas_startSpawn fixme; /* changed names -- added __Cilk to end*/
    3.29 +    
    3.30 +#define Meas_startSpawn__Cilk \
    3.31      int32 startStamp, endStamp; \
    3.32      saveLowTimeStampCountInto( startStamp ); \
    3.33  
    3.34 -#define Meas_endSpawn \
    3.35 +#define Meas_endSpawn__Cilk \
    3.36      saveLowTimeStampCountInto( endStamp ); \
    3.37      addIntervalToHist( startStamp, endStamp, \
    3.38                               _PRTopEnv->measHists[ spawnHistIdx ] );
    3.39  
    3.40 -#define Meas_startSync \
    3.41 +#define Meas_startSync__Cilk \
    3.42      int32 startStamp, endStamp; \
    3.43      saveLowTimeStampCountInto( startStamp ); \
    3.44  
    3.45 -#define Meas_endSync \
    3.46 +#define Meas_endSync__Cilk \
    3.47      saveLowTimeStampCountInto( endStamp ); \
    3.48      addIntervalToHist( startStamp, endStamp, \
    3.49                               _PRTopEnv->measHists[ syncHistIdx ] );
     4.1 --- a/HW_Dependent_Primitives/PR__primitives.h	Tue Feb 05 20:23:27 2013 -0800
     4.2 +++ b/HW_Dependent_Primitives/PR__primitives.h	Sat Mar 02 09:43:45 2013 -0800
     4.3 @@ -31,8 +31,10 @@
     4.4  void 
     4.5  jmpToTwoParamFn();
     4.6  
     4.7 -void *
     4.8 +void
     4.9  asmTerminateCoreCtlr(SlaveVP *currSlv);
    4.10 +void
    4.11 +asmTerminateCoreCtlrSeq(SlaveVP *animatingSlv);
    4.12  
    4.13  #define flushRegisters() \
    4.14          asm volatile ("":::"%rbx", "%r12", "%r13","%r14","%r15")
     5.1 --- a/HW_Dependent_Primitives/PR__primitives_asm.s	Tue Feb 05 20:23:27 2013 -0800
     5.2 +++ b/HW_Dependent_Primitives/PR__primitives_asm.s	Sat Mar 02 09:43:45 2013 -0800
     5.3 @@ -156,7 +156,7 @@
     5.4  
     5.5  /*
     5.6   * This one for the sequential version is special. It discards the current stack
     5.7 - * and returns directly from the coreCtlr after PR_WL__dissipate_slaveVP was called
     5.8 + * and returns directly from the coreCtlr
     5.9   */
    5.10  .globl asmTerminateCoreCtlrSeq
    5.11  asmTerminateCoreCtlrSeq:
    5.12 @@ -164,7 +164,7 @@
    5.13      movq    0x20(%rdi), %rsp         #restore stack pointer
    5.14      movq    0x18(%rdi), %rbp         #restore frame pointer
    5.15      #argument is in %rdi
    5.16 -    call    PR_int__dissipate_slaveVP__SL
    5.17 +    call    PR_int__free_slaveVP
    5.18      movq    %rbp      , %rsp        #goto the coreCtlrs stack
    5.19      pop     %rbp        #restore the old framepointer
    5.20      ret                 #return from core controller
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/PR.c	Sat Mar 02 09:43:45 2013 -0800
     6.3 @@ -0,0 +1,314 @@
     6.4 +/*
     6.5 + * Copyright 2010  OpenSourceResearchInstitute
     6.6 + *
     6.7 + * Licensed under BSD
     6.8 + */
     6.9 +
    6.10 +#include <stdio.h>
    6.11 +#include <stdlib.h>
    6.12 +#include <string.h>
    6.13 +#include <malloc.h>
    6.14 +#include <inttypes.h>
    6.15 +#include <sys/time.h>
    6.16 +#include <pthread.h>
    6.17 +
    6.18 +#include "PR.h"
    6.19 +
    6.20 +
    6.21 +#define thdAttrs NULL
    6.22 +
    6.23 +
    6.24 +/* MEANING OF   WL  PI  SS  int
    6.25 + * These indicate which places the function is safe to use.  They stand for:
    6.26 + * WL: Wrapper Library
    6.27 + * PI: Plugin 
    6.28 + * SS: Startup and Shutdown
    6.29 + * int: internal to the PR implementation
    6.30 + */
    6.31 +
    6.32 +
    6.33 +//===========================================================================
    6.34 +
    6.35 +//===========================================================================
    6.36 +
    6.37 +/*Setup has two phases:
    6.38 + * 1) Semantic layer first calls init_PR, which creates masterEnv, and puts
    6.39 + *    the master Slv into the work-queue, ready for first "call"
    6.40 + * 2) Semantic layer then does its own init, which creates the seed virt
    6.41 + *    slave inside the semantic layer, ready to assign it when
    6.42 + *    asked by the first run of the animationMaster.
    6.43 + *
    6.44 + *This part is bit weird because PR really wants to be "always there", and
    6.45 + * have applications attach and detach..  for now, this PR is part of
    6.46 + * the app, so the PR system starts up as part of running the app.
    6.47 + *
    6.48 + *The semantic layer is isolated from the PR internals by making the
    6.49 + * semantic layer do setup to a state that it's ready with its
    6.50 + * initial Slvs, ready to assign them to slots when the animationMaster
    6.51 + * asks.  Without this pattern, the semantic layer's setup would
    6.52 + * have to modify slots directly to assign the initial virt-procrs, and put
    6.53 + * them into the readyToAnimateQ itself, breaking the isolation completely.
    6.54 + *
    6.55 + * 
    6.56 + *The semantic layer creates the initial Slv(s), and adds its
    6.57 + * own environment to masterEnv, and fills in the pointers to
    6.58 + * the requestHandler and slaveAssigner plug-in functions
    6.59 + */
    6.60 +
    6.61 +//Check the comments above -- likely out of sync
    6.62 +
    6.63 +/*This allocates PR data structures, populates the top environments.  After
    6.64 + * this call, processes can be started.
    6.65 + */
    6.66 +void
    6.67 +PR__start()
    6.68 + {
    6.69 +   PR_SS__create_topEnv();
    6.70 +   
    6.71 +  #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
    6.72 +   printf( "\n\n Running in SEQUENTIAL mode \n\n" );
    6.73 +      //Only difference between version with an OS thread pinned to each core and
    6.74 +      // the sequential version of PR is PR__init_Seq, this, and coreCtlr_Seq.
    6.75 +
    6.76 +      //Don't do anything here -- using main thread for all PR activity, so
    6.77 +      // do PR activity when main thread calls "wait for process to end"
    6.78 +  #else
    6.79 +   DEBUG__printf1(dbgInfra,"Offset of lock in masterEnv: %d ", (int32)offsetof(TopEnv,masterLock) );
    6.80 +   PR_SS__create_the_coreCtlr_OS_threads();
    6.81 +
    6.82 +  #endif
    6.83 + }
    6.84 +
    6.85 +
    6.86 +/*For now, this is ONLY called from the main thread -- seems this can be relaxed
    6.87 + * at some point, but want to reduce complexity to get the first version working
    6.88 + * so making this restriction for now..
    6.89 + * 
    6.90 + *It creates a seed slave, from the top-level fn and initial data passed into
    6.91 + * this fn.
    6.92 + *The only langlet in the created process is the default PRServ.  The rest
    6.93 + * must be started up via calls  made by the seed VP's top-level fn (passed in
    6.94 + * to this call).
    6.95 + *That places the information about which langlets are used within the process
    6.96 + * into the seed Fn of that process, where all the langlet start() calls are
    6.97 + * made.
    6.98 + * 
    6.99 + *A process is represented by a structure that holds all the process-specific
   6.100 + * information:
   6.101 + *-] The hash-array containing the language environs of any langlets started
   6.102 + *   inside the process.
   6.103 + *-] Counter of num live slaves and num live tasks in the process
   6.104 + * 
   6.105 + */
   6.106 +PRProcess *
   6.107 +PR__create_process( TopLevelFnPtr seed_Fn, void *seedData )
   6.108 + { SlaveVP    *seedSlv;
   6.109 +   PRProcess  *process;
   6.110 +   PRLangEnv **langEnvs, **langEnvsList;
   6.111 +      
   6.112 +      //This runs outside of the master lock, so use PR_WL form of malloc
   6.113 +   process = PR_WL__malloc( sizeof(PRProcess) );
   6.114 +   _PRTopEnv->processes[_PRTopEnv->numProcesses] = process;
   6.115 +   _PRTopEnv->numProcesses += 1;
   6.116 +   
   6.117 +   langEnvs     = 
   6.118 +      (PRLangEnv **)PR_int__make_collection_of_size( NUM_IN_COLLECTION );
   6.119 +   langEnvsList = PR_WL__malloc( NUM_IN_COLLECTION * sizeof(PRCollElem *) );
   6.120 +   process->langEnvs     = langEnvs;
   6.121 +   process->protoLangEnvsList = langEnvsList;
   6.122 +   process->numLangEnvs  = 0;
   6.123 +   
   6.124 +      //A Process starts with one slave, the seed slave
   6.125 +   seedSlv = PR_int__create_slaveVP( seed_Fn, seedData, process );
   6.126 +   seedSlv->typeOfVP           = SeedSlv;
   6.127 +   seedSlv->processSlaveIsIn   = process;
   6.128 +   process->numLiveGenericSlvs = 1; //count the  seed 
   6.129 +   process->numLiveTasks       = 0;
   6.130 +   
   6.131 +   PRServLangEnv * 
   6.132 +   servicesLangEnv = 
   6.133 +     PRServ__start(seedSlv);
   6.134 +   
   6.135 +      //resume seedVP into PR's built-in services language's lang env
   6.136 +   process->numEnvsWithWork = 0; //Seed is in PRServ lang env.. resume incrs this
   6.137 +   PR_PI__make_slave_ready( seedSlv, servicesLangEnv );
   6.138 +   
   6.139 +
   6.140 +      //The first process created has to unblock the core controllers.
   6.141 +      // This is the "magic" that starts the activity of PR going.
   6.142 +   #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
   6.143 +      //Do nothing here..  in sequential mode, are using the main thread, so
   6.144 +      // don't use it to do anything yet..  do the PR activity when main thread
   6.145 +      // calls "wait for process to end"
   6.146 +   #else
   6.147 +   if( _PRTopEnv->numProcesses == 1 )
   6.148 +    {
   6.149 +         //tell the core controller threads that a process is ready to be animated
   6.150 +         //get lock, to lock out any threads still starting up -- they'll see
   6.151 +         // that firstProcessReady is true before entering while loop, and so never
   6.152 +         // wait on the condition
   6.153 +      pthread_mutex_lock(     &suspendLock );
   6.154 +      _PRTopEnv->firstProcessReady = 1;
   6.155 +      pthread_mutex_unlock(   &suspendLock );
   6.156 +      pthread_cond_broadcast( &suspendCond );
   6.157 +    }
   6.158 +   #endif
   6.159 +   pthread_mutex_init( &(process->doneLock), NULL );
   6.160 +   pthread_cond_init(  &(process->doneCond), NULL );
   6.161 +   process->executionIsComplete = FALSE;
   6.162 +   
   6.163 +   return process;
   6.164 + }
   6.165 +
   6.166 +PR__end_seedVP( SlaveVP *seedSlv )
   6.167 + {
   6.168 +   PR_WL__send_end_slave_req( NULL, (RequestHandler)&PRServ__handleDissipateSeed, seedSlv, 
   6.169 +                              PRServ_MAGIC_NUMBER );
   6.170 + }
   6.171 +
   6.172 +PR__end_process_from_inside( SlaveVP *seedSlv )
   6.173 + {   
   6.174 +   PR_WL__send_lang_request( NULL, (RequestHandler)&PRServ__handle_end_process_from_inside,
   6.175 +                             seedSlv, PRServ_MAGIC_NUMBER );
   6.176 + }
   6.177 +
   6.178 +
   6.179 +
   6.180 +/*When all work in the process has completed, then return from this call.
   6.181 + * The seedVP of the process may still exist, but it has no work, nor do any
   6.182 + * other VPs..
   6.183 + *The process must be shutdown via a separate call.  That shutdown frees the
   6.184 + * process struct and bookkeeping structs.
   6.185 + *First checks whether the process is done, if yes, calls the clean-up fn then
   6.186 + * returns the result extracted from the PRProcess struct.
   6.187 + *If process not done yet, then performs a wait (in a loop to be sure the
   6.188 + * wakeup is not spurious, which can happen).  PR registers the wait, and upon
   6.189 + * the process ending (last SlaveVP owned by it dissipates), then PR signals
   6.190 + * this to wakeup.  This then calls the cleanup fn and returns the result.
   6.191 + */
   6.192 +void *
   6.193 +PR__give_results_from_process_when_ready( PRProcess *process )
   6.194 + { void *result;
   6.195 +      //First get the "ACK" lock, then do normal wait for signal, then release
   6.196 +      // ACK lock, to let end-process know it can free the process struct
   6.197 +   pthread_mutex_lock( &(process->doneAckLock) );
   6.198 +   
   6.199 +   pthread_mutex_lock( &(process->doneLock) );
   6.200 +   while( process->executionIsComplete != TRUE )
   6.201 +    {
   6.202 +      pthread_cond_wait( &(process->doneCond),
   6.203 +                         &(process->doneLock) );
   6.204 +    }
   6.205 +   pthread_mutex_unlock( &(process->doneLock) );
   6.206 +   result = process->resultToReturn;
   6.207 +   
   6.208 +      //now send "ACK" signal to process_end Fn, that it may proceed
   6.209 +   pthread_mutex_unlock( &(process->doneAckLock) ); 
   6.210 +      
   6.211 +   return result;
   6.212 +      //TODO: BUG? -- can process be created and end, before this acquires the
   6.213 +      // first lock?  Can see some rare code that creates a bunch, before getting
   6.214 +      // to waiting..  leave for now..  pain to fix..
   6.215 + }
   6.216 +
   6.217 +
   6.218 +void
   6.219 +PR__wait_for_process_to_end( PRProcess *process )
   6.220 + { 
   6.221 +  #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
   6.222 +      // call the one and only core ctlr (sequential version), in the main thread.
   6.223 +   coreCtlr_Seq( NULL );
   6.224 +   flushRegisters();  //Not sure why here, but leaving to be safe
   6.225 +
   6.226 +  #else
   6.227 +      //First get the "ACK" lock, then do normal wait for signal, then release
   6.228 +      // ACK lock, to let end-process know it can free the process struct
   6.229 +   pthread_mutex_lock( &(process->doneAckLock) );   
   6.230 +   pthread_mutex_lock( &(process->doneLock) );
   6.231 +   while( process->executionIsComplete != TRUE )
   6.232 +    {
   6.233 +      pthread_cond_wait( &(process->doneCond),
   6.234 +                         &(process->doneLock) );
   6.235 +    }
   6.236 +   pthread_mutex_unlock( &(process->doneLock) );
   6.237 +      //now send "ACK" signal to process_end Fn, that it may proceed
   6.238 +   pthread_mutex_unlock( &(process->doneAckLock) ); 
   6.239 +   
   6.240 +      //TODO: BUG? -- can process be created and end, before this acquires the
   6.241 +      // first lock?  Can see some rare code that creates a bunch, before getting
   6.242 +      // to waiting..  leave for now..  pain to fix..
   6.243 +  #endif
   6.244 + }
   6.245 +
   6.246 +
   6.247 +void
   6.248 +PR__wait_for_all_activity_to_end()
   6.249 + { 
   6.250 +   pthread_mutex_lock( &(_PRTopEnv->activityDoneLock) );
   6.251 +   while( !(_PRTopEnv->allActivityIsDone) )
   6.252 +    {
   6.253 +      pthread_cond_wait( &(_PRTopEnv->activityDoneCond),
   6.254 +                         &(_PRTopEnv->activityDoneLock) );
   6.255 +    }
   6.256 +   pthread_mutex_unlock( &(_PRTopEnv->activityDoneLock) );
   6.257 + }
   6.258 +
   6.259 +
   6.260 +/*This info is retrieved by PRServ's "give environ string" function
   6.261 + *These Fn s are meant to be called from main, or possibly the seed slave. 
   6.262 + */
   6.263 +void
   6.264 +PR__set_app_info( char *info )
   6.265 + { int32 len;
   6.266 +   char *copy;
   6.267 +   len = strlen(info) +1;
   6.268 +   copy = PR_int__malloc(len);
   6.269 +   strcpy(copy, info);
   6.270 +   _PRTopEnv->metaInfo->appInfo = copy;
   6.271 + }
   6.272 +void
   6.273 +PR__set_input_info( char *info )
   6.274 + { int32 len;
   6.275 +   char *copy;
   6.276 +   len = strlen(info) +1;
   6.277 +   copy = PR_int__malloc(len);
   6.278 +   strcpy(copy, info);
   6.279 +   _PRTopEnv->metaInfo->inputInfo = copy;
   6.280 + }
   6.281 +
   6.282 +
   6.283 +
   6.284 +
   6.285 +//==========================  SHUT DOWN  ===========================
   6.286 +
   6.287 +/*This is called from the main thread, and causes PR's OS threads to stop
   6.288 + * then cleans up any memory allocated by PR from the OS.
   6.289 + * 
   6.290 + *The main thread has a separate call it can use to wait for all work to
   6.291 + * finish, so when this is called, it just shuts down, whether there's
   6.292 + * unfinished work or not.
   6.293 + * 
   6.294 + *However, cores that are performing work won't see this shutdown until
   6.295 + * they finish their current work-unit.
   6.296 + */
   6.297 +void
   6.298 +PR__shutdown()
   6.299 + { int32 coreIdx;
   6.300 +   
   6.301 +   PR_SS__shutdown_OS_threads();
   6.302 +   
   6.303 +      //wait for the OS threads to exit
   6.304 +   for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ )
   6.305 +    {
   6.306 +      pthread_join( coreCtlrThdHandles[coreIdx], NULL );
   6.307 +    }
   6.308 +
   6.309 +      //Before getting rid of everything, print out any measurements made
   6.310 +   PR_SS__print_out_measurements();
   6.311 +
   6.312 +      //free all memory allocated from the OS
   6.313 +   PR_SS__cleanup_at_end_of_shutdown();
   6.314 + }
   6.315 +
   6.316 +
   6.317 +
     7.1 --- a/PR.h	Tue Feb 05 20:23:27 2013 -0800
     7.2 +++ b/PR.h	Sat Mar 02 09:43:45 2013 -0800
     7.3 @@ -86,7 +86,7 @@
     7.4  #include "PR__WL.h"
     7.5  
     7.6  //=================================
     7.7 -#define implement_me printf("Unimpl Fn: \n%s \n%s : %s\n", __FILE__, __FUNCTION__, __LINE__)
     7.8 +#define implement_me() printf("Unimpl Fn: \n%s \n%s : %d\n", __FILE__, __FUNCTION__, __LINE__)
     7.9  //#define fix_me printf("Fix me at: \n%s \n%s : %s\n", __FILE__, __FUNCTION__, __LINE__)
    7.10  
    7.11  
     8.1 --- a/PR__PI.c	Tue Feb 05 20:23:27 2013 -0800
     8.2 +++ b/PR__PI.c	Sat Mar 02 09:43:45 2013 -0800
     8.3 @@ -49,6 +49,16 @@
     8.4      }
     8.5   }
     8.6  
     8.7 +/*Any langlet can transfer slaves over to be resumed in PRServ.. the resume Fn
     8.8 + * is registered in the PRServ lang env during process creation.
     8.9 + */
    8.10 +void
    8.11 +PR_PI__resume_slave_in_PRServ( SlaveVP *slave )
    8.12 + { void *langEnv;
    8.13 +   langEnv = PR_PI__give_lang_env_for_slave( slave, PRServ_MAGIC_NUMBER );
    8.14 +   PR_PI__make_slave_ready( slave, langEnv );
    8.15 + }
    8.16 +
    8.17  void
    8.18  PR_PI__make_task_ready( void *_task, void *_langEnv )
    8.19   { PRLangEnv *protoLangEnv;
    8.20 @@ -57,7 +67,7 @@
    8.21      {
    8.22        //put task into override readyQ
    8.23        
    8.24 -      //update override hasWork flag ?
    8.25 +      //update numWorkReady
    8.26      }
    8.27     else
    8.28      { //call langlet's registered make ready
    8.29 @@ -72,7 +82,84 @@
    8.30      }
    8.31   }
    8.32  
    8.33 +
    8.34 +/*This is used by langlets..  the intent is that they provide a wrapper
    8.35 + * lib call for a "wait" command, and then call this PR service inside their
    8.36 + * request handler.
    8.37 + *Note: PRServ doesn't offer a "wait for work to end".. it also doesn't have any
    8.38 + * create work calls..  and there is no way to end PRServ, except by ending the
    8.39 + * process.  Therefore, this can safely use the PRServ env to
    8.40 + * resume any waiting slaves (incl free task slaves, which are one-to-one
    8.41 + * with a task).
    8.42 + */
    8.43 +void
    8.44 +PR_PI__handle_wait_for_langlets_work_to_end( SlaveVP *slave, void *langEnv )
    8.45 + { PRLangEnv *protoLangEnv;
    8.46   
    8.47 +   protoLangEnv = PR_int__give_proto_lang_env( langEnv );
    8.48 +
    8.49 +   if( protoLangEnv->numLiveWork == 0 )
    8.50 +    {    //resume into different env than one with no work, as it may be shut down
    8.51 +      void *
    8.52 +      resumeEnv = PR_PI__give_lang_env_from_process( slave->processSlaveIsIn, PRServ_MAGIC_NUMBER ); 
    8.53 +      PR_PI__make_slave_ready( slave, resumeEnv );
    8.54 +      return;
    8.55 +    }
    8.56 +   else
    8.57 +    {
    8.58 +      writePrivQ( slave, protoLangEnv->waitingForWorkToEndQ );
    8.59 +    }
    8.60 + }
    8.61 +   
    8.62 +SlaveVP *
    8.63 +PR_PI__give_slave_lang_meta_task_is_assigned_to( void *langMetaTask )
    8.64 + { PRMetaTask *metaTask = PR_int__give_prolog_of_lang_meta_task( langMetaTask );
    8.65 +   return metaTask->slaveAssignedTo;
    8.66 + }
    8.67 +
    8.68 +void
    8.69 +PR_PI__set_no_del_flag_in_lang_meta_task( void *langMetaTask )
    8.70 + { PRMetaTask *protoMetaTask = PR_int__give_prolog_of_lang_meta_task( langMetaTask );
    8.71 +   protoMetaTask->goAheadAndFree = FALSE;
    8.72 + }
    8.73 +
    8.74 +void
    8.75 +PR_PI__clear_no_del_flag_in_lang_meta_task( void *langMetaTask )
    8.76 + { PRMetaTask *protoMetaTask = PR_int__give_prolog_of_lang_meta_task( langMetaTask );
    8.77 +   protoMetaTask->goAheadAndFree = TRUE;
    8.78 + }
    8.79 +
    8.80 +/*Two use-cases for freeing a meta-task..  one is the langlet has control
    8.81 + * over the meta tasks's life-line it may differ from the task-work-unit's
    8.82 + * lifeline..  the other is PR controls, for example when a langlet or 
    8.83 + * process gets pre-maturely shutdown due to outside influences, or exception,
    8.84 + * and so on..
    8.85 + *In the first case, the langlet has two choices..  it can free all the langlet
    8.86 + * malloc'd data owned by the meta-task, then as PR to free the remaining
    8.87 + * proto meta-task..  or, it can just call PR's full-service "free meta-task"
    8.88 + * which in turn calls the langlet's "free just langlet-malloc'd data" Fn, which
    8.89 + * was given to the meta-task creator..
    8.90 + * 
    8.91 + *In the second case, PR calls the langlet's "free just langlet malloc'd data"
    8.92 + * Fn, which was given to the meta-task creator.  The langlet has no other 
    8.93 + * involvement.
    8.94 + * 
    8.95 + *This is used by the langlet when it separately frees its own
    8.96 + * portion of the meta-task.
    8.97 + * 
    8.98 + *PR uses "PR_int__free_lang_meta_task", which calls the langlet's freer, which
    8.99 + * was given to the meta task creator
   8.100 + */
   8.101 +void
   8.102 +PR_PI__free_proto_meta_task_by_langlet( PRMetaTask *protoMetaTask )
   8.103 + { 
   8.104 +   PR_int__remove_elem_from_collection( protoMetaTask->langMagicNumber,
   8.105 +                    (PRCollElem **) protoMetaTask->slaveAssignedTo->metaTasks );
   8.106 +
   8.107 +   PR_int__free( protoMetaTask );       
   8.108 + }
   8.109 +
   8.110 +
   8.111  PRReqst *
   8.112  PR_PI__take_next_request_out_of( SlaveVP *slaveWithReq )
   8.113   { PRReqst *req;
     9.1 --- a/PR__PI.h	Tue Feb 05 20:23:27 2013 -0800
     9.2 +++ b/PR__PI.h	Sat Mar 02 09:43:45 2013 -0800
     9.3 @@ -36,28 +36,159 @@
     9.4   * wrapper-library calls!
     9.5   */
     9.6  
     9.7 -#define PR_PI__create_slaveVP PR_int__create_slaveVP_helper
     9.8 +#define \
     9.9 +PR_PI__create_slaveVP   PR_int__create_slaveVP_helper
    9.10  
    9.11 -inline
    9.12 +//==============
    9.13 +//=== Lang Data
    9.14 +//=
    9.15 +#define \
    9.16 +PR_PI__give_lang_data_from_slave   PR_int__give_lang_data_from_slave
    9.17 +#define \
    9.18 +PR_SS__give_lang_data_from_slave   PR_int__give_lang_data_from_slave
    9.19 +
    9.20 +
    9.21 +//============
    9.22 +//=== Lang Env
    9.23 +//=
    9.24 +#define \
    9.25 +PR_PI__give_proto_lang_env_for_slave   PR_int__give_proto_lang_env_for_slave
    9.26 +#define \
    9.27 +PR_PI__give_lang_env_for_slave   PR_int__give_lang_env_for_slave
    9.28 +#define \
    9.29 +PR_PI__give_lang_env_from_process   PR_int__give_lang_env_from_process
    9.30 +
    9.31 +
    9.32 +//=========
    9.33 +//=== Meta Task
    9.34 +//=
    9.35 +#define \
    9.36 +PR_PI__give_lang_meta_task_from_slave    PR_int__give_lang_meta_task_from_slave
    9.37 +#define \
    9.38 +PR_PI__give_prolog_of_lang_meta_task   PR_int__give_prolog_of_lang_meta_task
    9.39 +
    9.40  SlaveVP *
    9.41  PR_PI__give_slave_lang_meta_task_is_assigned_to( void *langMetaTask );
    9.42  
    9.43 +#define \
    9.44 +PR_PI__free_lang_meta_task_and_remove_from_slave    PR_int__free_lang_meta_task_and_remove_from_coll
    9.45 +
    9.46 +#define \
    9.47 +PR_PI__free_lang_meta_task    PR_int__free_lang_meta_task
    9.48 +
    9.49 +void
    9.50 +PR_PI__set_no_del_flag_in_lang_meta_task( void *langMetaTask );
    9.51 +void
    9.52 +PR_PI__clear_no_del_flag_in_lang_meta_task( void *langMetaTask );
    9.53 +
    9.54 +//==========
    9.55 +//===
    9.56 +//=
    9.57 +#define \
    9.58 +PR_PI__give_ID_from_lang_meta_task   PR__give_ID_from_lang_meta_task
    9.59 +#define \
    9.60 +PR_PI__give_ID_from_slave   PR__give_ID_from_slave
    9.61 +
    9.62 +//=============
    9.63 +//===
    9.64 +//=
    9.65 +#define \
    9.66 +PR_PI__put_slave_into_slot   PR_int__put_slave_into_slot
    9.67 +#define \
    9.68 +PR_PI__put_task_into_slot    PR_int__put_task_into_slot
    9.69  
    9.70  PRReqst *
    9.71  PR_PI__take_next_request_out_of( SlaveVP *slaveWithReq );
    9.72 -//#define PR_PI__take_next_request_out_of( slave ) slave->requests
    9.73  
    9.74 -//inline void *
    9.75 -//PR_PI__take_lang_reqst_from( PRReqst *req );
    9.76 -#define PR_PI__take_lang_reqst_from( req ) req->langReqData
    9.77 +#define \
    9.78 +PR_PI__take_lang_reqst_from( req )   req->langReq
    9.79 +
    9.80 +void
    9.81 +PR_PI__resume_slave_in_PRServ( SlaveVP *slave );
    9.82 +
    9.83 +#define \
    9.84 +PR_PI__malloc   PR_int__malloc
    9.85 +#define \
    9.86 +PR_PI__malloc_aligned   PR_int__malloc_aligned
    9.87 +#define \
    9.88 +PR_PI__free  PR_int__free
    9.89 +
    9.90 +
    9.91 +#define \
    9.92 +PR_PI__throw_exception   PR_int__throw_exception
    9.93  
    9.94  //===============  Startup and Shutdown  ================
    9.95 +//===
    9.96 +//=
    9.97 +void
    9.98 +PR_SS__create_topEnv();
    9.99 +
   9.100 +AnimSlot **
   9.101 +PR_SS__create_anim_slots( int32 coreSlotsAreOn );
   9.102 +
   9.103 +void
   9.104 +PR_SS__create_the_coreCtlr_OS_threads();
   9.105 +
   9.106 +//===================
   9.107 +void *
   9.108 +PR_SS__create_lang_env( int32 size, SlaveVP *slave, int32 magicNum );
   9.109 +
   9.110 +void
   9.111 +PR_SS__register_assigner( SlaveAssigner assigner, SlaveVP *seedVP, int32 magicNum );
   9.112 +void
   9.113 +PR_SS__register_lang_shutdown_handler( LangShutdownHdlr shutdownHdlr, SlaveVP *seedVP,
   9.114 +                                  int32 magicNum );
   9.115 +void
   9.116 +PR_SS__register_lang_data_creator( LangDataCreator langDataCreator, 
   9.117 +                                              SlaveVP *seedVP, int32 magicNum );
   9.118 +void
   9.119 +PR_SS__register_lang_meta_task_creator( LangDataCreator langMetaTaskCreator, 
   9.120 +                                              SlaveVP *seedVP, int32 magicNum );
   9.121 +void
   9.122 +PR_SS__register_make_slave_ready_fn( MakeSlaveReadyFn fn, SlaveVP *seedVP,
   9.123 +                                                               int32 magicNum );
   9.124 +void
   9.125 +PR_SS__register_make_task_ready_fn( MakeTaskReadyFn fn, SlaveVP *seedVP,
   9.126 +                                                               int32 magicNum );
   9.127 +//===================
   9.128 +
   9.129 +void
   9.130 +PR_SS__end_process_normally( PRProcess *process );
   9.131 +
   9.132  void
   9.133  PR_SS__shutdown_OS_threads();
   9.134 +
   9.135 +SlaveVP* 
   9.136 +PR_SS__create_shutdown_slave();
   9.137 +
   9.138 +void
   9.139 +PR_SS__cleanup_at_end_of_shutdown();
   9.140   
   9.141  void
   9.142  PR_SS__print_out_measurements();
   9.143  
   9.144 +void
   9.145 +PR_SS__wait_for_PR_to_shutdown();
   9.146 +
   9.147 +
   9.148 +//=============================
   9.149 +//===
   9.150 +//=
   9.151 +
   9.152 +#define \
   9.153 +PR_SS__give_proto_lang_env_for_slave   PR_int__give_proto_lang_env_for_slave
   9.154 +
   9.155 +#define \
   9.156 +PR_SS__give_lang_meta_task_from_slave   PR_int__give_lang_meta_task_from_slave
   9.157 +#define \
   9.158 +PR_SS__give_lang_env_for_slave   PR_int__give_lang_env_for_slave
   9.159 +#define \
   9.160 +PR_SS__give_lang_env_from_process   PR_int__give_lang_env_from_process
   9.161 +
   9.162 +#define \
   9.163 +PR_SS__malloc  PR_WL__malloc /*SS happens outside the Master*/
   9.164 +#define \
   9.165 +PR_SS__free    PR_WL__free
   9.166  
   9.167  //================================================
   9.168  #endif	/* _PR__PI_H */
    10.1 --- a/PR__SS.c	Tue Feb 05 20:23:27 2013 -0800
    10.2 +++ b/PR__SS.c	Sat Mar 02 09:43:45 2013 -0800
    10.3 @@ -28,14 +28,6 @@
    10.4  
    10.5  
    10.6  //===========================================================================
    10.7 -AnimSlot **
    10.8 -create_anim_slots( int32 coreSlotsAreOn );
    10.9 -
   10.10 -void
   10.11 -create_topEnv();
   10.12 -
   10.13 -void
   10.14 -create_the_coreCtlr_OS_threads();
   10.15  
   10.16  MallocProlog *
   10.17  create_free_list();
   10.18 @@ -45,571 +37,8 @@
   10.19  
   10.20  
   10.21  //===========================================================================
   10.22 -
   10.23 -/*Setup has two phases:
   10.24 - * 1) Semantic layer first calls init_PR, which creates masterEnv, and puts
   10.25 - *    the master Slv into the work-queue, ready for first "call"
   10.26 - * 2) Semantic layer then does its own init, which creates the seed virt
   10.27 - *    slave inside the semantic layer, ready to assign it when
   10.28 - *    asked by the first run of the animationMaster.
   10.29 - *
   10.30 - *This part is bit weird because PR really wants to be "always there", and
   10.31 - * have applications attach and detach..  for now, this PR is part of
   10.32 - * the app, so the PR system starts up as part of running the app.
   10.33 - *
   10.34 - *The semantic layer is isolated from the PR internals by making the
   10.35 - * semantic layer do setup to a state that it's ready with its
   10.36 - * initial Slvs, ready to assign them to slots when the animationMaster
   10.37 - * asks.  Without this pattern, the semantic layer's setup would
   10.38 - * have to modify slots directly to assign the initial virt-procrs, and put
   10.39 - * them into the readyToAnimateQ itself, breaking the isolation completely.
   10.40 - *
   10.41 - * 
   10.42 - *The semantic layer creates the initial Slv(s), and adds its
   10.43 - * own environment to masterEnv, and fills in the pointers to
   10.44 - * the requestHandler and slaveAssigner plug-in functions
   10.45 - */
   10.46 -
   10.47 -//Check the comments above -- likely out of sync
   10.48 -
   10.49 -/*This allocates PR data structures, populates the top environments.  After
   10.50 - * this call, processes can be started.
   10.51 - */
   10.52  void
   10.53 -PR__start()
   10.54 - {
   10.55 -   create_topEnv();
   10.56 -   
   10.57 -  #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
   10.58 -   printf( "\n\n Running in SEQUENTIAL mode \n\n" );
   10.59 -  #else
   10.60 -   DEBUG__printf1(dbgInfra,"Offset of lock in masterEnv: %d ", (int32)offsetof(TopEnv,masterLock) );
   10.61 -   create_the_coreCtlr_OS_threads();
   10.62 -
   10.63 -  #endif
   10.64 - }
   10.65 -
   10.66 -
   10.67 -/*This creates a new process and sets the mode to single lang for it
   10.68 - *It creates a seed slave, from the top-level fn and initial data passed into
   10.69 - * this fn.
   10.70 - *The only langlet in the created process is the default PRServ.  The rest
   10.71 - * must b e started up via calls  made by the seed VP's top-level fn (passed in
   10.72 - * to this call).
   10.73 - * 
   10.74 - *A process is represented by a structure that holds all the process-specific
   10.75 - * information:
   10.76 - *-] The hash-array containing the language environs of any langlets started
   10.77 - *   inside the process.
   10.78 - *-] Counter of num live slaves and num live tasks in the process
   10.79 - * 
   10.80 - */
   10.81 -/*
   10.82 -PRProcess *
   10.83 -PR__create_process__SL( TopLevelFnPtr seed_Fn, void *seedData )
   10.84 - { SlaveVP    *seedSlv;
   10.85 -   PRProcess  *process;
   10.86 -   PRLangEnv **langEnvs, **langEnvsList;
   10.87 -   
   10.88 -   _PRTopEnv->mode         = SingleLang;
   10.89 -   
   10.90 -   
   10.91 -   process = malloc( sizeof(PRProcess) );
   10.92 -   _PRTopEnv->processes[_PRTopEnv->numProcesses] = process;
   10.93 -   _PRTopEnv->numProcesses += 1;
   10.94 -   
   10.95 -   langEnvs     = malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRCollElem *) );
   10.96 -   ((int32 *)langEnvs)[0]  = NUM_IN_COLLECTION;
   10.97 -   langEnvsList = malloc( NUM_IN_COLLECTION * sizeof(PRCollElem *) );
   10.98 -   process->langEnvs     = langEnvs;
   10.99 -   process->langEnvsList = langEnvsList;
  10.100 -   process->numLangEnvs  = 0;
  10.101 -   
  10.102 -      //A Process starts with one slave, the seed slave
  10.103 -   seedSlv = PR_int__create_slaveVP( seed_Fn, seedData, process );
  10.104 -   seedSlv->typeOfVP           = SeedSlv;
  10.105 -   seedSlv->processSlaveIsIn   = process;
  10.106 -   process->numLiveGenericSlvs = 1; //count the  seed
  10.107 -   process->numLiveTasks       = 0;
  10.108 -   
  10.109 -   PRServLangEnv *
  10.110 -   servicesLangEnv = 
  10.111 -    PR_int__create_lang_env_in_process( sizeof(PRServLangEnv), process, PRServ_MAGIC_NUMBER );
  10.112 -
  10.113 -   servicesLangEnv->slavesReadyToResumeQ = makePrivQ();
  10.114 -   servicesLangEnv->taskReadyQ           = makePrivQ();
  10.115 -   
  10.116 -      //resume seedVP into PR's built-in services language's language env
  10.117 -   process->numEnvsWithWork = 0; //Seed is in PRServ lang env.. resume incrs this
  10.118 -   PRServ__resume_slaveVP( seedSlv, servicesLangEnv );
  10.119 -   
  10.120 -
  10.121 -      //The first process created has to unblock the core controllers.
  10.122 -   if( _PRTopEnv->numProcesses == 1 )
  10.123 -    {
  10.124 -    #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
  10.125 -      //Only difference between version with an OS thread pinned to each core and
  10.126 -      // the sequential version of PR is PR__init_Seq, this, and coreCtlr_Seq.
  10.127 -
  10.128 -            // call the one and only core ctlr (sequential version), in the main thread.
  10.129 -         coreCtlr_Seq( NULL );
  10.130 -         flushRegisters();  //Not sure why here, but leaving to be safe
  10.131 -    #else
  10.132 -         //tell the core controller threads that a process is ready to be animated
  10.133 -         //get lock, to lock out any threads still starting up -- they'll see
  10.134 -         // that firstProcessReady is true before entering while loop, and so never
  10.135 -         // wait on the condition
  10.136 -      pthread_mutex_lock(     &suspendLock );
  10.137 -      _PRTopEnv->firstProcessReady = 1;
  10.138 -      pthread_mutex_unlock(   &suspendLock );
  10.139 -      pthread_cond_broadcast( &suspendCond );
  10.140 -    #endif
  10.141 -    }
  10.142 -   pthread_mutex_init( process->doneLock, NULL );
  10.143 -   pthread_cond_init( process->doneCond, NULL );
  10.144 -   process->executionIsComplete = FALSE;
  10.145 -   
  10.146 -   return process;
  10.147 - }
  10.148 - */
  10.149 -
  10.150 -/*This is only called in multi-lang mode.
  10.151 - *It creates a seed slave, from the top-level fn and initial data passed into
  10.152 - * this fn.
  10.153 - *The only langlet in the created process is the default PRServ.  The rest
  10.154 - * must be started up via calls  made by the seed VP's top-level fn (passed in
  10.155 - * to this call).
  10.156 - * 
  10.157 - *A process is represented by a structure that holds all the process-specific
  10.158 - * information:
  10.159 - *-] The hash-array containing the language environs of any langlets started
  10.160 - *   inside the process.
  10.161 - *-] Counter of num live slaves and num live tasks in the process
  10.162 - * 
  10.163 - */
  10.164 -PRProcess *
  10.165 -PR__create_process( TopLevelFnPtr seed_Fn, void *seedData )
  10.166 - { SlaveVP    *seedSlv;
  10.167 -   PRProcess  *process;
  10.168 -   PRLangEnv **langEnvs, **langEnvsList;
  10.169 -   
  10.170 -   _PRTopEnv->mode         = MultiLang; //leftover, not used, but reminder
  10.171 -   
  10.172 -      //This runs outside of the master lock, so use PR_WL form of malloc
  10.173 -   process = PR_WL__malloc( sizeof(PRProcess) );
  10.174 -   _PRTopEnv->processes[_PRTopEnv->numProcesses] = process;
  10.175 -   _PRTopEnv->numProcesses += 1;
  10.176 -   
  10.177 -   langEnvs     = PR_WL__malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRCollElem *) );
  10.178 -   ((int32 *)langEnvs)[0]  = NUM_IN_COLLECTION;
  10.179 -   langEnvsList = PR_WL__malloc( NUM_IN_COLLECTION * sizeof(PRCollElem *) );
  10.180 -   process->langEnvs     = langEnvs;
  10.181 -   process->langEnvsList = langEnvsList;
  10.182 -   process->numLangEnvs  = 0;
  10.183 -   
  10.184 -      //A Process starts with one slave, the seed slave
  10.185 -   seedSlv = PR_int__create_slaveVP( seed_Fn, seedData, process );
  10.186 -   seedSlv->typeOfVP           = SeedSlv;
  10.187 -   seedSlv->processSlaveIsIn   = process;
  10.188 -   process->numLiveGenericSlvs = 1; //count the  seed 
  10.189 -   process->numLiveTasks       = 0;
  10.190 -   
  10.191 -   PRServLangEnv *
  10.192 -   servicesLangEnv = 
  10.193 -    PR_int__create_lang_env_in_process( sizeof(PRServLangEnv), process,
  10.194 -                                        PRServ_MAGIC_NUMBER );
  10.195 -
  10.196 -   servicesLangEnv->slavesReadyToResumeQ = makePrivQ();
  10.197 -   servicesLangEnv->taskReadyQ           = makePrivQ();
  10.198 -   
  10.199 -      //resume seedVP into PR's built-in services language's language env
  10.200 -   process->numEnvsWithWork = 0; //Seed is in PRServ lang env.. resume incrs this
  10.201 -   PRServ__resume_slaveVP( seedSlv, servicesLangEnv );
  10.202 -   
  10.203 -
  10.204 -      //The first process created has to unblock the core controllers.
  10.205 -   if( _PRTopEnv->numProcesses == 1 )
  10.206 -    {
  10.207 -    #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
  10.208 -      //Only difference between version with an OS thread pinned to each core and
  10.209 -      // the sequential version of PR is PR__init_Seq, this, and coreCtlr_Seq.
  10.210 -
  10.211 -            // call the one and only core ctlr (sequential version), in the main thread.
  10.212 -         coreCtlr_Seq( NULL );
  10.213 -         flushRegisters();  //Not sure why here, but leaving to be safe
  10.214 -    #else
  10.215 -         //tell the core controller threads that a process is ready to be animated
  10.216 -         //get lock, to lock out any threads still starting up -- they'll see
  10.217 -         // that firstProcessReady is true before entering while loop, and so never
  10.218 -         // wait on the condition
  10.219 -      pthread_mutex_lock(     &suspendLock );
  10.220 -      _PRTopEnv->firstProcessReady = 1;
  10.221 -      pthread_mutex_unlock(   &suspendLock );
  10.222 -      pthread_cond_broadcast( &suspendCond );
  10.223 -    #endif
  10.224 -    }
  10.225 -   pthread_mutex_init( &(process->doneLock), NULL );
  10.226 -   pthread_cond_init(  &(process->doneCond), NULL );
  10.227 -   process->executionIsComplete = FALSE;
  10.228 -   
  10.229 -   return process;
  10.230 - }
  10.231 -
  10.232 -
  10.233 -/*are already in Master when detect, inside end-task or dissipate, so call "PR_SS__shutdown_process"
  10.234 - */
  10.235 -void
  10.236 -PR_SS__shutdown_process( PRProcess *process )
  10.237 - { int32 i, processIdx;
  10.238 -   PRProcess **processes;
  10.239 -   
  10.240 -      //remove process from PR's list of processes..
  10.241 -   processes = _PRTopEnv->processes;
  10.242 -   //find the process within the list
  10.243 -   for( i = 0; i < _PRTopEnv->numProcesses; i++ )
  10.244 -    { if( processes[i] == process )
  10.245 -       { processIdx = i;
  10.246 -         break;
  10.247 -       }
  10.248 -    }
  10.249 -   //move all the higher processes down, overwriting the target
  10.250 -   for( i = processIdx +1; i < _PRTopEnv->numProcesses; i++ )
  10.251 -    { processes[i-1] = processes[i];
  10.252 -    }
  10.253 -   _PRTopEnv->numProcesses -= 1;
  10.254 -   
  10.255 -      //remove process from the process-to-slot chooser
  10.256 -   _PRTopEnv->currProcessIdx = 0; //start choosing starting at process 0
  10.257 -      
  10.258 -      //call shutdown on each langlet started in process (which frees any
  10.259 -      // langlet-allocd data in langEnv);
  10.260 -      //Then free the lang env
  10.261 -   PRLangEnv *protoLangEnv;
  10.262 -   for( i = 0; i < process->numLangEnvs; i++ )
  10.263 -    { protoLangEnv = PR_int__give_proto_lang_env(process->langEnvsList[i]);
  10.264 -         //The lang shutdowns should free any slaves or tasks in the langEnv
  10.265 -      (*protoLangEnv->shutdownHdlr)(&(protoLangEnv[1]));
  10.266 -      PR_int__free( protoLangEnv );
  10.267 -    }
  10.268 -   PR_int__free( process->langEnvsList ); //list array
  10.269 -   PR_int__free( &(((int32 *)process->langEnvs)[-1]) ); //the collection array
  10.270 -   
  10.271 -      //any slaves from this process still in slots will finish executing, but
  10.272 -      // have no lang env for the request handlers to use!
  10.273 -      //So, have to mark each slave, so the request handling isn't done
  10.274 -   AnimSlot *slot, **animSlots;
  10.275 -   int32 core;
  10.276 -   for( core = 0; core < NUM_CORES; core++ )
  10.277 -    { animSlots = _PRTopEnv->allAnimSlots[core];
  10.278 -      for( i = 0; i < NUM_ANIM_SLOTS; i++ )
  10.279 -       { slot =  animSlots[i];
  10.280 -         if( slot->slaveAssignedToSlot->processSlaveIsIn == process )
  10.281 -          {    //turn off req handling by disallowing slave from chging slot flag
  10.282 -            slot->slaveAssignedToSlot->animSlotAssignedTo = NULL;
  10.283 -            slot->workIsDone = FALSE; //just in case, make sure req hdling off
  10.284 -            slot->needsWorkAssigned = TRUE; //make new slave be assigned
  10.285 -          }
  10.286 -       }
  10.287 -    }
  10.288 -     
  10.289 -      //cause resume of "PR__wait_for_process_to_end()" call
  10.290 -   pthread_mutex_lock(     &(process->doneLock) );
  10.291 -   process->executionIsComplete = TRUE;
  10.292 -   pthread_mutex_unlock(   &(process->doneLock) );
  10.293 -   pthread_cond_broadcast( &(process->doneCond) );
  10.294 -      //now wait for woken waiter to Ack, then free the process struct
  10.295 -   pthread_mutex_lock(     &(process->doneAckLock)  ); //BUG:? may be a race
  10.296 -   pthread_mutex_unlock(   &(process->doneAckLock)  );  
  10.297 -   PR_int__free(process);
  10.298 -
  10.299 -      //if no more processes, cause resume of "PR__wait_for_all_activity_to_end"
  10.300 -   if( _PRTopEnv->numProcesses == 0)
  10.301 -    { 
  10.302 -      pthread_mutex_lock(     &(_PRTopEnv->activityDoneLock) );
  10.303 -      _PRTopEnv->allActivityIsDone = TRUE;
  10.304 -      pthread_mutex_unlock(   &(_PRTopEnv->activityDoneLock) );
  10.305 -      pthread_cond_broadcast( &(_PRTopEnv->activityDoneCond) );
  10.306 -    }
  10.307 - }
  10.308 -
  10.309 -/*This waits for the OS threads in the PR system to end.  Causing them to end
  10.310 - * has to be done separately (haven't worked out details as of this comment)
  10.311 - */
  10.312 -void
  10.313 -PR_SS__wait_for_PR_to_shutdown()
  10.314 - {
  10.315 -      //wait for all to complete
  10.316 -   int coreIdx;
  10.317 -   for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ )
  10.318 -    {
  10.319 -      pthread_join( coreCtlrThdHandles[coreIdx], NULL );
  10.320 -    }
  10.321 - }
  10.322 -
  10.323 -void
  10.324 -PR__wait_for_all_activity_to_end()
  10.325 - { 
  10.326 -   pthread_mutex_lock( &(_PRTopEnv->activityDoneLock) );
  10.327 -   while( !(_PRTopEnv->allActivityIsDone) )
  10.328 -    {
  10.329 -      pthread_cond_wait( &(_PRTopEnv->activityDoneCond),
  10.330 -                         &(_PRTopEnv->activityDoneLock) );
  10.331 -    }
  10.332 -   pthread_mutex_unlock( &(_PRTopEnv->activityDoneLock) );
  10.333 - }
  10.334 -
  10.335 -
  10.336 -void
  10.337 -PR__wait_for_process_to_end( PRProcess *process )
  10.338 - {    //First get the "ACK" lock, then do normal wait for signal, then release
  10.339 -      // ACK lock, to let end-process know it can free the process struct
  10.340 -   pthread_mutex_lock( &(process->doneAckLock) );   
  10.341 -   pthread_mutex_lock( &(process->doneLock) );
  10.342 -   while( process->executionIsComplete != TRUE )
  10.343 -    {
  10.344 -      pthread_cond_wait( &(process->doneCond),
  10.345 -                         &(process->doneLock) );
  10.346 -    }
  10.347 -   pthread_mutex_unlock( &(process->doneLock) );
  10.348 -      //now send "ACK" signal to process_end Fn, that it may proceed
  10.349 -   pthread_mutex_unlock( &(process->doneAckLock) ); 
  10.350 -   
  10.351 -      //TODO: BUG? -- can process be created and end, before this acquires the
  10.352 -      // first lock?  Can see some rare code that creates a bunch, before getting
  10.353 -      // to waiting..  leave for now..  pain to fix..
  10.354 - }
  10.355 -
  10.356 -/*When all work in the process has completed, then return from this call.
  10.357 - * The seedVP of the process may still exist, but it has no work, nor do any
  10.358 - * other VPs..
  10.359 - *The process must be shutdown via a separate call.  That shutdown frees the
  10.360 - * process struct and bookkeeping structs.
  10.361 - *First checks whether the process is done, if yes, calls the clean-up fn then
  10.362 - * returns the result extracted from the PRProcess struct.
  10.363 - *If process not done yet, then performs a wait (in a loop to be sure the
  10.364 - * wakeup is not spurious, which can happen).  PR registers the wait, and upon
  10.365 - * the process ending (last SlaveVP owned by it dissipates), then PR signals
  10.366 - * this to wakeup.  This then calls the cleanup fn and returns the result.
  10.367 - */
  10.368 -void *
  10.369 -PR__give_results_from_process_when_ready( PRProcess *process )
  10.370 - { void *result;
  10.371 -      //First get the "ACK" lock, then do normal wait for signal, then release
  10.372 -      // ACK lock, to let end-process know it can free the process struct
  10.373 -   pthread_mutex_lock( &(process->doneAckLock) );
  10.374 -   
  10.375 -   pthread_mutex_lock( &(process->doneLock) );
  10.376 -   while( process->executionIsComplete != TRUE )
  10.377 -    {
  10.378 -      pthread_cond_wait( &(process->doneCond),
  10.379 -                         &(process->doneLock) );
  10.380 -    }
  10.381 -   pthread_mutex_unlock( &(process->doneLock) );
  10.382 -   result = process->resultToReturn;
  10.383 -   
  10.384 -      //now send "ACK" signal to process_end Fn, that it may proceed
  10.385 -   pthread_mutex_unlock( &(process->doneAckLock) ); 
  10.386 -      
  10.387 -   return result;
  10.388 -      //TODO: BUG? -- can process be created and end, before this acquires the
  10.389 -      // first lock?  Can see some rare code that creates a bunch, before getting
  10.390 -      // to waiting..  leave for now..  pain to fix..
  10.391 - }
  10.392 -
  10.393 -
  10.394 -inline
  10.395 -void *
  10.396 -PR_SS__create_lang_env( int32 size, SlaveVP *slave, int32 magicNum )
  10.397 - {
  10.398 -   return PR_int__create_lang_env_in_process( size, slave->processSlaveIsIn, magicNum );
  10.399 - }
  10.400 -
  10.401 -
  10.402 -/*These store the pointer to handler into the language env -- language env
  10.403 - * found by using magic num to look it up in the process that the seedVP
  10.404 - * is inside of.
  10.405 - */
  10.406 -void
  10.407 -PR_SS__register_assigner( SlaveAssigner assigner, SlaveVP *seedVP, int32 magicNum )
  10.408 - { PRLangEnv *langEnv;
  10.409 - 
  10.410 -   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.411 -   langEnv->workAssigner = assigner; 
  10.412 - }
  10.413 -void
  10.414 -PR_SS__register_shutdown_handler( LangShutdownHdlr shutdownHdlr, SlaveVP *seedVP,
  10.415 -                                  int32 magicNum )
  10.416 - { PRLangEnv *langEnv;
  10.417 - 
  10.418 -   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.419 -   langEnv->shutdownHdlr = shutdownHdlr; 
  10.420 - }
  10.421 -void
  10.422 -PR_SS__register_lang_data_creator( LangDataCreator langDataCreator, 
  10.423 -                                              SlaveVP *seedVP, int32 magicNum )
  10.424 - { PRLangEnv *langEnv;
  10.425 - 
  10.426 -   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.427 -   langEnv->langDataCreator = langDataCreator; 
  10.428 - }
  10.429 -void
  10.430 -PR_SS__register_lang_meta_task_creator( LangDataCreator langMetaTaskCreator, 
  10.431 -                                              SlaveVP *seedVP, int32 magicNum )
  10.432 - { PRLangEnv *langEnv;
  10.433 - 
  10.434 -   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.435 -   langEnv->langMetaTaskCreator = langMetaTaskCreator; 
  10.436 - }
  10.437 -void
  10.438 -PR_SS__register_make_slave_ready_fn( MakeSlaveReadyFn fn, SlaveVP *seedVP,
  10.439 -                                                         int32 magicNum )
  10.440 - { PRLangEnv *langEnv;
  10.441 - 
  10.442 -   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.443 -   langEnv->makeSlaveReadyFn = fn; 
  10.444 - }
  10.445 -void
  10.446 -PR_SS__register_make_task_ready_fn( MakeTaskReadyFn fn, SlaveVP *seedVP,
  10.447 -                                                         int32 magicNum )
  10.448 - { PRLangEnv *langEnv;
  10.449 - 
  10.450 -   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.451 -   langEnv->makeTaskReadyFn = fn; 
  10.452 - }
  10.453 -
  10.454 -/*
  10.455 -void
  10.456 -PR_SS__register_create_task_handler( RequestHandler createTaskHandler, SlaveVP *seedVP, int32 magicNum )
  10.457 - { PRLangEnv *langEnv;
  10.458 - 
  10.459 -   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.460 -   langEnv->createTaskHdlr = createTaskHandler; 
  10.461 - }
  10.462 -void
  10.463 -PR_SS__register_end_task_handler( RequestHandler endTaskHandler, SlaveVP *seedVP, int32 magicNum )
  10.464 - { PRLangEnv *langEnv;
  10.465 - 
  10.466 -   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.467 -   langEnv->endTaskHdlr = endTaskHandler; 
  10.468 - }
  10.469 -void
  10.470 -PR_SS__register_create_slave_handler( RequestHandler createSlvHandler, SlaveVP *seedVP, int32 magicNum )
  10.471 - { PRLangEnv *langEnv;
  10.472 - 
  10.473 -   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.474 -   langEnv->createSlaveHdlr = createSlvHandler; 
  10.475 - }
  10.476 -void
  10.477 -PR_SS__register_dissipate_slave_handler( RequestHandler dissipateHandler, SlaveVP *seedVP, int32 magicNum )
  10.478 - { PRLangEnv *langEnv;
  10.479 - 
  10.480 -   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.481 -   langEnv->dissipateSlaveHdlr = dissipateHandler; 
  10.482 - }
  10.483 -void
  10.484 -PR_SS__register_request_handler( RequestHandler reqHandler, SlaveVP *seedVP, int32 magicNum )
  10.485 - { PRLangEnv *langEnv;
  10.486 - 
  10.487 -   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.488 -   langEnv->requestHdlr = reqHandler; 
  10.489 - }
  10.490 - */
  10.491 -/*
  10.492 -void
  10.493 -PR_SS__register_lang_data_initializer( LangDataInitializer langDataInitializer, 
  10.494 -                                              SlaveVP *seedVP, int32 magicNum )
  10.495 - { PRLangEnv *langEnv;
  10.496 - 
  10.497 -   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.498 -   langEnv->langDataInitializer = langDataInitializer; 
  10.499 - }
  10.500 -void
  10.501 -PR_SS__register_lang_data_freer( LangDataFreer langDataFreer, 
  10.502 -                                              SlaveVP *seedVP, int32 magicNum )
  10.503 - { PRLangEnv *langEnv;
  10.504 - 
  10.505 -   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.506 -   langEnv->langDataFreer = langDataFreer; 
  10.507 - }
  10.508 -*/
  10.509 -
  10.510 -
  10.511 -
  10.512 -
  10.513 -/*
  10.514 - *This function returns information about the version of PR, the language
  10.515 - * the program is being run in, its version, and information on the 
  10.516 - * hardware.
  10.517 - */
  10.518 -char *
  10.519 -PRServ___give_environment_string()
  10.520 - { char *buffer = PR_WL__malloc(10000);
  10.521 -   int32 j;
  10.522 -   
  10.523 -   j = sizeof(int32);  //put total num chars here when done
  10.524 -   //--------------------------
  10.525 -   j += sprintf(buffer+j, "#\n# >> Build information <<\n");
  10.526 -   j += sprintf(buffer+j, "# GCC VERSION: %d.%d.%d\n",__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__);
  10.527 -   j += sprintf(buffer+j, "# Build Date: %s %s\n", __DATE__, __TIME__);
  10.528 -    
  10.529 -   j += sprintf(buffer+j, "#\n# >> Hardware information <<\n");
  10.530 -   j += sprintf(buffer+j, "# Hardware Architecture: ");
  10.531 -   #ifdef __x86_64
  10.532 -   j += sprintf(buffer+j, "x86_64");
  10.533 -   #endif //__x86_64
  10.534 -   #ifdef __i386
  10.535 -   j += sprintf(buffer+j, "x86");
  10.536 -   #endif //__i386
  10.537 -   j += sprintf(buffer+j, "\n");
  10.538 -   j += sprintf(buffer+j, "# Number of Cores: %d\n", NUM_CORES);
  10.539 -   //--------------------------
  10.540 -    
  10.541 -   //PR Plugins
  10.542 -   j += sprintf(buffer+j, "#\n# >> PR Plugins <<\n");
  10.543 -   j += sprintf(buffer+j, "# Language : ");
  10.544 -   j += sprintf(buffer+j, _LANG_NAME_);
  10.545 -   j += sprintf(buffer+j, "\n");
  10.546 -       //Meta info gets set by calls from the language during its init,
  10.547 -       // and info registered by calls from inside the application
  10.548 -   j += sprintf(buffer+j, "# Assigner: %s\n", _PRTopEnv->metaInfo->assignerInfo);
  10.549 -
  10.550 -   //--------------------------
  10.551 -   //Application
  10.552 -   j += sprintf(buffer+j, "#\n# >> Application <<\n");
  10.553 -   j += sprintf(buffer+j, "# Name: %s\n", _PRTopEnv->metaInfo->appInfo);
  10.554 -   j += sprintf(buffer+j, "# Data Set:\n%s\n",_PRTopEnv->metaInfo->inputInfo);
  10.555 -    
  10.556 -   ((int32 *)buffer)[0] = j - sizeof(int32); //insert the number of chars
  10.557 -   //--------------------------
  10.558 -   return (char *) &(((int32 *)buffer)[1]); //return pointer to first char
  10.559 - }
  10.560 -
  10.561 -void
  10.562 -PR__set_app_info( char *info )
  10.563 - { int32 len;
  10.564 -   char *copy;
  10.565 -   len = strlen(info) +1;
  10.566 -   copy = PR_int__malloc(len);
  10.567 -   strcpy(copy, info);
  10.568 -   _PRTopEnv->metaInfo->appInfo = copy;
  10.569 - }
  10.570 -void
  10.571 -PR__set_input_info( char *info )
  10.572 - { int32 len;
  10.573 -   char *copy;
  10.574 -   len = strlen(info) +1;
  10.575 -   copy = PR_int__malloc(len);
  10.576 -   strcpy(copy, info);
  10.577 -   _PRTopEnv->metaInfo->inputInfo = copy;
  10.578 - }
  10.579 -
  10.580 -
  10.581 -
  10.582 -
  10.583 -
  10.584 -
  10.585 -void
  10.586 -create_topEnv()
  10.587 +PR_SS__create_topEnv()
  10.588   { TopEnv       *masterEnv;
  10.589     PRQueueStruc   **readyToAnimateQs;
  10.590     int32            coreIdx;
  10.591 @@ -640,16 +69,18 @@
  10.592     allAnimSlots            = PR_int__malloc( NUM_CORES * sizeof(AnimSlot *) );
  10.593     _PRTopEnv->allAnimSlots = allAnimSlots;
  10.594  
  10.595 -   //Make the master VPs
  10.596 +   //Make the animation slots and similar per-core structs..
  10.597     for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
  10.598      {    
  10.599 -      readyToAnimateQs[ coreIdx ] = makePRQ();
  10.600 +      //readyToAnimateQs[ coreIdx ] = makePRQ();
  10.601        
  10.602 -         //Q: should give masterVP core-specific info as its init data?
  10.603 +/*         //Q: should give masterVP core-specific info as its init data?
  10.604 +   Don't have masterVPs anymore -- the pinned pthread takes that role
  10.605        masterVPs[ coreIdx ] = PR_int__create_slaveVP_helper( (TopLevelFnPtr)&animationMaster, (void*)_PRTopEnv );
  10.606        masterVPs[ coreIdx ]->coreAnimatedBy = coreIdx;
  10.607        masterVPs[ coreIdx ]->typeOfVP = Master;
  10.608 -      allAnimSlots[ coreIdx ] = create_anim_slots( coreIdx ); //makes for one core
  10.609 + */
  10.610 +      allAnimSlots[ coreIdx ] = PR_SS__create_anim_slots( coreIdx ); //makes for one core
  10.611      }
  10.612      
  10.613        //For each animation slot, there is an idle slave, and an initial
  10.614 @@ -659,10 +90,11 @@
  10.615     
  10.616     for( coreNum = 0;  coreNum < NUM_CORES; coreNum++ )
  10.617      { //langEnv->coreIsDone[coreNum] = FALSE; //use during shutdown
  10.618 -    
  10.619 +         //Still have multiple slots -- left over from prev incarnation
  10.620        for( slotNum = 0; slotNum < NUM_ANIM_SLOTS; ++slotNum )
  10.621         { idleSlv = PR_int__create_slaveVP_helper( &idle_fn, NULL );
  10.622           idleSlv->coreAnimatedBy                = coreNum;
  10.623 +         idleSlv->typeOfVP                      = IdleVP;
  10.624           idleSlv->animSlotAssignedTo            =
  10.625                                 _PRTopEnv->allAnimSlots[coreNum][slotNum];
  10.626           _PRTopEnv->idleSlv[coreNum][slotNum] = idleSlv;
  10.627 @@ -688,6 +120,7 @@
  10.628     
  10.629     _PRTopEnv->numSlavesCreated = 0;  //used by create slave to set slave ID
  10.630    
  10.631 +      //TODO: remove this, and the vars from TopEnv
  10.632     //=================== single lang only vars ==================
  10.633     //
  10.634     //
  10.635 @@ -704,6 +137,7 @@
  10.636     //
  10.637     readyToAnimateQs = PR_int__malloc( NUM_CORES * sizeof(PRQueueStruc *) );
  10.638     
  10.639 +      //BUG: have a fixed max num processes, but never check whether exceeded
  10.640     _PRTopEnv->processes    = PR_int__malloc( NUM_IN_COLLECTION * sizeof(PRProcess *) );
  10.641     _PRTopEnv->numProcesses = 0;
  10.642     _PRTopEnv->currProcessIdx = 0;
  10.643 @@ -731,7 +165,7 @@
  10.644   }
  10.645  
  10.646  AnimSlot **
  10.647 -create_anim_slots( int32 coreSlotsAreOn )
  10.648 +PR_SS__create_anim_slots( int32 coreSlotsAreOn )
  10.649   { AnimSlot  **animSlots;
  10.650     int i;
  10.651  
  10.652 @@ -751,7 +185,7 @@
  10.653   }
  10.654  
  10.655  void
  10.656 -freeAnimSlots( AnimSlot **animSlots )
  10.657 +PR_SS__freeAnimSlots( AnimSlot **animSlots )
  10.658   { int i;
  10.659     for( i = 0; i < NUM_ANIM_SLOTS; i++ )
  10.660      {
  10.661 @@ -769,7 +203,7 @@
  10.662   * all the core controller threads when the first process is created.
  10.663   */
  10.664  void
  10.665 -create_the_coreCtlr_OS_threads()
  10.666 +PR_SS__create_the_coreCtlr_OS_threads()
  10.667   {
  10.668     //========================================================================
  10.669     //                      Create the Threads
  10.670 @@ -800,34 +234,149 @@
  10.671   }
  10.672  
  10.673  
  10.674 -//==========================  SHUT DOWN  ===========================
  10.675 +//======================
  10.676 +//===
  10.677 +//=
  10.678 +//inline
  10.679 +void *
  10.680 +PR_SS__create_lang_env( int32 size, SlaveVP *slave, int32 magicNum )
  10.681 + {
  10.682 +   return PR_int__create_lang_env_in_process( size, slave->processSlaveIsIn, magicNum );
  10.683 + }
  10.684  
  10.685 -/*This is called from the main thread, and causes PR's OS threads to stop
  10.686 - * then cleans up any memory allocated by PR from the OS.
  10.687 - * 
  10.688 - *The main thread has a separate call it can use to wait for all work to
  10.689 - * finish, so when this is called, it just shuts down, whether there's
  10.690 - * unfinished work or not.
  10.691 - * 
  10.692 - *However, cores that are performing work won't see this shutdown until
  10.693 - * they finish their current work-unit.
  10.694 +
  10.695 +/*These store the pointer to handler into the language env -- language env
  10.696 + * found by using magic num to look it up in the process that the seedVP
  10.697 + * is inside of.
  10.698   */
  10.699 -PR__shutdown()
  10.700 - { int32 coreIdx;
  10.701 +void
  10.702 +PR_SS__register_assigner( SlaveAssigner assigner, SlaveVP *seedVP, int32 magicNum )
  10.703 + { PRLangEnv *langEnv;
  10.704 + 
  10.705 +   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.706 +   langEnv->workAssigner = assigner; 
  10.707 + }
  10.708 +void
  10.709 +PR_SS__register_lang_shutdown_handler( LangShutdownHdlr shutdownHdlr, SlaveVP *seedVP,
  10.710 +                                  int32 magicNum )
  10.711 + { PRLangEnv *langEnv;
  10.712 + 
  10.713 +   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.714 +   langEnv->shutdownHdlr = shutdownHdlr; 
  10.715 + }
  10.716 +void
  10.717 +PR_SS__register_lang_data_creator( LangDataCreator langDataCreator, 
  10.718 +                                              SlaveVP *seedVP, int32 magicNum )
  10.719 + { PRLangEnv *langEnv;
  10.720 + 
  10.721 +   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.722 +   langEnv->langDataCreator = langDataCreator; 
  10.723 + }
  10.724 +void
  10.725 +PR_SS__register_lang_meta_task_creator( LangMetaTaskCreator langMetaTaskCreator, 
  10.726 +                                              SlaveVP *seedVP, int32 magicNum )
  10.727 + { PRLangEnv *protoLangEnv;
  10.728 + 
  10.729 +   protoLangEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.730 +   protoLangEnv->langMetaTaskCreator = langMetaTaskCreator; 
  10.731 + }
  10.732 +void
  10.733 +PR_SS__register_make_slave_ready_fn( MakeSlaveReadyFn fn, SlaveVP *seedVP,
  10.734 +                                                         int32 magicNum )
  10.735 + { PRLangEnv *langEnv;
  10.736 + 
  10.737 +   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.738 +   langEnv->makeSlaveReadyFn = fn; 
  10.739 + }
  10.740 +void
  10.741 +PR_SS__register_make_task_ready_fn( MakeTaskReadyFn fn, SlaveVP *seedVP,
  10.742 +                                                         int32 magicNum )
  10.743 + { PRLangEnv *langEnv;
  10.744 + 
  10.745 +   langEnv = PR_SS__give_proto_lang_env_for_slave( seedVP, magicNum );
  10.746 +   langEnv->makeTaskReadyFn = fn; 
  10.747 + }
  10.748 +
  10.749 +//========
  10.750 +
  10.751 +
  10.752 +/*are in Master when call this..  due to detecting end-of-work, from inside 
  10.753 + * end-task or dissipate..  or, call this when app calls "end process"
  10.754 + */
  10.755 +void
  10.756 +PR_SS__end_process_normally( PRProcess *process )
  10.757 + { int32 i, processIdx;
  10.758 +   PRProcess **processes;
  10.759     
  10.760 -   PR_SS__shutdown_OS_threads();
  10.761 +      //remove process from PR's list of processes..
  10.762 +   processes = _PRTopEnv->processes;
  10.763 +   //find the process within the list
  10.764 +   for( i = 0; i < _PRTopEnv->numProcesses; i++ )
  10.765 +    { if( processes[i] == process )
  10.766 +       { processIdx = i;
  10.767 +         break;
  10.768 +       }
  10.769 +    }
  10.770 +   //move all the higher processes down, overwriting the target
  10.771 +   for( i = processIdx +1; i < _PRTopEnv->numProcesses; i++ )
  10.772 +    { processes[i-1] = processes[i];
  10.773 +    }
  10.774 +   _PRTopEnv->numProcesses -= 1;
  10.775     
  10.776 -      //wait for the OS threads to exit
  10.777 -   for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ )
  10.778 +      //remove process from the process-to-slot chooser
  10.779 +   _PRTopEnv->currProcessIdx = 0; //start choosing starting at process 0
  10.780 +      
  10.781 +      //call shutdown on each langlet started in process (which frees any
  10.782 +      // langlet-allocd data in langEnv);
  10.783 +      //Then free the lang env
  10.784 +   PRLangEnv *protoLangEnv;
  10.785 +   for( i = 0; i < process->numLangEnvs; i++ )
  10.786 +    { protoLangEnv = PR_int__give_proto_lang_env(process->protoLangEnvsList[i]);
  10.787 +         //The lang shutdowns should free any slaves or tasks in the langEnv
  10.788 +      (*protoLangEnv->shutdownHdlr)(&(protoLangEnv[1]));
  10.789 +      PR_int__free( protoLangEnv );
  10.790 +    }
  10.791 +   PR_int__free( process->protoLangEnvsList ); //list array
  10.792 +   PR_int__free( &(((int32 *)process->langEnvs)[-1]) ); //the collection array
  10.793 +   
  10.794 +      //any slaves from this process still in slots will finish executing, but
  10.795 +      // have no lang env for the request handlers to use!
  10.796 +      //So, have to mark each slave, so the request handling isn't done
  10.797 +   AnimSlot *slot, **animSlots;
  10.798 +   int32 core;
  10.799 +   for( core = 0; core < NUM_CORES; core++ )
  10.800 +    { animSlots = _PRTopEnv->allAnimSlots[core];
  10.801 +      for( i = 0; i < NUM_ANIM_SLOTS; i++ )
  10.802 +       { slot =  animSlots[i];
  10.803 +         if( slot->slaveAssignedToSlot->processSlaveIsIn == process )
  10.804 +          {    //turn off req handling by disallowing slave from chging slot flag
  10.805 +            slot->slaveAssignedToSlot->animSlotAssignedTo = NULL;
  10.806 +            slot->workIsDone = FALSE; //just in case, make sure req hdling off
  10.807 +            slot->needsWorkAssigned = TRUE; //make new slave be assigned
  10.808 +          }
  10.809 +       }
  10.810 +    }
  10.811 +     
  10.812 +      //cause resume of "PR__wait_for_process_to_end()" call
  10.813 +   if( process->hasWaitingToEnd )
  10.814      {
  10.815 -      pthread_join( coreCtlrThdHandles[coreIdx], NULL );
  10.816 +      pthread_mutex_lock(     &(process->doneLock) );
  10.817 +      process->executionIsComplete = TRUE;
  10.818 +      pthread_mutex_unlock(   &(process->doneLock) );
  10.819 +       pthread_cond_broadcast( &(process->doneCond) );
  10.820 +          //now wait for woken waiter to Ack, then free the process struct
  10.821 +       pthread_mutex_lock(     &(process->doneAckLock)  ); //BUG:? may be a race
  10.822 +       pthread_mutex_unlock(   &(process->doneAckLock)  );  
  10.823 +       PR_int__free(process);
  10.824 +   }
  10.825 +      //if no more processes, cause resume of "PR__wait_for_all_activity_to_end"
  10.826 +   if( _PRTopEnv->numProcesses == 0)
  10.827 +    { 
  10.828 +      pthread_mutex_lock(     &(_PRTopEnv->activityDoneLock) );
  10.829 +      _PRTopEnv->allActivityIsDone = TRUE;
  10.830 +      pthread_mutex_unlock(   &(_PRTopEnv->activityDoneLock) );
  10.831 +      pthread_cond_broadcast( &(_PRTopEnv->activityDoneCond) );
  10.832      }
  10.833 -
  10.834 -      //Before getting rid of everything, print out any measurements made
  10.835 -   PR_SS__print_out_measurements();
  10.836 -
  10.837 -      //free all memory allocated from the OS
  10.838 -   PR_SS__cleanup_at_end_of_shutdown();
  10.839   }
  10.840  
  10.841  
  10.842 @@ -868,12 +417,26 @@
  10.843     SlaveVP* shutdownVP;
  10.844     
  10.845     shutdownVP = PR_int__create_slaveVP_helper( &endOSThreadFn, NULL );
  10.846 -   shutdownVP->typeOfVP = Shutdown;
  10.847 +   shutdownVP->typeOfVP = ShutdownVP;
  10.848      
  10.849     return shutdownVP;
  10.850   }
  10.851  
  10.852  
  10.853 +/*This is run in the main thread, as part of the PR__shutdown() call
  10.854 + * It frees any memory allocated from the OS
  10.855 + */
  10.856 +void
  10.857 +PR_SS__cleanup_at_end_of_shutdown()
  10.858 + { 
  10.859 +      //All the environment data has been allocated with PR__malloc, so just
  10.860 +      // free the memory obtained by PR__malloc, then free the top env.
  10.861 +      //These are the only two that use system free 
  10.862 +   PR_ext__free_free_list( _PRTopEnv->freeLists );
  10.863 +   free( (void *)_PRTopEnv );
  10.864 + }
  10.865 +
  10.866 +
  10.867  
  10.868  void
  10.869  PR_SS__print_out_measurements()
  10.870 @@ -891,20 +454,23 @@
  10.871     MEAS__Print_Hists_for_Plugin_Meas;
  10.872   }
  10.873  
  10.874 -/*This is run in the main thread, as part of the PR__shutdown() call
  10.875 - * It frees any memory allocated from the OS
  10.876 +/*This waits for the OS threads in the PR system to end.  Causing them to end
  10.877 + * has to be done separately (haven't worked out details as of this comment)
  10.878   */
  10.879  void
  10.880 -PR_SS__cleanup_at_end_of_shutdown()
  10.881 - { 
  10.882 -      //All the environment data has been allocated with PR__malloc, so just
  10.883 -      // free the memory obtained by PR__malloc, then free the top env.
  10.884 -      //These are the only two that use system free 
  10.885 -   PR_ext__free_free_list( _PRTopEnv->freeLists );
  10.886 -   free( (void *)_PRTopEnv );
  10.887 +PR_SS__wait_for_PR_to_shutdown()
  10.888 + {
  10.889 +      //wait for all to complete
  10.890 +   int coreIdx;
  10.891 +   for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ )
  10.892 +    {
  10.893 +      pthread_join( coreCtlrThdHandles[coreIdx], NULL );
  10.894 +    }
  10.895   }
  10.896  
  10.897  
  10.898 +//============================
  10.899 +
  10.900  /*Am trying to be cute, avoiding IF statement in coreCtlr that checks for
  10.901   * a special shutdown slaveVP.  Ended up with extra-complex shutdown sequence.
  10.902   *This function has the sole purpose of setting the stack and framePtr
    11.1 --- a/PR__WL.c	Tue Feb 05 20:23:27 2013 -0800
    11.2 +++ b/PR__WL.c	Sat Mar 02 09:43:45 2013 -0800
    11.3 @@ -24,8 +24,10 @@
    11.4  
    11.5  
    11.6  
    11.7 -
    11.8 -inline 
    11.9 +/*As of Feb 2013, doesn't use magic number -- only one ID shared across all
   11.10 + * langlets
   11.11 + */
   11.12 +inline
   11.13  int32 *
   11.14  PR__give_ID_from_slave( SlaveVP *animSlv, int32 magicNumber )
   11.15   {
   11.16 @@ -34,9 +36,9 @@
   11.17  
   11.18  inline
   11.19  int32 *
   11.20 -PR__give_ID_from_task( void *_task )
   11.21 - { PRMetaTask task;
   11.22 -   task = ((PRMetaTask *)_task)[-1];
   11.23 +PR__give_ID_from_lang_meta_task( void *_task )
   11.24 + { PRMetaTask *task;
   11.25 +   task = PR_int__give_prolog_of_lang_meta_task(_task);
   11.26     return task->ID;
   11.27   }
   11.28  
   11.29 @@ -99,8 +101,8 @@
   11.30   * pears -- making that suspend the last thing in the Slv's trace.
   11.31   */
   11.32  void
   11.33 -PR_WL__send_end_slave_req( RequestHandler handler, SlaveVP *slaveToDissipate,
   11.34 -                                                                int32 magicNum )
   11.35 +PR_WL__send_end_slave_req( void *langReq, RequestHandler handler,
   11.36 +                           SlaveVP *slaveToDissipate, int32 magicNum )
   11.37   { PRReqst req;
   11.38  
   11.39     req.reqType                = SlvDissipate;
   11.40 @@ -136,11 +138,11 @@
   11.41                                                SlaveVP *animSlv, int32 magicNum )
   11.42   { PRReqst req;
   11.43   
   11.44 -   req.reqType    = TaskEnd;
   11.45 -   req.langReq     = langReq;
   11.46 -   req.handler    = handler;
   11.47 +   req.reqType         = TaskEnd;
   11.48 +   req.langReq         = langReq;
   11.49 +   req.handler         = handler;
   11.50     req.langMagicNumber = magicNum;
   11.51 -   animSlv->request = &req;
   11.52 +   animSlv->request    = &req;
   11.53     
   11.54     PR_WL__suspend_slaveVP_and_send_req( animSlv );
   11.55   }
   11.56 @@ -160,7 +162,7 @@
   11.57  PR_WL__add_lang_request_in_mallocd_PRReqst( void *langReqData,
   11.58                                            SlaveVP *callingSlv )
   11.59   { PRReqst *req;
   11.60 -//WARNING: not update.. may be buggy
   11.61 +//WARNING: not updated.. may be buggy
   11.62     req = PR_int__malloc( sizeof(PRReqst) );
   11.63     req->reqType         = Language;
   11.64     req->langReq          = langReqData;
   11.65 @@ -168,7 +170,8 @@
   11.66     callingSlv->request  = req;
   11.67   }
   11.68  
   11.69 -inline int32 *
   11.70 +inline 
   11.71 +int32 *
   11.72  PR_WL__create_taskID_of_size( int32 numInts )
   11.73   { int32 *taskID;
   11.74     
   11.75 @@ -182,7 +185,8 @@
   11.76   * to plugin
   11.77   *Then it does suspend, to cause request to be sent.
   11.78   */
   11.79 -inline void
   11.80 +inline 
   11.81 +void
   11.82  PR_WL__send_lang_request( void *langReqData, RequestHandler handler, 
   11.83                                             SlaveVP *callingSlv, int32 magicNum )
   11.84   { PRReqst req;
   11.85 @@ -197,6 +201,19 @@
   11.86     PR_WL__suspend_slaveVP_and_send_req( callingSlv );
   11.87   }
   11.88  
   11.89 +inline 
   11.90 +void
   11.91 +PR_WL__send_lang_shutdown_request( SlaveVP *callingSlv, int32 magicNum )
   11.92 + { PRReqst req;
   11.93 +
   11.94 +   req.reqType         = LangShutdown;
   11.95 +   req.langMagicNumber = magicNum;
   11.96 +   req.nextReqst       = NULL;
   11.97 +   callingSlv->request = &req;
   11.98 +   
   11.99 +   PR_WL__suspend_slaveVP_and_send_req( callingSlv );
  11.100 + }
  11.101 +
  11.102  
  11.103  /*This sends a PRLang request -- for probe, exception, and so on..
  11.104   * 
  11.105 @@ -221,7 +238,7 @@
  11.106  void
  11.107  PR_WL__throw_exception( char *msgStr, SlaveVP *reqstSlv,  PRExcp *excpData )
  11.108   { PRReqst req;
  11.109 -   PRServReq langReq;
  11.110 +   PRServiceReq langReq;
  11.111  
  11.112     req.reqType         = Language;
  11.113     req.langReq          = &langReq;
    12.1 --- a/PR__WL.h	Tue Feb 05 20:23:27 2013 -0800
    12.2 +++ b/PR__WL.h	Sat Mar 02 09:43:45 2013 -0800
    12.3 @@ -34,33 +34,64 @@
    12.4   * aren't meant for use in wrapper libraries, because they are themselves
    12.5   * wrapper-library calls!
    12.6   */
    12.7 -//========== Startup and shutdown ==========
    12.8 +
    12.9 +//============== Top level Fns called from main   ===============
   12.10  void
   12.11  PR__start();
   12.12  
   12.13 -SlaveVP* 
   12.14 -PR_SS__create_shutdown_slave();
   12.15 +PRProcess *
   12.16 +PR__create_process( TopLevelFnPtr seed_Fn, void *seedData );
   12.17  
   12.18  void
   12.19 -PR_SS__shutdown();
   12.20 +PR__end_seedVP( SlaveVP *seedSlv );
   12.21  
   12.22  void
   12.23 -PR_SS__cleanup_at_end_of_shutdown();
   12.24 +PR__end_process_from_inside( SlaveVP *seedSlv );
   12.25 +
   12.26 +void *
   12.27 +PR__give_results_from_process_when_ready( PRProcess *process );
   12.28  
   12.29  void
   12.30 -PR_SS__register_langlets_langEnv( PRLangEnv *langEnv, SlaveVP  *seedVP, int32 VSs_MAGIC_NUMBER );
   12.31 +PR__wait_for_process_to_end( PRProcess *process );
   12.32 +fixme; //process->hasWaitingToEnd
   12.33 +
   12.34 +void
   12.35 +PR__wait_for_all_activity_to_end();
   12.36 +
   12.37 +void
   12.38 +PR__shutdown();
   12.39 +
   12.40 +#define \
   12.41 +PR__create_taskID_of_size   PR_WL__create_taskID_of_size
   12.42 +
   12.43 +inline
   12.44 +int32 *
   12.45 +PR__give_ID_from_slave( SlaveVP *animSlv, int32 magicNumber );
   12.46 +
   12.47 +inline
   12.48 +int32 *
   12.49 +PR__give_ID_from_lang_meta_task( void *_task );
   12.50 +
   12.51 +#define \
   12.52 +PR__malloc  PR_WL__malloc
   12.53 +
   12.54 +#define \
   12.55 +PR__free    PR_WL__free
   12.56 +
   12.57 +
   12.58  
   12.59  //============== include internally used fn prototypes ================
   12.60  #include "PR__int.h"
   12.61  
   12.62 -//==============    ===============
   12.63  
   12.64 -inline
   12.65 -SlaveVP *
   12.66 -PR_PI__give_slave_lang_meta_task_is_assigned_to( void *langMetaTask );
   12.67 +#define \
   12.68 +PR_WL__create_slaveVP   PR_int__create_slaveVP_helper
   12.69  
   12.70 +#define \
   12.71 +PR_WL__give_lang_meta_task_from_slave   PR_int__give_lang_meta_task_from_slave
   12.72  
   12.73 -#define PR_WL__create_slaveVP PR_int__create_slaveVP_helper
   12.74 +#define \
   12.75 +PR_WL__give_prolog_of_lang_meta_task   PR_int__give_prolog_of_lang_meta_task
   12.76  
   12.77  //==============  Request Related  ===============
   12.78  
   12.79 @@ -86,13 +117,12 @@
   12.80  inline void
   12.81  PR_WL__send_service_request( void *langReqData, SlaveVP *callingSlv );
   12.82  
   12.83 -PRReqst *
   12.84 -PR_PI__take_next_request_out_of( SlaveVP *slaveWithReq );
   12.85 -//#define PR_PI__take_next_request_out_of( slave ) slave->requests
   12.86 +inline void
   12.87 +PR_WL__send_lang_shutdown_request( SlaveVP *callingSlv, int32 magicNum );
   12.88  
   12.89 -//inline void *
   12.90 -//PR_PI__take_lang_reqst_from( PRReqst *req );
   12.91 -#define PR_PI__take_lang_reqst_from( req ) req->langReqData
   12.92 +inline 
   12.93 +int32 *
   12.94 +PR_WL__create_taskID_of_size( int32 numInts );
   12.95  
   12.96  //======================== MEASUREMENT ======================
   12.97  uint64
   12.98 @@ -106,15 +136,7 @@
   12.99  PR_WL__throw_exception( char *msgStr, SlaveVP *reqstSlv,  PRExcp *excpData );
  12.100  #define PR_App__throw_exception PR_WL__throw_exception
  12.101  
  12.102 -#define implement_me printf("Unimpl Fn: \n%s \n%s : %s\n", __FILE__, __FUNCTION__, __LINE__)
  12.103 -//#define fix_me printf("Fix me at: \n%s \n%s : %s\n", __FILE__, __FUNCTION__, __LINE__)
  12.104  
  12.105 -//=========================  PR request handlers  ========================
  12.106 -void inline
  12.107 -handleMakeProbe( PRServReq *langReq, void *langEnv );
  12.108 -
  12.109 -void inline
  12.110 -handleThrowException( PRServReq *langReq, void *langEnv );
  12.111  //=======================================================================
  12.112  
  12.113  //========================= Services =======================
    13.1 --- a/PR__int.c	Tue Feb 05 20:23:27 2013 -0800
    13.2 +++ b/PR__int.c	Sat Mar 02 09:43:45 2013 -0800
    13.3 @@ -73,17 +73,15 @@
    13.4   
    13.5     newSlv = PR_int__create_slaveVP_helper( fnPtr, dataParam );
    13.6        
    13.7 -   int32 *
    13.8 -   langDatas    = PR_int__malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRLangData *) );
    13.9 -   langDatas[0] = NUM_IN_COLLECTION;    //size held in prolog
   13.10 -   newSlv->langDatas = &(langDatas[1]); //skip over the size
   13.11 +   newSlv->langDatas = 
   13.12 +      (PRLangData **)PR_int__make_collection_of_size( NUM_IN_COLLECTION );
   13.13             
   13.14 -   int32 *
   13.15 -   metaTasks    = PR_int__malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRMetaTask *) );
   13.16 -   metaTasks[0] = NUM_IN_COLLECTION;    //size held in prolog
   13.17 -   newSlv->metaTasks = &(metaTasks[1]);
   13.18 +   newSlv->metaTasks = 
   13.19 +      (PRMetaTask **) PR_int__make_collection_of_size( NUM_IN_COLLECTION );
   13.20     
   13.21     process->numLiveGenericSlvs += 1;
   13.22 +   
   13.23 +   return newSlv;
   13.24   }
   13.25  
   13.26  
   13.27 @@ -98,16 +96,13 @@
   13.28     retSlv = PR_int__create_slaveVP_helper( &idle_fn, NULL );
   13.29     retSlv->typeOfVP     = SlotTaskSlv; 
   13.30     
   13.31 -   int32 *
   13.32 -   langDatas    = PR_int__malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRLangData *) );
   13.33 -   langDatas[0] = NUM_IN_COLLECTION;    //size held in prolog
   13.34 -   retSlv->langDatas = &(langDatas[1]); //skip over the size
   13.35 +      
   13.36 +   retSlv->langDatas = 
   13.37 +      (PRLangData **) PR_int__make_collection_of_size( NUM_IN_COLLECTION );
   13.38             
   13.39 -   int32 *
   13.40 -   metaTasks    = PR_int__malloc( sizeof(int32) + NUM_IN_COLLECTION * sizeof(PRMetaTask *) );
   13.41 -   metaTasks[0] = NUM_IN_COLLECTION;    //size held in prolog
   13.42 -   retSlv->metaTasks = &(metaTasks[1]);
   13.43 -   
   13.44 +   retSlv->metaTasks = 
   13.45 +      (PRMetaTask **) PR_int__make_collection_of_size( NUM_IN_COLLECTION );
   13.46 +     
   13.47     return retSlv;
   13.48   }
   13.49  
   13.50 @@ -145,29 +140,34 @@
   13.51   * either a recycled free task slave that finished it's task and has been
   13.52   * idle in the recycle queue, or else create a new slave to be the slot slave.
   13.53   *The master only calls this with a slot slave that needs to be replaced.
   13.54 + * 
   13.55 + *The master continues after this call, handing the converted Free task slave
   13.56 + * to a request handler,  which places the converted slave into the langlet's
   13.57 + * env, so it will eventually resume
   13.58   */
   13.59 -inline void
   13.60 -PR_int__replace_with_new_slot_slv( SlaveVP *requestingSlv, PRProcess *process )
   13.61 +inline 
   13.62 +void
   13.63 +PR_int__replace_with_new_slot_slv( SlaveVP *oldSlotSlv )
   13.64   { SlaveVP *newSlotSlv;
   13.65 -
   13.66 +   
   13.67        //get a new slave to be the slot slave
   13.68 -   newSlotSlv  = PR_int__get_recycled_slot_slave( process );
   13.69 +   newSlotSlv  = PR_int__get_recycled_slot_slave();
   13.70     
   13.71        //a slot slave is pinned to a particular slot on a particular core
   13.72        //Note, this happens before the request is seen by handler, so nothing
   13.73        // has had a chance to change the coreAnimatedBy or anything else..
   13.74 -   newSlotSlv->animSlotAssignedTo = requestingSlv->animSlotAssignedTo;
   13.75 -   newSlotSlv->coreAnimatedBy     = requestingSlv->coreAnimatedBy;
   13.76 +   newSlotSlv->animSlotAssignedTo = oldSlotSlv->animSlotAssignedTo;
   13.77 +   newSlotSlv->coreAnimatedBy     = oldSlotSlv->coreAnimatedBy;
   13.78      
   13.79        //put it into the slot slave matrix
   13.80 -   int32 slotNum = requestingSlv->animSlotAssignedTo->slotIdx;
   13.81 -   int32 coreNum = requestingSlv->coreAnimatedBy;
   13.82 +   int32 slotNum = oldSlotSlv->animSlotAssignedTo->slotIdx;
   13.83 +   int32 coreNum = oldSlotSlv->coreAnimatedBy;
   13.84     _PRTopEnv->slotTaskSlvs[coreNum][slotNum] = newSlotSlv;
   13.85  
   13.86        //Fix up requester, to be an extra slave now (but not an ended one)
   13.87        // because it's active, doesn't go into freeTaskSlvRecycleQ
   13.88 -   requestingSlv->typeOfVP = FreeTaskSlv;
   13.89 -   requestingSlv->processSlaveIsIn = process;   
   13.90 +      //Note that process was set when task was assigned to the slot slave..
   13.91 +   oldSlotSlv->typeOfVP = FreeTaskSlv;   
   13.92   }
   13.93  
   13.94  void idle_fn(void* data, SlaveVP *animatingSlv)
   13.95 @@ -241,31 +241,42 @@
   13.96     PR_int__free( slave );   
   13.97   }
   13.98  
   13.99 -/*This calls recycle handler registered for each langlet's lang data and meta
  13.100 - * task.  It also recycles the slave struct.
  13.101 +/*This calls the freer registered for each langlet's lang data and meta
  13.102 + * task.  Then it makes the collections empty.  It also recycles the slave 
  13.103 + * struct.
  13.104 + *Note: it does not clear "next in coll" pointers in the coll elements!
  13.105   * 
  13.106   *DOES NOT DECREMENT NUMBER OF LIVE SLAVES IN PROCESS
  13.107 - * 
  13.108 - *This assumes that each slave has an array of 
  13.109 + *
  13.110 + *Note, the fn applied to all elements of collections checks the "don't delete"
  13.111 + * flag in the lang data and the meta task.. so, if an alternative way of 
  13.112 + * freeing the slaveVP struct is created, it should handle the "don't delete"
  13.113 + * flag. (although, an "abort" cleanup should ignore the don't delete flag)
  13.114   */
  13.115  void
  13.116 -PR_int__recycle_slave( SlaveVP *slave )
  13.117 +PR_int__recycle_slaveVP( SlaveVP *slave )
  13.118   { 
  13.119     PR_int__apply_Fn_to_all_in_collection( &freeLangDataAsElem, 
  13.120                                             (PRCollElem**) slave->langDatas );
  13.121     PR_int__apply_Fn_to_all_in_collection( &freeMetaTaskAsElem, 
  13.122                                             (PRCollElem**) slave->metaTasks );
  13.123 +   //now, set the collections to "empty"
  13.124 +   PR_int__set_collection_to_empty((PRCollElem**) slave->langDatas);
  13.125 +   PR_int__set_collection_to_empty((PRCollElem**) slave->metaTasks);
  13.126  
  13.127     writePrivQ( slave, _PRTopEnv->slaveRecycleQ );
  13.128   }
  13.129  
  13.130  /*Receives a protoLangData, but in the form of a void, so have to cast
  13.131 + *First checks the "no delete" flag..
  13.132   */
  13.133  void
  13.134  freeLangDataAsElem( void *elem )
  13.135   { PRLangData *protoLangData;
  13.136     
  13.137     protoLangData = (PRLangData *)elem; //recycler actually receives the prolog.
  13.138 +   if( protoLangData->goAheadAndFree == FALSE ) 
  13.139 +       return;
  13.140     
  13.141        //apply the free fn that's stored in the lang data prolog
  13.142        //Note: freeing whole slave, so no need to remove from collection
  13.143 @@ -285,6 +296,9 @@
  13.144     protoMetaTask = (PRMetaTask *)elem;  //recycler receives the prolog, and must call
  13.145     //a PR Fn to convert prolog to lang-specific version.
  13.146     
  13.147 +   if( protoMetaTask->goAheadAndFree == FALSE ) 
  13.148 +       return;
  13.149 +   
  13.150        //apply the free fn that's stored in the meta task prolog
  13.151     (*(protoMetaTask->freer))( PR_int__give_lang_meta_task_of_prolog(protoMetaTask) );  
  13.152   }
  13.153 @@ -305,29 +319,34 @@
  13.154     return (PRLangEnv *) &(((PRLangEnv *)langEnv)[-1]);
  13.155   }
  13.156  
  13.157 -inline
  13.158 +//inline
  13.159  void *
  13.160 -PR_int__create_lang_env_in_process( int32 size, PRProcess process, int32 magicNum )
  13.161 +PR_int__create_lang_env_in_process( int32 numBytes, PRProcess *process, int32 magicNum )
  13.162   { PRLangEnv *retEnv;
  13.163     PRCollElem **langEnvs;
  13.164     
  13.165        //make the new lang env, with room for the prolog
  13.166 -   retEnv = PR_int__malloc( sizeof(PRLangEnv) + size );
  13.167 +   retEnv = PR_int__malloc( sizeof(PRLangEnv) + numBytes );
  13.168 +   retEnv->chainedLangEnv = NULL;      //used while inserting into langEnvs
  13.169 +   retEnv->langMagicNumber = magicNum; //used while inserting into langEnvs
  13.170 +   retEnv->processEnvIsIn = process;
  13.171 +   retEnv->numLiveWork = 0;
  13.172 +   retEnv->waitingForWorkToEndQ = makePrivQ();
  13.173     
  13.174        //process has a PR Collection of lang envs -- get it and insert into it
  13.175     langEnvs = (PRCollElem **)process->langEnvs;
  13.176     PR_int__insert_elem_into_collection( (PRCollElem *)retEnv, langEnvs, magicNum);
  13.177 -   int32 idxInProcess = process->numLangEnvs;
  13.178 -   process->langEnvsList[idxInProcess] = retEnv;
  13.179 +   int32 idxInProcess = process->numLangEnvs; //index starts at 0 for first lang
  13.180 +   process->protoLangEnvsList[idxInProcess] = retEnv;
  13.181     retEnv->idxInProcess = idxInProcess;
  13.182     process->numLangEnvs += 1;
  13.183     
  13.184 -   return &(retEnv[1]); //skip over prolog
  13.185 +   return (void *)&(retEnv[1]); //skip over prolog
  13.186   }
  13.187  
  13.188  inline
  13.189  void *
  13.190 -PR_int__free_lang_env( void *langEnv )
  13.191 +PR_int__remove_lang_env_from_process_and_free( void *langEnv )
  13.192   { PRLangEnv   *protoLangEnv = PR_int__give_proto_lang_env( langEnv );
  13.193     PRCollElem **langEnvs;
  13.194     PRLangEnv  **langEnvsList;
  13.195 @@ -335,11 +354,11 @@
  13.196        //process has a PR Collection of lang envs -- get it and remove env
  13.197     PRProcess *process = protoLangEnv->processEnvIsIn;
  13.198     langEnvs = (PRCollElem **)process->langEnvs;
  13.199 -   PR_int__remove_elem_from_collection( (PRCollElem *)protoLangEnv, langEnvs );
  13.200 +   PR_int__remove_elem_from_collection( protoLangEnv->langMagicNumber, langEnvs );
  13.201     int32 count, idx;
  13.202     idx = protoLangEnv->idxInProcess;
  13.203 -   count = (process->numLangEnvs - idx - 1) * sizeof(PRLangEnv *);
  13.204 -   memmove( langEnvsList[idx], langEnvsList[idx+1], count);
  13.205 +   count = (process->numLangEnvs - idx) * sizeof(PRLangEnv *);//idx starts at 0
  13.206 +   memmove( &(langEnvsList[idx]), &(langEnvsList[idx+1]), count);
  13.207     
  13.208     PR_int__free( protoLangEnv );
  13.209   }
  13.210 @@ -362,7 +381,7 @@
  13.211  PRLangEnv *
  13.212  PR_int__give_proto_lang_env_for_slave( SlaveVP *slave, int32 magicNum )
  13.213   {    
  13.214 -   return PR_int__give_proto_lang_env_for_process( slave->processSlaveIsIn, magicNum );
  13.215 +   return PR_int__give_proto_lang_env_from_process( slave->processSlaveIsIn, magicNum );
  13.216   }
  13.217  
  13.218  inline
  13.219 @@ -380,7 +399,7 @@
  13.220   }
  13.221  inline
  13.222  PRLangEnv *
  13.223 -PR_int__give_proto_lang_env_for_process( PRProcess *process, int32 magicNum )
  13.224 +PR_int__give_proto_lang_env_from_process( PRProcess *process, int32 magicNum )
  13.225   { PRLangEnv    *retLangEnv;
  13.226     PRCollElem **langEnvs;
  13.227     
  13.228 @@ -453,25 +472,29 @@
  13.229   */
  13.230  inline
  13.231  void
  13.232 -PR_int__put_task_into_slot( PRMetaTask *task, PRProcess *process, AnimSlot *slot )
  13.233 +PR_int__put_task_into_slot( void *langMetaTask, AnimSlot *slot )
  13.234   { int32 slotNum, coreNum;
  13.235     SlaveVP *slotSlv;
  13.236 +   PRMetaTask *protoMetaTask;
  13.237   
  13.238 +   protoMetaTask = PR_int__give_prolog_of_lang_meta_task( langMetaTask );
  13.239 +   
  13.240        //get the slot slave to assign the task to..
  13.241     slotNum = slot->slotIdx;
  13.242     coreNum = slot->coreSlotIsOn;
  13.243     slotSlv = _PRTopEnv->slotTaskSlvs[coreNum][slotNum];
  13.244  
  13.245       //point slave to task's function
  13.246 -   PR_int__reset_slaveVP_to_TopLvlFn( slotSlv, task->topLevelFn, task->initData );
  13.247 -   PR_int__insert_meta_task_into_slave( task, slotSlv );
  13.248 +   PR_int__reset_slaveVP_to_TopLvlFn( slotSlv, protoMetaTask->topLevelFn, protoMetaTask->initData );
  13.249 +   PR_int__insert_meta_task_into_slave( protoMetaTask, slotSlv );
  13.250 +   slotSlv->processSlaveIsIn = protoMetaTask->processTaskIsIn;
  13.251     PR_int__put_slave_into_slot( slotSlv, slot );
  13.252   }
  13.253  
  13.254  //==========================
  13.255  inline 
  13.256  PRMetaTask *
  13.257 -PR_int__give_prolog_of_task( void *task )
  13.258 +PR_int__give_prolog_of_lang_meta_task( void *task )
  13.259   {
  13.260      return (PRMetaTask *) &(((PRMetaTask *)task)[-1]);
  13.261   }
  13.262 @@ -497,19 +520,33 @@
  13.263     retMetaTask->taskType        = SlotTask; //just common default
  13.264     retMetaTask->ID              = NULL;
  13.265     retMetaTask->freer           = freer;
  13.266 +   retMetaTask->goAheadAndFree  = TRUE;
  13.267       
  13.268     return retMetaTask; //skip over prolog
  13.269   }
  13.270  
  13.271 -/*Might never need this fn -- think the slave dissipator does this work
  13.272 +/*Calls the lang's freer, which is pointed to, and also removes from collection
  13.273 + */
  13.274 +void
  13.275 +PR_int__free_lang_meta_task_and_remove_from_coll( void *langMetaTask)
  13.276 + { PRMetaTask *protoMetaTask;
  13.277 +   
  13.278 +   protoMetaTask = PR_int__give_prolog_of_lang_meta_task( langMetaTask );
  13.279 +   PR_int__remove_elem_from_collection( protoMetaTask->langMagicNumber,
  13.280 +                    (PRCollElem **) protoMetaTask->slaveAssignedTo->metaTasks );
  13.281 +
  13.282 +   (*protoMetaTask->freer)(langMetaTask);
  13.283 +   PR_int__free( protoMetaTask );   
  13.284 + }
  13.285 +
  13.286 +/*Just calls the lang's freer, and frees the malloc'd meta-task chunk. Should
  13.287 + * already have been removed from slave's collection and all queues holding it
  13.288   */
  13.289  void
  13.290  PR_int__free_lang_meta_task( void *langMetaTask)
  13.291   { PRMetaTask *protoMetaTask;
  13.292     
  13.293 -   protoMetaTask = PR_int__give_prolog_of_task( langMetaTask );
  13.294 -   PR_int__remove_elem_from_collection( protoMetaTask->langMagicNumber,
  13.295 -                                    protoMetaTask->slaveAssignedTo->metaTasks );
  13.296 +   protoMetaTask = PR_int__give_prolog_of_lang_meta_task( langMetaTask );
  13.297  
  13.298     (*protoMetaTask->freer)(langMetaTask);
  13.299     PR_int__free( protoMetaTask );   
  13.300 @@ -578,22 +615,16 @@
  13.301     metaTasks = (PRCollElem **)slave->metaTasks;
  13.302     retMetaTask = PR_int__lookup_elem_in_collection( magicNum, metaTasks );
  13.303     if( retMetaTask != NULL ) 
  13.304 -      return &(retMetaTask[1]); //skip over prolog
  13.305 +      return PR_int__give_lang_meta_task_of_prolog(retMetaTask); //skip over prolog
  13.306     else
  13.307 -    { protoLangEnv = PR_int__give_proto_lang_env_for_slave( slave );
  13.308 +    { protoLangEnv = PR_int__give_proto_lang_env_for_slave( slave, magicNum );
  13.309        if(protoLangEnv->langMetaTaskCreator == NULL) 
  13.310 -         PR_int__throw_exception("register a meta task creator");
  13.311 +         PR_int__error("register a meta task creator");
  13.312           //This will call 
  13.313        return (*protoLangEnv->langMetaTaskCreator)( slave );
  13.314      }
  13.315   }
  13.316  
  13.317 -inline
  13.318 -SlaveVP *
  13.319 -PR_PI__give_slave_lang_meta_task_is_assigned_to( void *langMetaTask )
  13.320 - { PRMetaTask *metaTask = &(((PRMetaTask*)langMetaTask)[-1]);
  13.321 -   return metaTask->slaveAssignedTo;
  13.322 - }
  13.323  
  13.324  //================== langData =============================
  13.325  inline 
  13.326 @@ -628,6 +659,7 @@
  13.327     retLangData->chainedLangData = NULL;
  13.328     retLangData->langMagicNumber = magicNum;
  13.329     retLangData->freer = freer;
  13.330 +   retLangData->goAheadAndFree = TRUE;
  13.331     retLangData->slaveAssignedTo = slave;
  13.332    
  13.333        //multilang has a "collection" of lang datas inside the slave
  13.334 @@ -642,7 +674,7 @@
  13.335     
  13.336     protoLangData = PR_int__give_prolog_of_lang_data( langData );
  13.337     PR_int__remove_elem_from_collection( protoLangData->langMagicNumber,
  13.338 -                                    protoLangData->slaveAssignedTo->langDatas );
  13.339 +                    (PRCollElem **) protoLangData->slaveAssignedTo->langDatas );
  13.340  
  13.341     (*protoLangData->freer)(langData);
  13.342     PR_int__free( protoLangData );   
  13.343 @@ -660,9 +692,9 @@
  13.344     if( retLangData != NULL ) 
  13.345        return &( retLangData[1] ); //skip over prolog
  13.346     else
  13.347 -    { protoLangEnv = PR_int__give_proto_lang_env_for_slave( slave );
  13.348 +    { protoLangEnv = PR_int__give_proto_lang_env_for_slave( slave, magicNum );
  13.349        if(protoLangEnv->langDataCreator == NULL) 
  13.350 -         PR_int__throw_exception("register a lang data creator");
  13.351 +         PR_int__error("register a lang data creator");
  13.352           //This will call PR_PI__create_lang_data_in_slave
  13.353        return (*protoLangEnv->langDataCreator)( slave );
  13.354      }
  13.355 @@ -670,6 +702,22 @@
  13.356  
  13.357  
  13.358  //===============================================
  13.359 +PRCollElem ** //return an array of pointers
  13.360 +PR_int__make_collection_of_size( int32 numInColl )
  13.361 + { int32 *prolog;
  13.362 +   PRCollElem **coll;
  13.363 +      //Note using size of a pointer to a coll element
  13.364 +   int32 numBytes = sizeof(int32) + numInColl * sizeof(PRCollElem *);
  13.365 +   prolog = PR_WL__malloc( numBytes );
  13.366 +
  13.367 +      //operation of collection relies upon initial entries being NULL
  13.368 +   memset(prolog, ZERO, numBytes>>2);  //BUG: if size not multiple of 4
  13.369 +
  13.370 +   prolog[0] = numInColl;
  13.371 +   coll = (PRCollElem **)&(prolog[1]);
  13.372 +   return coll;
  13.373 + }
  13.374 +
  13.375  inline
  13.376  void
  13.377  PR_int__insert_elem_into_collection( PRCollElem *elem, PRCollElem **coll, int32 hash )
  13.378 @@ -733,32 +781,51 @@
  13.379        test = test->chained;
  13.380        if( test == NULL ) return; //not found, nothing to remove
  13.381      }
  13.382 -   if( prev == NULL)
  13.383 +   if( prev == NULL) //is first elem in chain, so modify ptr in array
  13.384      { coll[idx] = coll[idx]->chained;
  13.385        return;
  13.386      }
  13.387 -   else
  13.388 +   else //remove link from chain
  13.389      { prev->chained = test->chained;
  13.390        return;
  13.391      }
  13.392   }
  13.393  
  13.394 +
  13.395 +/*The function is allowed to modify its OWN chaining.. this takes the next
  13.396 + * in chain before calling the function (useful when the function conditionally
  13.397 + * frees)
  13.398 + */
  13.399  inline
  13.400  void
  13.401 -PR_int__apply_Fn_to_all_in_collection( void (*Fn)(void *), PRCollElem *coll )
  13.402 +PR_int__apply_Fn_to_all_in_collection( void (*Fn)(void *), PRCollElem **coll )
  13.403   { int32 idx, numIdxsInColl;
  13.404 -   PRCollElem *test;
  13.405 +   PRCollElem *test, *chainedTest;
  13.406  
  13.407     numIdxsInColl = ((int32 *)coll)[-1]; //prolog is num idxs
  13.408 -   for( idx = 0; idx < ; idx++ )
  13.409 +      //march down array of elements, for each, march down linked chain of elems
  13.410 +   for( idx = 0; idx < numIdxsInColl; idx++ )
  13.411      { test = coll[idx];
  13.412        while( test != NULL )
  13.413 -       { (*Fn)((void *)test); 
  13.414 -         test = test->chained;  
  13.415 +       { chainedTest = test->chained; //Fn may destroy test or change test->chained
  13.416 +         (*Fn)((void *)test);
  13.417 +         test = chainedTest;
  13.418         }
  13.419      }
  13.420   }
  13.421  
  13.422 +/*Just sets all entries to NULL -- doesn't modify chaining of any elements
  13.423 + * that may be left in the collection..
  13.424 + */
  13.425 +inline
  13.426 +void
  13.427 +PR_int__set_collection_to_empty( PRCollElem **coll )
  13.428 + { int32 numIdxsInColl = ((int32 *)coll)[-1]; //prolog is num idxs
  13.429 +   memset( coll, 0, numIdxsInColl * sizeof(PRCollElem *) );
  13.430 + }
  13.431 +//==========================================
  13.432 +
  13.433 +
  13.434  //==========================================
  13.435  
  13.436  /*Later, improve this -- for now, just exits the application after printing
  13.437 @@ -772,13 +839,20 @@
  13.438     exit(1);
  13.439   }
  13.440  
  13.441 +void
  13.442 +PR_int__error( char *msgStr )
  13.443 + {
  13.444 +   printf("%s",msgStr);
  13.445 +   fflush(stdin);
  13.446 +   exit(1);
  13.447 + }
  13.448  
  13.449 -inline 
  13.450 +
  13.451  char *
  13.452  PR_int__strDup( char *str )
  13.453   { char *retStr;
  13.454  
  13.455 -   if( str == NULL ) return (char *)NULL;
  13.456 +   if( str == NULL ) return NULL;
  13.457     retStr = (char *)PR_int__malloc( strlen(str) + 1 );
  13.458     strcpy( retStr, str );
  13.459  
  13.460 @@ -793,13 +867,16 @@
  13.461  PR_int__get_master_lock()
  13.462   { int32 *addrOfMasterLock;
  13.463   
  13.464 +  #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
  13.465 +            return;
  13.466 +  #endif
  13.467 +
  13.468     addrOfMasterLock = &(_PRTopEnv->masterLock);
  13.469  
  13.470     int numTriesToGetLock = 0;
  13.471     int gotLock = 0;
  13.472     
  13.473              MEAS__Capture_Pre_Master_Lock_Point;
  13.474 -
  13.475     while( !gotLock ) //keep going until get master lock
  13.476      { 
  13.477        numTriesToGetLock++;   //if too many, means too much contention
    14.1 --- a/PR__int.h	Tue Feb 05 20:23:27 2013 -0800
    14.2 +++ b/PR__int.h	Sat Mar 02 09:43:45 2013 -0800
    14.3 @@ -20,10 +20,6 @@
    14.4   */
    14.5  
    14.6  inline
    14.7 -PRMetaTask *
    14.8 -PR_int__create_generic_slave_meta_task( void *initData );
    14.9 -
   14.10 -inline
   14.11  void
   14.12  PR_int__reset_slaveVP_to_TopLvlFn( SlaveVP *slaveVP, TopLevelFnPtr fnPtr,
   14.13                                void    *dataParam);
   14.14 @@ -64,7 +60,7 @@
   14.15  
   14.16  inline
   14.17  void
   14.18 -PR_int__put_task_into_slot( PRMetaTask *task, PRProcess *process, AnimSlot *slot );
   14.19 +PR_int__put_task_into_slot( void *task, AnimSlot *slot );
   14.20  
   14.21  inline
   14.22  void
   14.23 @@ -74,16 +70,10 @@
   14.24  PRHandle__ServiceReq(  SlaveVP *requestingSlv );
   14.25  
   14.26  void
   14.27 -PR_WL__suspend_slaveVP_and_send_req( SlaveVP *animatingSlv );
   14.28 -
   14.29 -void
   14.30 -PR_int__dissipate_slaveVP__SL( SlaveVP *animatingSlv );
   14.31 -
   14.32 -void
   14.33  PR_int__free_slaveVP( SlaveVP *slave );
   14.34  
   14.35  void
   14.36 -PR_int__recycle_slave( SlaveVP *slave );
   14.37 +PR_int__recycle_slaveVP( SlaveVP *slave );
   14.38  
   14.39  void
   14.40  freeLangDataAsElem( void *elem );
   14.41 @@ -91,6 +81,10 @@
   14.42  void
   14.43  freeMetaTaskAsElem( void *elem );
   14.44  
   14.45 +
   14.46 +//=============================
   14.47 +//=== Lange Env
   14.48 +//=
   14.49  inline 
   14.50  void *
   14.51  PR_int__give_lang_env( PRLangEnv *protoLangEnv );
   14.52 @@ -99,13 +93,13 @@
   14.53  PRLangEnv *
   14.54  PR_int__give_proto_lang_env( void *langEnv );
   14.55  
   14.56 -inline
   14.57 +//inline
   14.58  void *
   14.59  PR_int__create_lang_env_in_process( int32 size, PRProcess *process, int32 magicNum );
   14.60  
   14.61  inline
   14.62  void *
   14.63 -PR_int__free_lang_env( void *langEnv );
   14.64 +PR_int__remove_lang_env_from_process_and_free( void *langEnv );
   14.65  
   14.66  inline
   14.67  void *
   14.68 @@ -114,42 +108,28 @@
   14.69  inline
   14.70  void *
   14.71  PR_int__give_lang_env_for_slave( SlaveVP *slave, int32 magicNum );
   14.72 -#define PR_PI__give_lang_env_for  PR_int__give_lang_env_for_slave
   14.73 -#define PR_SS__give_lang_env_for_slave  PR_int__give_lang_env_for_slave
   14.74  //No WL version -- not safe!  if use env in WL, be sure data rd & wr is stable
   14.75  
   14.76  inline
   14.77  PRLangEnv *
   14.78 -PR_int__give_proto_lang_env_for_slave__ML( SlaveVP *slave, int32 magicNumber );
   14.79 -#define PR_PI__give_proto_lang_env_for  PR_int__give_proto_lang_env_for_slave__ML
   14.80 -#define PR_SS__give_proto_lang_env_for_slave  PR_int__give_proto_lang_env_for_slave__ML
   14.81 +PR_int__give_proto_lang_env_for_slave( SlaveVP *slave, int32 magicNumber );
   14.82  //No WL version -- not safe!  if use env in WL, be sure data rd & wr is stable
   14.83  
   14.84  inline
   14.85  void *
   14.86  PR_int__give_lang_env_from_process( PRProcess *process, int32 magicNum );
   14.87 -#define PR_PI__give_lang_env_from_process  PR_int__give_lang_env_from_process
   14.88 -#define PR_SS__give_lang_env_from_process  PR_int__give_lang_env_from_process
   14.89 -//#define PR_WL__give_lang_env_from_process  PR_int__give_lang_env_from_process
   14.90  //No WL version -- not safe!  if use env in WL, be sure data rd & wr is stable
   14.91  
   14.92  inline
   14.93  PRLangEnv *
   14.94 -PR_int__give_proto_lang_env_for_process( PRProcess *process, int32 magicNum );
   14.95 +PR_int__give_proto_lang_env_from_process( PRProcess *process, int32 magicNum );
   14.96  
   14.97 -/*
   14.98 -inline
   14.99 -void
  14.100 -PR_int__set_work_in_lang_env( void *_langEnv );
  14.101 -
  14.102 -inline
  14.103 -void
  14.104 -PR_int__clear_work_in_lang_env( void *_langEnv );
  14.105 - */
  14.106 -
  14.107 +//=======================
  14.108 +//=== Meta Task
  14.109 +//=
  14.110  inline 
  14.111  PRMetaTask *
  14.112 -PR_int__give_prolog_of_task( void *task );
  14.113 +PR_int__give_prolog_of_lang_meta_task( void *task );
  14.114  
  14.115  inline
  14.116  void *
  14.117 @@ -157,11 +137,19 @@
  14.118  
  14.119  inline
  14.120  void *
  14.121 -PR_int__create_lang_meta_task( int32 size, int32 magicNum );
  14.122 +PR_int__create_lang_meta_task( int32 size, LangMetaTaskFreer freer, int32 magicNum );
  14.123  
  14.124  inline
  14.125  void *
  14.126 -PR_int__create_lang_meta_task_in_slave( int32 size, SlaveVP *slave, int32 magicNum );
  14.127 +PR_int__create_lang_meta_task_in_slave( int32 size, LangMetaTaskFreer freer,
  14.128 +                                        SlaveVP *slave, int32 magicNum );
  14.129 +
  14.130 +inline
  14.131 +PRMetaTask *
  14.132 +PR_int__create_generic_slave_meta_task( void *initData );
  14.133 +
  14.134 +void
  14.135 +PR_int__free_lang_meta_task_and_remove_from_coll( void *langMetaTask );
  14.136  
  14.137  inline
  14.138  void
  14.139 @@ -174,28 +162,35 @@
  14.140  inline
  14.141  void *
  14.142  PR_int__give_lang_meta_task_from_slave( SlaveVP *slave, int32 magicNumer );
  14.143 -//#define PR_int__give_lang_meta_task_from_slave__ML( slave, magicNumber )\
  14.144 -        slave->metaTask->langMetaTask;
  14.145 -#define PR_PI__give_lang_meta_task_from_slave__ML  PR_int__give_lang_meta_task_from_slave
  14.146 -#define PR_SS__give_lang_meta_task_from_slave__ML  PR_int__give_lang_meta_task_from_slave
  14.147 -#define PR_WL__give_lang_meta_task_from_slave__ML  PR_int__give_lang_meta_task_from_slave
  14.148  
  14.149  inline
  14.150  SlaveVP *
  14.151  PR_PI__give_slave_lang_meta_task_is_assigned_to( void *langMetaTask );
  14.152  
  14.153 +//==============
  14.154 +//=== Lang Data
  14.155 +//=
  14.156  inline
  14.157  void *
  14.158 -PR_PI__create_lang_data_in_slave( int32 size, SlaveVP *slave, int32 magicNum );
  14.159 +PR_PI__create_lang_data_in_slave( int32 size, LangDataFreer freer,
  14.160 +                                   SlaveVP *slave, int32 magicNum );
  14.161  
  14.162  inline
  14.163  void *
  14.164  PR_int__give_lang_data_from_slave( SlaveVP *slave, int32 magicNumer );
  14.165 -#define PR_PI__give_lang_data  PR_int__give_lang_data_from_slave
  14.166 -#define PR_SS__give_lang_data  PR_int__give_lang_data_from_slave
  14.167  #define PR_WL__give_lang_data  PR_int__give_lang_data_from_slave
  14.168  
  14.169  inline
  14.170 +void *
  14.171 +PR_int__give_lang_data_of_prolog( PRLangData *langData);
  14.172 +
  14.173 +//==================================================
  14.174 +//===  Collection
  14.175 +//=
  14.176 +PRCollElem ** //return an array of pointers
  14.177 +PR_int__make_collection_of_size( int32 numInColl );
  14.178 +
  14.179 +inline
  14.180  void
  14.181  PR_int__insert_elem_into_collection( PRCollElem *elem, PRCollElem **coll, int32 hash );
  14.182  
  14.183 @@ -209,19 +204,25 @@
  14.184  
  14.185  inline
  14.186  void
  14.187 -PR_int__apply_Fn_to_all_in_collection( void (*Fn)(void *), PRCollElem *coll );
  14.188 +PR_int__set_collection_to_empty( PRCollElem **coll );
  14.189 +
  14.190 +inline
  14.191 +void
  14.192 +PR_int__apply_Fn_to_all_in_collection( void (*Fn)(void *), PRCollElem **coll );
  14.193 +
  14.194 +//===========
  14.195 +//===
  14.196 +//=
  14.197 +void
  14.198 +PR_int__error( char *msgStr );
  14.199  
  14.200  void
  14.201  PR_int__throw_exception( char *msgStr, SlaveVP *reqstSlv, PRExcp *excpData );
  14.202 -#define PR_PI__throw_exception  PR_int__throw_exception
  14.203  
  14.204 -inline char *
  14.205 +char *
  14.206  PR_int__strDup( char *str );
  14.207  
  14.208  inline void
  14.209 -PR_int__backoff_for_TooLongToGetLock( int32 numTriesToGetLock );
  14.210 -
  14.211 -inline void
  14.212  PR_int__get_master_lock();
  14.213  
  14.214  #define PR_int__release_master_lock() _PRTopEnv->masterLock = UNLOCKED
    15.1 --- a/PR__structs.h	Tue Feb 05 20:23:27 2013 -0800
    15.2 +++ b/PR__structs.h	Sat Mar 02 09:43:45 2013 -0800
    15.3 @@ -17,7 +17,10 @@
    15.4  
    15.5  
    15.6  //================================ Typedefs =================================
    15.7 -//
    15.8 +//===
    15.9 +//=
   15.10 +#define ZERO 0
   15.11 +
   15.12  typedef unsigned long long    TSCount;
   15.13  
   15.14  typedef struct _AnimSlot      AnimSlot;
   15.15 @@ -30,13 +33,13 @@
   15.16  typedef struct _PRLangData    PRLangData; //a prolog
   15.17  typedef struct _PRCollElem    PRCollElem; //generic form of the prologs
   15.18  
   15.19 -typedef SlaveVP *(*SlaveAssigner)  ( void *, AnimSlot* ); //langEnv, slot for HW info
   15.20 +typedef bool32   (*SlaveAssigner)  ( void *, AnimSlot* ); //langEnv, slot for HW info
   15.21  typedef void     (*RequestHandler) ( void *, SlaveVP *, void * ); //req, slv, langEnv
   15.22  typedef void    *(*CreateHandler)  ( void *, SlaveVP *, void * ); //req, slv, langEnv
   15.23  typedef void     (*LangShutdownHdlr) ( void * ); //langEnv
   15.24  typedef void    *(*LangDataCreator)  ( SlaveVP * ); 
   15.25  typedef void     (*LangDataFreer)    ( void * ); //lang data to free
   15.26 -typedef void    *(*LangMetaTaskCreator)( SlaveVP * ); 
   15.27 +typedef void    *(*LangMetaTaskCreator)( SlaveVP * );  //when slave has no meta task for magic num 
   15.28  typedef void     (*LangMetaTaskFreer)  ( void * ); //lang meta task to free
   15.29  typedef void     (*MakeSlaveReadyFn)   ( SlaveVP *, void * ); //slave and langEnv
   15.30  typedef void     (*MakeTaskReadyFn)    ( void *, void * ); //langTask and langEnv
   15.31 @@ -73,7 +76,7 @@
   15.32     void     *resultToReturn;
   15.33      
   15.34     PRLangEnv **langEnvs;     //used as a hash table
   15.35 -   PRLangEnv **langEnvsList; //for fast linear scan of envs
   15.36 +   PRLangEnv **protoLangEnvsList; //for fast linear scan of envs
   15.37     int32      numLangEnvs;   //for fast linear scan of envs
   15.38      
   15.39     SlaveVP        *seedSlv;
   15.40 @@ -86,6 +89,7 @@
   15.41     
   15.42     
   15.43        //These are used to coord with an OS thread waiting for process to end
   15.44 +   bool32          hasWaitingToEnd;
   15.45     bool32          executionIsComplete;
   15.46     pthread_mutex_t doneLock;
   15.47     pthread_cond_t  doneCond;   
   15.48 @@ -124,9 +128,13 @@
   15.49     Service,       //To invoke a PR provided equivalent of a language request (ex: probe)
   15.50     Hardware,
   15.51     IO,
   15.52 -   OSCall
   15.53 +   OSCall, 
   15.54 +   LangShutdown,
   15.55 +   ProcessEnd,
   15.56 +   PRShutdown
   15.57   };
   15.58  
   15.59 +
   15.60  struct _PRReqst
   15.61   {
   15.62     enum PRReqstType   reqType;//used for special forms that have PR behavior
   15.63 @@ -149,7 +157,7 @@
   15.64   };
   15.65  //PRReqst
   15.66  
   15.67 -enum PRServReqType   //These are equivalent to lang requests, but for
   15.68 +enum PRServiceReqType   //These are equivalent to lang requests, but for
   15.69   {                    // PR's services available directly to app, like OS
   15.70     make_probe = 1,    // and probe services -- like a PR-wide built-in lang
   15.71     throw_excp,
   15.72 @@ -158,13 +166,13 @@
   15.73   };
   15.74  
   15.75  typedef struct
   15.76 - { enum PRServReqType   reqType;
   15.77 + { enum PRServiceReqType   reqType;
   15.78     SlaveVP             *requestingSlv;
   15.79     char                *nameStr;  //for create probe
   15.80     char                *msgStr;   //for exception
   15.81     void                *exceptionData;
   15.82   }
   15.83 -PRServReq;
   15.84 +PRServiceReq;
   15.85  
   15.86  
   15.87  //====================  Core data structures  ===================
   15.88 @@ -192,9 +200,9 @@
   15.89     FreeTaskSlv,   //When a suspended task ends, the slave becomes this
   15.90     GenericSlv,     //the VP is explicitly seen in the app code, or task suspends
   15.91     SeedSlv,
   15.92 -   Master,
   15.93 -   Shutdown,
   15.94 -   Idle
   15.95 +   Master_VP,
   15.96 +   ShutdownVP,
   15.97 +   IdleVP
   15.98   };
   15.99   
  15.100  /*This structure embodies the state of a slaveVP.  It is reused for masterVP
  15.101 @@ -228,8 +236,8 @@
  15.102        //For language specific data that needs to be in the slave
  15.103        //These are accessed  directly for single-lang, but multi-lang places
  15.104        // a holder here instead, then uses magic num to get lang's version
  15.105 -   void       *langDatas;  //Lang saves lang-specific things in slave here
  15.106 -   void       *metaTasks;
  15.107 +   PRLangData  **langDatas;  //Lang saves lang-specific things in slave here
  15.108 +   PRMetaTask  **metaTasks;
  15.109  
  15.110          //=========== MEASUREMENT STUFF ==========
  15.111           MEAS__Insert_Meas_Fields_into_Slave;
  15.112 @@ -335,16 +343,6 @@
  15.113     LangMetaTaskCreator langMetaTaskCreator;
  15.114     MakeSlaveReadyFn makeSlaveReadyFn;
  15.115     MakeTaskReadyFn  makeTaskReadyFn;
  15.116 -/*
  15.117 -   CreateTaskHdlr  createTaskHdlr;
  15.118 -   RequestHandler  endTaskHdlr; 
  15.119 -   CreateSlvHdlr   createSlaveHdlr;
  15.120 -   RequestHandler  dissipateSlaveHdlr;
  15.121 -  
  15.122 -   LangDataFreer    langDataFreer;
  15.123 -   LangMetaTaskFreer langMetaTaskFreer;
  15.124 -   RequestHandler   langDataInitializer;
  15.125 - */
  15.126       
  15.127        //when multi-lang, master polls lang env's to find one with work in it..
  15.128        // in single-lang case, flag ignored, master always asks lang for work
  15.129 @@ -354,7 +352,9 @@
  15.130     int32           idxInProcess; //index into array of langEnvs in the process
  15.131     
  15.132     int32           numReadyWork;
  15.133 -   fixme; //make make_ready update the process's numEnvs with work
  15.134 +   
  15.135 +   int32           numLiveWork;
  15.136 +   PrivQueueStruc *waitingForWorkToEndQ;
  15.137   };
  15.138  //PRLangEnv -- this is the prolog of every lang's lang env
  15.139  
  15.140 @@ -371,10 +371,12 @@
  15.141     //=============================================================
  15.142     enum PRTaskType taskType;
  15.143     int32          *ID;              //is standard PR ID
  15.144 -   SlaveVP        *slaveAssignedTo; //no valid until task animated
  15.145 +   PRProcess      *processTaskIsIn;
  15.146 +   SlaveVP        *slaveAssignedTo; //not valid until task animated
  15.147     TopLevelFnPtr   topLevelFn;      //This is the Fn executes as the task
  15.148     void           *initData;        //The data taken by the function
  15.149     LangMetaTaskFreer freer;
  15.150 +   bool32          goAheadAndFree;
  15.151  
  15.152     //NOTE: info needed for "wait" functionality is inside lang's metaTask
  15.153   };
  15.154 @@ -386,6 +388,7 @@
  15.155     PRLangData   *chainedLangData;
  15.156     //=============================================================
  15.157     LangDataFreer  freer;
  15.158 +   bool32         goAheadAndFree;
  15.159     SlaveVP       *slaveAssignedTo;
  15.160   };
  15.161  //PRLangData -- this is the prolog of each lang's lang data
  15.162 @@ -399,16 +402,6 @@
  15.163  
  15.164  
  15.165  
  15.166 -//The language env of PR's services langlet
  15.167 -typedef struct
  15.168 - { 
  15.169 -   PrivQueueStruc  *slavesReadyToResumeQ; //Shared (slaves not pinned)
  15.170 -   PrivQueueStruc  *taskReadyQ;           //Shared (tasks not pinned)
  15.171 - }
  15.172 -PRServLangEnv;
  15.173 -
  15.174 -
  15.175 -
  15.176  //=========================  Extra Stuff Data Strucs  =======================
  15.177  typedef struct
  15.178   {
    16.1 --- a/Services_Offered_by_PR/Measurement_and_Stats/MEAS__macros.h	Tue Feb 05 20:23:27 2013 -0800
    16.2 +++ b/Services_Offered_by_PR/Measurement_and_Stats/MEAS__macros.h	Sat Mar 02 09:43:45 2013 -0800
    16.3 @@ -501,7 +501,7 @@
    16.4  #define MEAS__Make_Meas_Hists_for_Language
    16.5  #endif
    16.6  
    16.7 -#define makeAMeasHist( idx, name, numBins, startVal, binWidth ) \
    16.8 +#define makeAMeasHist( histInfo, idx, name, numBins, startVal, binWidth ) \
    16.9        makeHighestDynArrayIndexBeAtLeast( _PRTopEnv->measHistsInfo, idx ); \
   16.10        _PRTopEnv->measHists[idx] =  \
   16.11                         makeFixedBinHist( numBins, startVal, binWidth, name );
    17.1 --- a/Services_Offered_by_PR/Measurement_and_Stats/probes.c	Tue Feb 05 20:23:27 2013 -0800
    17.2 +++ b/Services_Offered_by_PR/Measurement_and_Stats/probes.c	Sat Mar 02 09:43:45 2013 -0800
    17.3 @@ -49,7 +49,7 @@
    17.4  IntervalProbe *
    17.5  create_generic_probe( char *nameStr, SlaveVP *animSlv )
    17.6   {
    17.7 -   PRServReq reqData;
    17.8 +   PRServiceReq reqData;
    17.9  
   17.10     reqData.reqType  = make_probe;
   17.11     reqData.nameStr  = nameStr;
   17.12 @@ -189,7 +189,7 @@
   17.13     probe = _PRTopEnv->intervalProbes[ probeID ];
   17.14     probe->schedChoiceWasRecorded = TRUE;
   17.15     probe->coreNum = animatingSlv->coreAnimatedBy;
   17.16 -   probe->slaveID = animatingSlv->slaveID;
   17.17 +   probe->slaveNum = animatingSlv->slaveNum;
   17.18     probe->slaveCreateSecs = animatingSlv->createPtInSecs;
   17.19   }
   17.20  
   17.21 @@ -265,8 +265,8 @@
   17.22     
   17.23     
   17.24     if( probe->schedChoiceWasRecorded )
   17.25 -    { printf( "coreNum: %d, slaveID: %d, slaveVPCreated: %0.6f | ",
   17.26 -              probe->coreNum, probe->slaveID, probe->slaveCreateSecs );
   17.27 +    { printf( "coreNum: %d, slaveNum: %d, slaveVPCreated: %0.6f | ",
   17.28 +              probe->coreNum, probe->slaveNum, probe->slaveCreateSecs );
   17.29      }
   17.30  
   17.31     if( probe->endSecs == 0 ) //just a single point in time
    18.1 --- a/Services_Offered_by_PR/Measurement_and_Stats/probes.h	Tue Feb 05 20:23:27 2013 -0800
    18.2 +++ b/Services_Offered_by_PR/Measurement_and_Stats/probes.h	Sat Mar 02 09:43:45 2013 -0800
    18.3 @@ -65,7 +65,7 @@
    18.4  
    18.5     int32           schedChoiceWasRecorded;
    18.6     int32           coreNum;
    18.7 -   int32           slaveID;
    18.8 +   int32           slaveNum;
    18.9     float64         slaveCreateSecs;
   18.10     PROBES__Insert_timestamps_and_intervals_into_probe_struct;
   18.11   };
    19.1 --- a/Services_Offered_by_PR/Memory_Handling/vmalloc.h	Tue Feb 05 20:23:27 2013 -0800
    19.2 +++ b/Services_Offered_by_PR/Memory_Handling/vmalloc.h	Sat Mar 02 09:43:45 2013 -0800
    19.3 @@ -54,24 +54,18 @@
    19.4  
    19.5  void *
    19.6  PR_int__malloc( size_t sizeRequested );
    19.7 -#define PR_PI__malloc  PR_int__malloc
    19.8 -#define PR_SS__malloc  PR_int__malloc
    19.9  
   19.10  void *
   19.11  PR_WL__malloc( int32  sizeRequested ); /*BUG: -- get master lock */
   19.12 -#define PR_App__malloc  PR_WL__malloc
   19.13  
   19.14  void *
   19.15  PR_int__malloc_aligned( size_t sizeRequested );
   19.16 -#define PR_PI__malloc_aligned PR_int__malloc_aligned
   19.17  
   19.18  void
   19.19  PR_int__free( void *ptrToFree );
   19.20 -#define PR_PI__free  PR_int__free
   19.21  
   19.22  void
   19.23  PR_WL__free( void *ptrToFree );
   19.24 -#define PR_App__free  PR_WL__free
   19.25  
   19.26  
   19.27  
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/Services_Offered_by_PR/Services_Language/Measurement/PRServ_Measurement.h	Sat Mar 02 09:43:45 2013 -0800
    20.3 @@ -0,0 +1,16 @@
    20.4 +/*
    20.5 + *  Copyright 2009 OpenSourceResearchInstitute.org
    20.6 + *  Licensed under GNU General Public License version 2
    20.7 + *
    20.8 + * Author: seanhalle@yahoo.com
    20.9 + *
   20.10 + */
   20.11 +
   20.12 +#ifndef _PRServ_MEAS_H
   20.13 +#define	_PRServ_MEAS_H
   20.14 +
   20.15 +
   20.16 +   #define MEAS__Make_Meas_Hists_for_PRServ
   20.17 +
   20.18 +#endif	/*  */
   20.19 +
    21.1 --- a/Services_Offered_by_PR/Services_Language/PRServ.c	Tue Feb 05 20:23:27 2013 -0800
    21.2 +++ b/Services_Offered_by_PR/Services_Language/PRServ.c	Sat Mar 02 09:43:45 2013 -0800
    21.3 @@ -4,6 +4,30 @@
    21.4   * Licensed under BSD
    21.5   */
    21.6  
    21.7 +//===========================================================================
    21.8 +//
    21.9 +//===========================================================================
   21.10 +/*These are the library functions *called in the application*
   21.11 + * 
   21.12 + *There's a pattern for the outside sequential code to interact with the
   21.13 + * PR_HW code.
   21.14 + *The PR_HW system is inside a boundary..  every PRServ system is in its
   21.15 + * own directory that contains the functions for each of the processor types.
   21.16 + * One of the processor types is the "seed" processor that starts the
   21.17 + * cascade of creating all the processors that do the work.
   21.18 + */
   21.19 +
   21.20 +
   21.21 +//===========================================================================
   21.22 +//
   21.23 +//===========================================================================
   21.24 +/*This file is for the built-in "services" or "utility" langlet, which starts
   21.25 + * automatically when a new process is created.  The seed VP initially runs
   21.26 + * within this langlet's environment.
   21.27 + */
   21.28 +
   21.29 +//===========================================================================
   21.30 +
   21.31  #include <stdio.h>
   21.32  #include <stdlib.h>
   21.33  #include <malloc.h>
   21.34 @@ -11,26 +35,19 @@
   21.35  #include "Queue_impl/PrivateQueue.h"
   21.36  #include "Hash_impl/PrivateHash.h"
   21.37  
   21.38 -#include "../../PR.h"
   21.39  #include "PRServ.h"
   21.40 +//#include "Measurement/PRServ_Counter_Recording.h"
   21.41  
   21.42  //==========================================================================
   21.43 +//=== prototypes for local helper functions
   21.44 +//=
   21.45  void
   21.46  PRServ__init_Helper();
   21.47 +
   21.48  //==========================================================================
   21.49  
   21.50  
   21.51  
   21.52 -//===========================================================================
   21.53 -
   21.54 -
   21.55 -/*These are the library functions *called in the application*
   21.56 - * 
   21.57 - */
   21.58 -
   21.59 -
   21.60 -//===========================================================================
   21.61 -
   21.62  int32
   21.63  PRServ__giveMinWorkUnitCycles( float32 percentOverhead )
   21.64   {
   21.65 @@ -53,12 +70,12 @@
   21.66   * saves jump point, and second jumps back several times to get reliable time
   21.67   */
   21.68  void
   21.69 -PRServ__begin_primitive()
   21.70 - { PRServSemData *semData;
   21.71 +PRServ__begin_primitive( SlaveVP *animSlv )
   21.72 + { PRServLangData *langData;
   21.73     
   21.74 -   semData = (PRServSemData *)PR_WL__give_sem_data( animSlv, PRServ_MAGIC_NUMBER);
   21.75 +   langData = (PRServLangData *)PR_WL__give_lang_data( animSlv, PRServ_MAGIC_NUMBER);
   21.76  
   21.77 -   saveLowTimeStampCountInto( semData->primitiveStartTime );
   21.78 +   saveLowTimeStampCountInto( langData->primitiveStartTime );
   21.79   }
   21.80  
   21.81  /*Just quick and dirty for now -- make reliable later
   21.82 @@ -67,251 +84,75 @@
   21.83   * also to throw out any "weird" values due to OS interrupt or TSC rollover
   21.84   */
   21.85  int32
   21.86 -PRServ__end_primitive_and_give_cycles( SlaveVP animSlv )
   21.87 +PRServ__end_primitive_and_give_cycles( SlaveVP *animSlv )
   21.88   { int32 endTime, startTime;
   21.89 -   PRServSemData *semData;
   21.90 +   PRServLangData *langData;
   21.91     
   21.92     //TODO: fix by repeating time-measurement
   21.93     saveLowTimeStampCountInto( endTime );
   21.94 -   semData = (PRServSemData *)PR_WL__give_sem_data( animSlv, PRServ_MAGIC_NUMBER);
   21.95 -   startTime = semData->primitiveStartTime;
   21.96 -   return (endTime - startTime - 2*TSC_LOW_CYCLES);
   21.97 +   langData = (PRServLangData *)PR_WL__give_lang_data( animSlv, PRServ_MAGIC_NUMBER);
   21.98 +   startTime = langData->primitiveStartTime;
   21.99 +   return (endTime - startTime);
  21.100   }
  21.101  
  21.102  
  21.103 -
  21.104 -//===========================================================================
  21.105 -
  21.106 -SlaveVP *
  21.107 -PRServ__create_thread( TopLevelFnPtr fnPtr,   void *initData,
  21.108 -                        SlaveVP *creatingThd )
  21.109 - { 
  21.110 -   return PRServ__create_thread_w_ID_and_affinity( fnPtr, initData, NO_ID,
  21.111 -                                                        ANY_CORE, creatingThd );
  21.112 +inline 
  21.113 +int32 *
  21.114 +PRServ__give_self_taskID( SlaveVP *animSlv )
  21.115 + {
  21.116 +   return PR__give_ID_from_slave( animSlv, PRServ_MAGIC_NUMBER );
  21.117   }
  21.118  
  21.119 -SlaveVP *
  21.120 -PRServ__create_thread_w_ID( TopLevelFnPtr fnPtr,   void *initData, int32 *thdID,
  21.121 -                         SlaveVP *creatingThd )
  21.122 - { 
  21.123 -   return PRServ__create_thread_w_ID_and_affinity( fnPtr, initData, thdID, 
  21.124 -                                                        ANY_CORE, creatingThd );
  21.125 +
  21.126 +/*
  21.127 + *This function returns information about the version of PR, the language
  21.128 + * the program is being run in, its version, and information on the 
  21.129 + * hardware.
  21.130 + */
  21.131 +char *
  21.132 +PRServ___give_environment_string()
  21.133 + { char *buffer = PR_WL__malloc(10000);
  21.134 +   int32 j;
  21.135 +   
  21.136 +   j = sizeof(int32);  //put total num chars here when done
  21.137 +   //--------------------------
  21.138 +   j += sprintf(buffer+j, "#\n# >> Build information <<\n");
  21.139 +   j += sprintf(buffer+j, "# GCC VERSION: %d.%d.%d\n",__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__);
  21.140 +   j += sprintf(buffer+j, "# Build Date: %s %s\n", __DATE__, __TIME__);
  21.141 +    
  21.142 +   j += sprintf(buffer+j, "#\n# >> Hardware information <<\n");
  21.143 +   j += sprintf(buffer+j, "# Hardware Architecture: ");
  21.144 +   #ifdef __x86_64
  21.145 +   j += sprintf(buffer+j, "x86_64");
  21.146 +   #endif //__x86_64
  21.147 +   #ifdef __i386
  21.148 +   j += sprintf(buffer+j, "x86");
  21.149 +   #endif //__i386
  21.150 +   j += sprintf(buffer+j, "\n");
  21.151 +   j += sprintf(buffer+j, "# Number of Cores: %d\n", NUM_CORES);
  21.152 +   //--------------------------
  21.153 +    
  21.154 +   //PR Plugins
  21.155 +   j += sprintf(buffer+j, "#\n# >> PR Plugins <<\n");
  21.156 +   j += sprintf(buffer+j, "# Language : ");
  21.157 +   j += sprintf(buffer+j, _LANG_NAME_);
  21.158 +   j += sprintf(buffer+j, "\n");
  21.159 +       //Meta info gets set by calls from the language during its init,
  21.160 +       // and info registered by calls from inside the application
  21.161 +   j += sprintf(buffer+j, "# Assigner: %s\n", _PRTopEnv->metaInfo->assignerInfo);
  21.162 +
  21.163 +   //--------------------------
  21.164 +   //Application
  21.165 +   j += sprintf(buffer+j, "#\n# >> Application <<\n");
  21.166 +   j += sprintf(buffer+j, "# Name: %s\n", _PRTopEnv->metaInfo->appInfo);
  21.167 +   j += sprintf(buffer+j, "# Data Set:\n%s\n",_PRTopEnv->metaInfo->inputInfo);
  21.168 +    
  21.169 +   ((int32 *)buffer)[0] = j - sizeof(int32); //insert the number of chars
  21.170 +   //--------------------------
  21.171 +   return (char *) &(((int32 *)buffer)[1]); //return pointer to first char
  21.172   }
  21.173  
  21.174  
  21.175 -SlaveVP *
  21.176 -PRServ__create_thread_w_ID_and_affinity( TopLevelFnPtr fnPtr,   void *initData, 
  21.177 -                    int32 *thdID, int32 coreToAssignOnto, SlaveVP *creatingThd )
  21.178 - { PRServSemReq reqData;
  21.179 -
  21.180 -      //the semantic request data is on the stack and disappears when this
  21.181 -      // call returns -- it's guaranteed to remain in the VP's stack for as
  21.182 -      // long as the VP is suspended.
  21.183 -   reqData.reqType            = create_slave; //know type because in a PR create req
  21.184 -   reqData.coreToAssignOnto   = coreToAssignOnto;
  21.185 -   
  21.186 -   PR_WL__send_create_slaveVP_req( &reqData, fnPtr, initData, thdID, 
  21.187 -                                                creatingThd, PRServ_MAGIC_NUMBER );
  21.188 -   return creatingThd->dataRetFromReq;
  21.189 - }
  21.190 -
  21.191 -/*This is always the last thing done in the code animated by a thread VP.
  21.192 - * Normally, this would be the last line of the thread's top level function.
  21.193 - * But, if the thread exits from any point, it has to do so by calling
  21.194 - * this.
  21.195 - *
  21.196 - *It simply sends a dissipate request, which handles all the state cleanup.
  21.197 - */
  21.198 -void
  21.199 -PRServ__end_thread( SlaveVP *thdToEnd )
  21.200 - {    
  21.201 -   PR_WL__send_dissipate_req( thdToEnd, PRServ_MAGIC_NUMBER );
  21.202 - }
  21.203 -
  21.204 -
  21.205 -
  21.206 -//===========================================================================
  21.207 -
  21.208 -
  21.209 -//======================= task submit and end ==============================
  21.210 -/*
  21.211 - */
  21.212 -void
  21.213 -PRServ__submit_task( PRServTaskType *taskType, void *args, SlaveVP *animSlv)
  21.214 - { PRServSemReq  reqData;
  21.215 -
  21.216 -   reqData.reqType    = submit_task;
  21.217 -   
  21.218 -   reqData.taskType   = taskType;
  21.219 -   reqData.args       = args;
  21.220 -   reqData.callingSlv = animSlv;
  21.221 -   
  21.222 -      //Create task is a special form, so have to pass as parameters, the
  21.223 -      // top-level-fn of task and the data for that fn, plus lang's req,
  21.224 -      // animating slave, and lang's magic number
  21.225 -   PR_WL__send_create_task_req( taskType->fn, args, &reqData, NO_ID, animSlv, PRServ_MAGIC_NUMBER );
  21.226 - }
  21.227 -
  21.228 -void
  21.229 -PRServ__submit_task_with_ID( PRServTaskType *taskType, void *args, int32 *taskID, 
  21.230 -                          SlaveVP     *animSlv)
  21.231 - { PRServSemReq  reqData;
  21.232 - 
  21.233 -   reqData.reqType    = submit_task;
  21.234 -   
  21.235 -   reqData.taskType   = taskType;
  21.236 -   reqData.args       = args;
  21.237 -   reqData.callingSlv = animSlv;
  21.238 - 
  21.239 -   PR_WL__send_create_task_req( taskType->fn, args, &reqData, taskID, animSlv, PRServ_MAGIC_NUMBER );
  21.240 - }
  21.241 -
  21.242 -
  21.243 -/*This call is the last to happen in every task.  It causes the slave to
  21.244 - * suspend and get the next task out of the task-queue.  Notice there is no
  21.245 - * assigner here.. only one slave, no slave ReadyQ, and so on..
  21.246 - *Can either make the assigner take the next task out of the taskQ, or can
  21.247 - * leave all as it is, and make task-end take the next task.
  21.248 - *Note: this fits the case in the new PR for no-context tasks, so will use
  21.249 - * the built-in taskQ of new PR, and should be local and much faster.
  21.250 - * 
  21.251 - *The task-stub is saved in the animSlv, so the request handler will get it
  21.252 - * from there, along with the task-type which has arg types, and so on..
  21.253 - * 
  21.254 - * NOTE: if want, don't need to send the animating SlaveVP around.. 
  21.255 - * instead, can make a single slave per core, and coreCtrlr looks up the
  21.256 - * slave from having the core number.
  21.257 - * 
  21.258 - *But, to stay compatible with all the other PR languages, leave it in..
  21.259 - */
  21.260 -void
  21.261 -PRServ__end_task( SlaveVP *animSlv )
  21.262 - { PRServSemReq  reqData;
  21.263 -
  21.264 -   reqData.reqType      = end_task;
  21.265 -   reqData.callingSlv   = animSlv;
  21.266 -   
  21.267 -   PR_WL__send_end_task_request( &reqData, animSlv, PRServ_MAGIC_NUMBER );
  21.268 - }
  21.269 -
  21.270 -
  21.271 -/*Waits for all tasks that are direct children to end, then resumes calling
  21.272 - * task or thread
  21.273 - */
  21.274 -void
  21.275 -PRServ__taskwait(SlaveVP *animSlv)
  21.276 - {
  21.277 -    PRServSemReq  reqData;
  21.278 -
  21.279 -   reqData.reqType      = taskwait;
  21.280 -   reqData.callingSlv   = animSlv;
  21.281 -   
  21.282 -   PR_WL__send_sem_request( &reqData, animSlv, PRServ_MAGIC_NUMBER );
  21.283 - }
  21.284 -
  21.285 -
  21.286 -
  21.287 -//==========================  send and receive ============================
  21.288 -//
  21.289 -
  21.290 -inline int32 *
  21.291 -PRServ__give_self_taskID( SlaveVP *animSlv )
  21.292 - {
  21.293 -   return PR__give_task_ID( animSlv, PRServ_MAGIC_NUMBER );
  21.294 - }
  21.295 -
  21.296 -//================================ send ===================================
  21.297 -
  21.298 -void
  21.299 -PRServ__send_of_type_to( void *msg, const int32 type, int32 *receiverID,
  21.300 -                      SlaveVP *senderSlv )
  21.301 - { PRServSemReq  reqData;
  21.302 -
  21.303 -   reqData.reqType    = send_type_to;
  21.304 -   
  21.305 -   reqData.msg        = msg;
  21.306 -   reqData.msgType    = type;
  21.307 -   reqData.receiverID = receiverID;
  21.308 -   reqData.senderSlv  = senderSlv;
  21.309 -   
  21.310 -   reqData.nextReqInHashEntry = NULL;
  21.311 -
  21.312 -   PR_WL__send_sem_request( &reqData, senderSlv, PRServ_MAGIC_NUMBER );
  21.313 -
  21.314 -      //When come back from suspend, no longer own data reachable from msg
  21.315 - }
  21.316 -
  21.317 -void
  21.318 -PRServ__send_from_to( void *msg, int32 *senderID, int32 *receiverID, SlaveVP *senderSlv )
  21.319 - { PRServSemReq  reqData;
  21.320 -
  21.321 -   reqData.reqType     = send_from_to;
  21.322 -   
  21.323 -   reqData.msg         = msg;
  21.324 -   reqData.senderID    = senderID;
  21.325 -   reqData.receiverID  = receiverID;
  21.326 -   reqData.senderSlv   = senderSlv;
  21.327 -
  21.328 -   reqData.nextReqInHashEntry = NULL;
  21.329 -
  21.330 -   PR_WL__send_sem_request( &reqData, senderSlv, PRServ_MAGIC_NUMBER );
  21.331 - }
  21.332 -
  21.333 -
  21.334 -//================================ receive ================================
  21.335 -
  21.336 -/*The "type" version of send and receive creates a many-to-one relationship.
  21.337 - * The sender is anonymous, and many sends can stack up, waiting to be
  21.338 - * received.  The same receiver can also have send from-to's
  21.339 - * waiting for it, and those will be kept separate from the "type"
  21.340 - * messages.
  21.341 - */
  21.342 -void *
  21.343 -PRServ__receive_type_to( const int32 type, int32* receiverID, SlaveVP *receiverSlv )
  21.344 - {       DEBUG__printf1(dbgRqstHdlr,"WL: receive type to %d",receiverID[1] );
  21.345 -   PRServSemReq  reqData;
  21.346 -
  21.347 -   reqData.reqType     = receive_type_to;
  21.348 -   
  21.349 -   reqData.msgType     = type;
  21.350 -   reqData.receiverID  = receiverID;
  21.351 -   reqData.receiverSlv = receiverSlv;
  21.352 -   
  21.353 -   reqData.nextReqInHashEntry = NULL;
  21.354 -
  21.355 -   PR_WL__send_sem_request( &reqData, receiverSlv, PRServ_MAGIC_NUMBER );
  21.356 -   
  21.357 -   return receiverSlv->dataRetFromReq;
  21.358 - }
  21.359 -
  21.360 -
  21.361 -
  21.362 -/*Call this at the point a receiving task wants in-coming data.
  21.363 - * Use this from-to form when know senderID -- it makes a direct channel
  21.364 - * between sender and receiver.
  21.365 - */
  21.366 -void *
  21.367 -PRServ__receive_from_to( int32 *senderID, int32 *receiverID, SlaveVP *receiverSlv )
  21.368 - { 
  21.369 -   PRServSemReq  reqData;
  21.370 -
  21.371 -   reqData.reqType     = receive_from_to;
  21.372 -
  21.373 -   reqData.senderID    = senderID;
  21.374 -   reqData.receiverID  = receiverID;
  21.375 -   reqData.receiverSlv = receiverSlv;
  21.376 -
  21.377 -   reqData.nextReqInHashEntry = NULL;
  21.378 -      DEBUG__printf2(dbgRqstHdlr,"WL: receive from %d to: %d", reqData.senderID[1], reqData.receiverID[1]);
  21.379 -      
  21.380 -   PR_WL__send_sem_request( &reqData, receiverSlv, PRServ_MAGIC_NUMBER );
  21.381 -
  21.382 -   return receiverSlv->dataRetFromReq;
  21.383 - }
  21.384 -
  21.385 -
  21.386 -
  21.387 -
  21.388  //==========================================================================
  21.389  //
  21.390  /*A function singleton is a function whose body executes exactly once, on a
  21.391 @@ -329,22 +170,24 @@
  21.392  void asm_write_ret_from_singleton(PRServSingleton *singletonPtrAddr);
  21.393  
  21.394  /*Fn singleton uses ID as index into array of singleton structs held in the
  21.395 - * semantic environment.
  21.396 + * language environment.
  21.397   */
  21.398  void
  21.399  PRServ__start_fn_singleton( int32 singletonID,   SlaveVP *animSlv )
  21.400   {
  21.401 -   PRServSemReq  reqData;
  21.402 +   PRServLangReq  reqData;
  21.403  
  21.404        //
  21.405 -   reqData.reqType     = singleton_fn_start;
  21.406 +   reqData.reqType     = prserv_singleton_fn_start;
  21.407     reqData.singletonID = singletonID;
  21.408  
  21.409 -   PR_WL__send_sem_request( &reqData, animSlv, PRServ_MAGIC_NUMBER );
  21.410 +   PR_WL__send_lang_request( &reqData, (RequestHandler)&PRServ__handleStartFnSingleton,
  21.411 +                             animSlv, PRServ_MAGIC_NUMBER );
  21.412     if( animSlv->dataRetFromReq ) //will be 0 or addr of label in end singleton
  21.413      {
  21.414 -       PRServSemEnv *semEnv = PR_WL__give_sem_env_for( animSlv, PRServ_MAGIC_NUMBER );
  21.415 -       asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID]));
  21.416 +      PRServLangEnv *langEnv =
  21.417 +              PR_int__give_lang_env_for_slave( animSlv, PRServ_MAGIC_NUMBER );
  21.418 +      asm_write_ret_from_singleton(&(langEnv->fnSingletons[ singletonID]));
  21.419      }
  21.420   }
  21.421  
  21.422 @@ -355,15 +198,16 @@
  21.423  void
  21.424  PRServ__start_data_singleton( PRServSingleton **singletonAddr,  SlaveVP *animSlv )
  21.425   {
  21.426 -   PRServSemReq  reqData;
  21.427 +   PRServLangReq  reqData;
  21.428  
  21.429     if( *singletonAddr && (*singletonAddr)->hasFinished )
  21.430         goto JmpToEndSingleton;
  21.431     
  21.432 -   reqData.reqType          = singleton_data_start;
  21.433 +   reqData.reqType          = prserv_singleton_data_start;
  21.434     reqData.singletonPtrAddr = singletonAddr;
  21.435  
  21.436 -   PR_WL__send_sem_request( &reqData, animSlv, PRServ_MAGIC_NUMBER );
  21.437 +   PR_WL__send_lang_request( &reqData, (RequestHandler)&PRServ__handleStartDataSingleton,
  21.438 +                             animSlv, PRServ_MAGIC_NUMBER );
  21.439     if( animSlv->dataRetFromReq ) //either 0 or end singleton's return addr
  21.440      {    //Assembly code changes the return addr on the stack to the one
  21.441           // saved into the singleton by the end-singleton-fn
  21.442 @@ -384,17 +228,20 @@
  21.443  void
  21.444  PRServ__end_fn_singleton( int32 singletonID, SlaveVP *animSlv )
  21.445   {
  21.446 -   PRServSemReq  reqData;
  21.447 +   PRServLangReq  reqData;
  21.448  
  21.449        //don't need this addr until after at least one singleton has reached
  21.450        // this function
  21.451 -   PRServSemEnv *semEnv = PR_WL__give_sem_env_for( animSlv, PRServ_MAGIC_NUMBER );
  21.452 -   asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID]));
  21.453 +   PRServLangEnv *
  21.454 +   langEnv = PR_int__give_lang_env_for_slave( animSlv, PRServ_MAGIC_NUMBER );
  21.455 +   
  21.456 +   asm_write_ret_from_singleton( &(langEnv->fnSingletons[ singletonID]) );
  21.457  
  21.458 -   reqData.reqType     = singleton_fn_end;
  21.459 +   reqData.reqType     = prserv_singleton_fn_end;
  21.460     reqData.singletonID = singletonID;
  21.461  
  21.462 -   PR_WL__send_sem_request( &reqData, animSlv, PRServ_MAGIC_NUMBER );
  21.463 +   PR_WL__send_lang_request( &reqData, (RequestHandler)&PRServ__handleEndFnSingleton, 
  21.464 +                             animSlv, PRServ_MAGIC_NUMBER );
  21.465  
  21.466  EndSingletonInstrAddr:
  21.467     return;
  21.468 @@ -403,7 +250,7 @@
  21.469  void
  21.470  PRServ__end_data_singleton(  PRServSingleton **singletonPtrAddr, SlaveVP *animSlv )
  21.471   {
  21.472 -   PRServSemReq  reqData;
  21.473 +   PRServLangReq  reqData;
  21.474  
  21.475        //don't need this addr until after singleton struct has reached
  21.476        // this function for first time
  21.477 @@ -413,10 +260,11 @@
  21.478        // function in different places for different data-singletons.
  21.479     asm_save_ret_to_singleton(*singletonPtrAddr);
  21.480  
  21.481 -   reqData.reqType          = singleton_data_end;
  21.482 +   reqData.reqType          = prserv_singleton_data_end;
  21.483     reqData.singletonPtrAddr = singletonPtrAddr;
  21.484  
  21.485 -   PR_WL__send_sem_request( &reqData, animSlv, PRServ_MAGIC_NUMBER );
  21.486 +   PR_WL__send_lang_request( &reqData, (RequestHandler)&PRServ__handleEndDataSingleton,
  21.487 +                             animSlv, PRServ_MAGIC_NUMBER );
  21.488   }
  21.489  
  21.490  /*This executes the function in the masterVP, so it executes in isolation
  21.491 @@ -433,14 +281,15 @@
  21.492  PRServ__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
  21.493                                      void *data, SlaveVP *animSlv )
  21.494   {
  21.495 -   PRServSemReq  reqData;
  21.496 +   PRServLangReq  reqData;
  21.497  
  21.498        //
  21.499 -   reqData.reqType          = atomic;
  21.500 +   reqData.reqType          = prserv_atomic;
  21.501     reqData.fnToExecInMaster = ptrToFnToExecInMaster;
  21.502     reqData.dataForFn        = data;
  21.503  
  21.504 -   PR_WL__send_sem_request( &reqData, animSlv, PRServ_MAGIC_NUMBER );
  21.505 +   PR_WL__send_lang_request( &reqData, (RequestHandler)&PRServ__handleAtomic, 
  21.506 +                             animSlv, PRServ_MAGIC_NUMBER );
  21.507   }
  21.508  
  21.509  
  21.510 @@ -460,14 +309,15 @@
  21.511  void
  21.512  PRServ__start_transaction( int32 transactionID, SlaveVP *animSlv )
  21.513   {
  21.514 -   PRServSemReq  reqData;
  21.515 +   PRServLangReq  reqData;
  21.516  
  21.517        //
  21.518     reqData.callingSlv  = animSlv;
  21.519 -   reqData.reqType     = trans_start;
  21.520 +   reqData.reqType     = prserv_trans_start;
  21.521     reqData.transID     = transactionID;
  21.522  
  21.523 -   PR_WL__send_sem_request( &reqData, animSlv, PRServ_MAGIC_NUMBER );
  21.524 +   PR_WL__send_lang_request( &reqData, (RequestHandler)&PRServ__handleTransStart,
  21.525 +                             animSlv, PRServ_MAGIC_NUMBER );
  21.526   }
  21.527  
  21.528  /*This suspends to the master, then uses transactionID as index into an
  21.529 @@ -482,36 +332,16 @@
  21.530  void
  21.531  PRServ__end_transaction( int32 transactionID, SlaveVP *animSlv )
  21.532   {
  21.533 -   PRServSemReq  reqData;
  21.534 +   PRServLangReq  reqData;
  21.535  
  21.536        //
  21.537     reqData.callingSlv      = animSlv;
  21.538 -   reqData.reqType     = trans_end;
  21.539 +   reqData.reqType     = prserv_trans_end;
  21.540     reqData.transID     = transactionID;
  21.541  
  21.542 -   PR_WL__send_sem_request( &reqData, animSlv, PRServ_MAGIC_NUMBER );
  21.543 +   PR_WL__send_lang_request( &reqData, (RequestHandler)&PRServ__handleTransEnd,
  21.544 +                             animSlv, PRServ_MAGIC_NUMBER );
  21.545   }
  21.546  
  21.547  //======================== Internal ==================================
  21.548 -/*
  21.549 - */
  21.550  
  21.551 -SlaveVP *
  21.552 -PRServ__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData,
  21.553 -                        SlaveVP *creatingSlv,  int32  coreToAssignOnto )
  21.554 - { PRServSemReq  reqData;
  21.555 -
  21.556 -      //the semantic request data is on the stack and disappears when this
  21.557 -      // call returns -- it's guaranteed to remain in the VP's stack for as
  21.558 -      // long as the VP is suspended.
  21.559 -   reqData.reqType            = create_slave_w_aff; //not used, May 2012
  21.560 -   reqData.coreToAssignOnto   = coreToAssignOnto;
  21.561 -   reqData.fnPtr              = fnPtr;
  21.562 -   reqData.initData           = initData;
  21.563 -   reqData.callingSlv         = creatingSlv;
  21.564 -
  21.565 -   PR_WL__send_create_slaveVP_req( &reqData, creatingSlv, PRServ_MAGIC_NUMBER );
  21.566 -
  21.567 -   return creatingSlv->dataRetFromReq;
  21.568 - }
  21.569 -
    22.1 --- a/Services_Offered_by_PR/Services_Language/PRServ.h	Tue Feb 05 20:23:27 2013 -0800
    22.2 +++ b/Services_Offered_by_PR/Services_Language/PRServ.h	Sat Mar 02 09:43:45 2013 -0800
    22.3 @@ -1,93 +1,105 @@
    22.4  /*
    22.5 - *  Copyright 2009 OpenSourceStewardshipFoundation.org
    22.6 + *  Copyright 2009 OpenSourceResearchInstitute.org
    22.7   *  Licensed under GNU General Public License version 2
    22.8   *
    22.9   * Author: seanhalle@yahoo.com
   22.10   *
   22.11   */
   22.12  
   22.13 +#ifndef _PRServ_H
   22.14 +#define	_PRServ_H
   22.15  
   22.16  #include "Queue_impl/PrivateQueue.h"
   22.17  #include "Hash_impl/PrivateHash.h"
   22.18 -//#include "../Measurement_and_Stats/"
   22.19 -
   22.20 -#ifndef _PRServ_H
   22.21 -#define	_PRServ_H
   22.22 +#include "PR_impl/PR.h"
   22.23  
   22.24  
   22.25  //===========================================================================
   22.26 -   //uniquely identifies PRServ -- should be a jenkins char-hash of "PRServ" onto int32
   22.27 -#define PRServ_MAGIC_NUMBER 0000000002
   22.28 +   //uniquely identifies PRServ -- should be a jenkins char-hash of "PRServ" to int32
   22.29 +#define PRServ_MAGIC_NUMBER 0000000001
   22.30  
   22.31 -#define NUM_STRUCS_IN_SEM_ENV 1000
   22.32 +#define NUM_STRUCS_IN_LANG_ENV 1000
   22.33  
   22.34 +   //This is hardware dependent -- it's the number of cycles of scheduling
   22.35 +   // overhead -- if a work unit is fewer than this, it is better being
   22.36 +   // combined sequentially with other work
   22.37 +   //This value depends on both PR overhead and PRServ's plugin.  At some point
   22.38 +   // it will be derived by perf-counter measurements during init of PRServ
   22.39 +#define MIN_WORK_UNIT_CYCLES 20000
   22.40  
   22.41  //===========================================================================
   22.42  /*This header defines everything specific to the PRServ semantic plug-in
   22.43   */
   22.44 -typedef struct _PRServSemReq    PRServSemReq;
   22.45 -//typedef struct _PRServTaskStub  PRServTaskStub;
   22.46 -//typedef void  (*PRServTaskFnPtr )   ( void *, SlaveVP *);
   22.47 -//typedef void  (*PtrToAtomicFn )  ( void * ); //executed atomically in master
   22.48 +typedef struct _PRServLangReq    PRServLangReq;
   22.49 +typedef void  (*PtrToAtomicFn )  ( void * ); //executed atomically in master
   22.50  //===========================================================================
   22.51  
   22.52 -
   22.53  //===========================================================================
   22.54  
   22.55 -/*This is placed into semData, used for dependencies and wait construct*/
   22.56 -struct _PRServTaskStub
   22.57 +/*Semantic layer-specific data sent inside a request from lib called in app
   22.58 + * to request handler called in AnimationMaster
   22.59 + */
   22.60 +
   22.61 +typedef struct
   22.62   {
   22.63 - //====== The first fields must match PRLangMetaTask fields ======
   22.64 -   int32             langMagicNumber; //magic num must be 1st field of langMetaTask
   22.65 -   PRMetaTask       *protoMetaTask;   //back-link must always be 2nd field
   22.66 - //====== end PRLangMetaTask fields =========
   22.67 - 
   22.68 +   SlaveVP      *VPCurrentlyExecuting;
   22.69 +   PrivQueueStruc *waitingVPQ;
   22.70 + }
   22.71 +PRServTrans;
   22.72 +
   22.73 +/*WARNING: assembly hard-codes position of endInstrAddr as first field
   22.74 + */
   22.75 +typedef struct
   22.76 + {
   22.77 +   void           *endInstrAddr;
   22.78 +   int32           hasBeenStarted;
   22.79 +   int32           hasFinished;
   22.80 +   PrivQueueStruc *waitQ;
   22.81 + }
   22.82 +PRServSingleton;
   22.83 +
   22.84 +/*Note: may not need this anymore -- switched to embedding pointer to handler*/
   22.85 +enum PRServLangReqType
   22.86 + {
   22.87 +   prserv_malloc_req = 1,
   22.88 +   prserv_free_req,
   22.89 +   prserv_singleton_fn_start,
   22.90 +   prserv_singleton_fn_end,
   22.91 +   prserv_singleton_data_start,
   22.92 +   prserv_singleton_data_end,
   22.93 +   prserv_atomic,
   22.94 +   prserv_trans_start,
   22.95 +   prserv_trans_end
   22.96   };
   22.97  
   22.98 +struct _PRServLangReq
   22.99 + { enum PRServLangReqType    reqType;
  22.100 +   SlaveVP           *callingSlv;
  22.101  
  22.102 -struct _PRServSemReq
  22.103 - { enum PRServReqType    reqType;
  22.104 -   SlaveVP           *callingSlv;
  22.105 -   void              *args;
  22.106 -//   PRServTaskStub       *taskStub;  //not needed -- get via PR accessor from slv
  22.107 -   
  22.108 -   SlaveVP           *senderSlv;
  22.109 -   SlaveVP           *receiverSlv;
  22.110 -   int32             *senderID;
  22.111 -   int32             *receiverID;
  22.112 -   int32              msgType;
  22.113 -   void              *msg;
  22.114 -   PRServSemReq         *nextReqInHashEntry;
  22.115 -//In PRReq:   int32             *taskID;
  22.116 -   
  22.117 -   TopLevelFnPtr      fnPtr;
  22.118 -   void              *initData;
  22.119 -   int32              coreToAssignOnto;
  22.120 -
  22.121 -//These, below, should move to util language..
  22.122     int32              sizeToMalloc;
  22.123     void              *ptrToFree;
  22.124  
  22.125     int32              singletonID;
  22.126 +   PRServSingleton     **singletonPtrAddr;
  22.127  
  22.128 +   PtrToAtomicFn      fnToExecInMaster;
  22.129     void              *dataForFn;
  22.130  
  22.131     int32              transID;
  22.132   }
  22.133 -/* PRServSemReq */;
  22.134 +/* PRServLangReq */;
  22.135  
  22.136  
  22.137  typedef struct
  22.138 - { PRLangEnv       *protoLangEnv;
  22.139 + { 
  22.140     PrivQueueStruc  *slavesReadyToResumeQ; //Shared (slaves not pinned)
  22.141 -   PrivQueueStruc  *freeTaskSlvRecycleQ;    //Shared
  22.142 -   PrivQueueStruc  *taskReadyQ;           //Shared (tasks not pinned)
  22.143 -   HashTable       *argPtrHashTbl;
  22.144 -   HashTable       *commHashTbl;
  22.145 -   int32            nextCoreToGetNewSlv;
  22.146 +   PrivQueueStruc  *taskReadyQ;           //will never be used in seed langlet
  22.147 +   
  22.148     int32            primitiveStartTime;
  22.149  
  22.150                         //fix limit on num with dynArray
  22.151 +   PRServSingleton     fnSingletons[NUM_STRUCS_IN_LANG_ENV];
  22.152 +   PRServTrans         transactionStrucs[NUM_STRUCS_IN_LANG_ENV];
  22.153     
  22.154     #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  22.155     ListOfArrays* unitList;
  22.156 @@ -104,33 +116,24 @@
  22.157     ListOfArrays* counterList[NUM_CORES];
  22.158     #endif
  22.159   }
  22.160 -PRServSemEnv;
  22.161 +PRServLangEnv;
  22.162  
  22.163  
  22.164 -typedef struct _TransListElem TransListElem;
  22.165 -struct _TransListElem
  22.166 +typedef struct _PRServTransListElem PRServTransListElem;
  22.167 +struct _PRServTransListElem
  22.168   {
  22.169     int32          transID;
  22.170 -   TransListElem *nextTrans;
  22.171 +   PRServTransListElem *nextTrans;
  22.172   };
  22.173  //TransListElem
  22.174   
  22.175 -/* PR now handles what this used to be used for
  22.176 -enum PRServSlvType
  22.177 - { FreeTaskSlv = 1,
  22.178 -   SlotTaskSlv,
  22.179 -   ThreadSlv
  22.180 - };
  22.181 -*/
  22.182 - 
  22.183  typedef struct
  22.184   {
  22.185     int32            highestTransEntered;
  22.186 -   TransListElem   *lastTransEntered;
  22.187 +   PRServTransListElem   *lastTransEntered;
  22.188     int32            primitiveStartTime;
  22.189 -//   PRServTaskStub     *taskStub; //get from slave via PR accessor
  22.190   }
  22.191 -PRServSemData;
  22.192 +PRServLangData;
  22.193   
  22.194  //===========================================================================
  22.195  
  22.196 @@ -149,36 +152,66 @@
  22.197  int32
  22.198  PRServ__give_number_of_cores_to_schedule_onto();
  22.199  
  22.200 +char *
  22.201 +PRServ___give_environment_string();
  22.202 +
  22.203  //=======================
  22.204  
  22.205 -void
  22.206 +PRServLangEnv *
  22.207  PRServ__start( SlaveVP *seedSlv );
  22.208  
  22.209  void
  22.210 -PRServ__cleanup_after_shutdown();
  22.211 +PRServ__end();
  22.212  
  22.213 -//=======================
  22.214  void
  22.215 -PRServ__resume_slaveVP( SlaveVP *seedSlv, PRServLangEnv *servicesLangEnv );
  22.216 -
  22.217 +PRServ__end_seedVP( SlaveVP *seedSlv );
  22.218  //=======================
  22.219  
  22.220 -#define PRServ__malloc( numBytes, callingSlave ) PR_App__malloc( numBytes, callingSlave)
  22.221 -
  22.222 -#define PRServ__free(ptrToFree, callingSlave ) PR_App__free( ptrToFree, callingSlave )
  22.223 -
  22.224 -
  22.225 -//=======================
  22.226 +inline int32 *
  22.227 +PRServ__create_taskID_of_size( int32 numInts, SlaveVP *animSlv );
  22.228  
  22.229  //=========================
  22.230 +void
  22.231 +PRServ__taskwait(SlaveVP *animSlv);
  22.232 +
  22.233 +inline int32 *
  22.234 +PRServ__give_self_taskID( SlaveVP *animSlv );
  22.235 +
  22.236 +//======================= Concurrency Stuff ======================
  22.237 +void
  22.238 +PRServ__start_fn_singleton( int32 singletonID, SlaveVP *animSlv );
  22.239 +
  22.240 +void
  22.241 +PRServ__end_fn_singleton( int32 singletonID, SlaveVP *animSlv );
  22.242 +
  22.243 +void
  22.244 +PRServ__start_data_singleton( PRServSingleton **singeltonAddr, SlaveVP *animSlv );
  22.245 +
  22.246 +void
  22.247 +PRServ__end_data_singleton( PRServSingleton **singletonAddr, SlaveVP *animSlv );
  22.248 +
  22.249 +void
  22.250 +PRServ__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
  22.251 +                                    void *data, SlaveVP *animSlv );
  22.252 +
  22.253 +void
  22.254 +PRServ__start_transaction( int32 transactionID, SlaveVP *animSlv );
  22.255 +
  22.256 +void
  22.257 +PRServ__end_transaction( int32 transactionID, SlaveVP *animSlv );
  22.258  
  22.259  
  22.260  //=========================  Internal use only  =============================
  22.261  
  22.262 -SlaveVP *
  22.263 -PRServ__assign_work_to_slot( void *_semEnv, AnimSlot *slot );
  22.264 +bool32
  22.265 +PRServ__assign_work_to_slot( void *_langEnv, AnimSlot *slot );
  22.266 +
  22.267 +//=====================    =====================
  22.268 +
  22.269 +#include "PRServ_Request_Handlers.h"
  22.270  
  22.271  //=====================  Measurement of Lang Overheads  =====================
  22.272 +#include "Measurement/PRServ_Measurement.h"
  22.273  
  22.274  //===========================================================================
  22.275  #endif	/* _PRServ_H */
    23.1 --- a/Services_Offered_by_PR/Services_Language/PRServ_PluginFns.c	Tue Feb 05 20:23:27 2013 -0800
    23.2 +++ b/Services_Offered_by_PR/Services_Language/PRServ_PluginFns.c	Sat Mar 02 09:43:45 2013 -0800
    23.3 @@ -12,17 +12,6 @@
    23.4  #include "PRServ_Request_Handlers.h"
    23.5  
    23.6  //=========================== Local Fn Prototypes ===========================
    23.7 -void
    23.8 -resume_slaveVP( SlaveVP *slave, PRServSemEnv *semEnv );
    23.9 -
   23.10 -inline void
   23.11 -handleSemReq( PRReqst *req, SlaveVP *requestingSlv, PRServSemEnv *semEnv );
   23.12 -
   23.13 -inline void
   23.14 -handleDissipate(                SlaveVP *requestingSlv, PRServSemEnv *semEnv );
   23.15 -
   23.16 -inline void
   23.17 -handleCreate(    PRReqst *req, SlaveVP *requestingSlv, PRServSemEnv *semEnv );
   23.18  
   23.19  //============================== Assigner ==================================
   23.20  //
   23.21 @@ -51,161 +40,91 @@
   23.22   * to suspend both kinds, but also to keep explicit slave stacks clean from
   23.23   * the junk tasks are allowed to leave behind.
   23.24   */
   23.25 -SlaveVP *
   23.26 -PRServ__assign_work_to_slot( void *_semEnv, AnimSlot *slot )
   23.27 +bool32
   23.28 +PRServ__assign_work_to_slot( void *_langEnv, AnimSlot *slot )
   23.29   { SlaveVP     *returnSlv;
   23.30 -   PRServSemEnv   *semEnv;
   23.31 +   PRServLangEnv  *langEnv;
   23.32     int32        coreNum, slotNum;
   23.33 -   PRMetaTask  *returnMetaTask = NULL, *newTaskStub;
   23.34    
   23.35     coreNum = slot->coreSlotIsOn;
   23.36     slotNum = slot->slotIdx;
   23.37     
   23.38 -   semEnv  = (PRServSemEnv *)_semEnv;
   23.39 +   langEnv = (PRServLangEnv *)_langEnv;
   23.40     
   23.41        //Check for suspended slaves that are ready to resume
   23.42 -   returnSlv = readPrivQ( semEnv->slavesReadyToResumeQ );
   23.43 +   returnSlv = readPrivQ( langEnv->slavesReadyToResumeQ );
   23.44     if( returnSlv != NULL )  //Yes, have a slave, so return it.
   23.45      { returnSlv->coreAnimatedBy   = coreNum;
   23.46 -      returnMetaTask = returnSlv->metaTasks;
   23.47 -      goto ReturnTheMetaTask;
   23.48 +      
   23.49 +      //PR calls this Fn, which in turn uses PR's primitive to assign
   23.50 +      // a slave to a slot.
   23.51 +      //Note: this represents a security risk, if langlet has a bug and gives
   23.52 +      // the wrong slot.. assuming will have a tool in future that analyzes
   23.53 +      // plugin code before certifying it..
   23.54 +      PR_int__put_slave_into_slot( returnSlv, slot );
   23.55 +      goto Success;
   23.56      }
   23.57     
   23.58 -   newTaskStub = readPrivQ( semEnv->taskReadyQ );
   23.59 -   if( newTaskStub != NULL )
   23.60 -    { returnMetaTask = newTaskStub->protoMetaTask;
   23.61 -      goto ReturnTheMetaTask;
   23.62 -    }
   23.63 +   
   23.64 +   //If here, didn't assign any work
   23.65 + Fail:
   23.66 +   return FALSE;
   23.67 +   //fixme; //figure out what to do -- go through holistic code still?
   23.68  
   23.69 -ReturnTheMetaTask:  //doing gotos to here should help with holistic..
   23.70 + Success:  //doing gotos to here should help with holistic..
   23.71  
   23.72     #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   23.73     //This no longer works -- should be moved into PR in master
   23.74     //This assumes the task has already been assigned to a slave, which happens
   23.75     // inside Master..
   23.76     if( returnMetaTask == NULL )
   23.77 -    { returnSlv = semEnv->process->idleSlv[coreNum][slotNum]; 
   23.78 +    { returnSlv = langEnv->process->idleSlv[coreNum][slotNum]; 
   23.79      
   23.80           //things that would normally happen in resume(), but these VPs
   23.81           // never go there
   23.82        returnSlv->numTimesAssignedToASlot++;
   23.83        Unit newU;
   23.84 -      newU.vp = returnSlv->slaveID;
   23.85 +      newU.vp = returnSlv->slaveNum;
   23.86        newU.task = returnSlv->numTimesAssignedToASlot;
   23.87 -      addToListOfArrays(Unit,newU,semEnv->unitList);
   23.88 +      addToListOfArrays(Unit,newU,langEnv->unitList);
   23.89  
   23.90        if (returnSlv->numTimesAssignedToASlot > 1)
   23.91         { Dependency newD;
   23.92 -         newD.from_vp = returnSlv->slaveID;
   23.93 +         newD.from_vp = returnSlv->slaveNum;
   23.94           newD.from_task = returnSlv->numTimesAssignedToASlot - 1;
   23.95 -         newD.to_vp = returnSlv->slaveID;
   23.96 +         newD.to_vp = returnSlv->slaveNum;
   23.97           newD.to_task = returnSlv->numTimesAssignedToASlot;
   23.98 -         addToListOfArrays(Dependency, newD, semEnv->ctlDependenciesList);  
   23.99 +         addToListOfArrays(Dependency, newD, langEnv->ctlDependenciesList);  
  23.100         }
  23.101        returnMetaTask = returnSlv->metaTasks;
  23.102      }
  23.103     else //returnSlv != NULL
  23.104      { //assignSlv->numTimesAssigned++;
  23.105        Unit prev_in_slot = 
  23.106 -         semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum];
  23.107 +         langEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum];
  23.108        if(prev_in_slot.vp != 0)
  23.109         { Dependency newD;
  23.110           newD.from_vp = prev_in_slot.vp;
  23.111           newD.from_task = prev_in_slot.task;
  23.112 -         newD.to_vp = returnSlv->slaveID;
  23.113 +         newD.to_vp = returnSlv->slaveNum;
  23.114           newD.to_task = returnSlv->numTimesAssignedToASlot;
  23.115 -         addToListOfArrays(Dependency,newD,semEnv->hwArcs);   
  23.116 +         addToListOfArrays(Dependency,newD,langEnv->hwArcs);   
  23.117         }
  23.118 -      prev_in_slot.vp = returnSlv->slaveID;
  23.119 +      prev_in_slot.vp = returnSlv->slaveNum;
  23.120        prev_in_slot.task = returnSlv->numTimesAssignedToASlot;
  23.121 -      semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum] =
  23.122 +      langEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum] =
  23.123           prev_in_slot;        
  23.124      }
  23.125     #endif
  23.126 -   return( returnMetaTask );
  23.127 +/* PR handles work available in lang env and in process..
  23.128 +   if( isEmptyPrivQ(langEnv->slavesReadyToResumeQ) &&
  23.129 +       isEmptyPrivQ(langEnv->taskReadyQ) ) 
  23.130 +      PR_int__clear_work_in_lang_env(langEnv);
  23.131 + */
  23.132 + 
  23.133 +   return TRUE;
  23.134   }
  23.135  
  23.136  
  23.137 -//===========================  Request Handler  ============================
  23.138 -//
  23.139 -/*
  23.140 - * (Not inline because invoked indirectly via a pointer)
  23.141 - */
  23.142 -
  23.143 -void
  23.144 -handleSemReq( PRReqst *req, SlaveVP *reqSlv, PRServSemEnv *semEnv )
  23.145 - { PRServSemReq *semReq;
  23.146 -
  23.147 -   semReq = PR_PI__take_sem_reqst_from(req);
  23.148 -   if( semReq == NULL ) return;
  23.149 -   switch( semReq->reqType )  //sem handlers are all in other file
  23.150 -    {
  23.151 -      case send_type_to:    handleSendTypeTo(   semReq,         semEnv);
  23.152 -         break;
  23.153 -      case send_from_to:    handleSendFromTo(   semReq,         semEnv);
  23.154 -         break;
  23.155 -      case receive_type_to: handleReceiveTypeTo(semReq,         semEnv);
  23.156 -         break;
  23.157 -      case receive_from_to: handleReceiveFromTo(semReq,         semEnv);
  23.158 -         break;
  23.159 -      case taskwait:        handleTaskwait(     semReq, reqSlv, semEnv);
  23.160 -           break;
  23.161 -         
  23.162 -      //====================================================================
  23.163 -      case malloc_req:      handleMalloc(       semReq, reqSlv, semEnv);
  23.164 -         break;
  23.165 -      case free_req:        handleFree(         semReq, reqSlv, semEnv);
  23.166 -         break;
  23.167 -      case singleton_fn_start:  handleStartFnSingleton(semReq, reqSlv, semEnv);
  23.168 -         break;
  23.169 -      case singleton_fn_end:    handleEndFnSingleton(  semReq, reqSlv, semEnv);
  23.170 -         break;
  23.171 -      case singleton_data_start:handleStartDataSingleton(semReq,reqSlv,semEnv);
  23.172 -         break;
  23.173 -      case singleton_data_end:  handleEndDataSingleton(semReq, reqSlv, semEnv);
  23.174 -         break;
  23.175 -      case atomic:          handleAtomic(       semReq, reqSlv, semEnv);
  23.176 -         break;
  23.177 -      case trans_start:     handleTransStart(   semReq, reqSlv, semEnv);
  23.178 -         break;
  23.179 -      case trans_end:       handleTransEnd(     semReq, reqSlv, semEnv);
  23.180 -         break;
  23.181 -    }
  23.182 - }
  23.183 -
  23.184 -
  23.185 -
  23.186  
  23.187  //=========================== Helper ==============================
  23.188 -void
  23.189 -resume_slaveVP( SlaveVP *slave, PRServSemEnv *semEnv )
  23.190 - {
  23.191 -      //both suspended tasks and suspended explicit slaves resumed with this
  23.192 -   writePrivQ( slave, semEnv->slavesReadyToResumeQ );
  23.193 -   if( semEnv->protoSemEnv->hasWork != TRUE ) 
  23.194 -       semEnv->protoSemEnv->hasWork = TRUE;
  23.195 -   
  23.196 -   #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS
  23.197 -/*
  23.198 -   int lastRecordIdx = slave->counter_history_array_info->numInArray -1;
  23.199 -   CounterRecord* lastRecord = slave->counter_history[lastRecordIdx];
  23.200 -   saveLowTimeStampCountInto(lastRecord->unblocked_timestamp);
  23.201 -*/
  23.202 -   #endif
  23.203 -   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  23.204 -   slave->numTimesAssignedToASlot++; //Somewhere here!
  23.205 -   Unit newU;
  23.206 -   newU.vp = slave->slaveID;
  23.207 -   newU.task = slave->numTimesAssignedToASlot;
  23.208 -   addToListOfArrays(Unit,newU,semEnv->unitList);
  23.209 -   
  23.210 -   if (slave->numTimesAssignedToASlot > 1)
  23.211 -    { Dependency newD;
  23.212 -      newD.from_vp = slave->slaveID;
  23.213 -      newD.from_task = slave->numTimesAssignedToASlot - 1;
  23.214 -      newD.to_vp = slave->slaveID;
  23.215 -      newD.to_task = slave->numTimesAssignedToASlot;
  23.216 -      addToListOfArrays(Dependency, newD ,semEnv->ctlDependenciesList);  
  23.217 -    }
  23.218 -   #endif
  23.219 - }
    24.1 --- a/Services_Offered_by_PR/Services_Language/PRServ_Request_Handlers.c	Tue Feb 05 20:23:27 2013 -0800
    24.2 +++ b/Services_Offered_by_PR/Services_Language/PRServ_Request_Handlers.c	Sat Mar 02 09:43:45 2013 -0800
    24.3 @@ -17,1048 +17,30 @@
    24.4  
    24.5  
    24.6  //=========================== Local Fn Prototypes ===========================
    24.7 -void
    24.8 -resume_slaveVP( SlaveVP *slave, PRServSemEnv *semEnv );
    24.9 -
   24.10 -
   24.11 -
   24.12 -//==========================================================================
   24.13 -//                           Helpers
   24.14 -//
   24.15 -
   24.16 -/*Only clone the elements of req used in these reqst handlers
   24.17 - */
   24.18 -PRServSemReq *
   24.19 -cloneReq( PRServSemReq *semReq )
   24.20 - { PRServSemReq *clonedReq;
   24.21 -
   24.22 -   clonedReq             = PR_PI__malloc( sizeof(PRServSemReq) );
   24.23 -   clonedReq->reqType    = semReq->reqType;
   24.24 -   clonedReq->senderSlv  = semReq->senderSlv;
   24.25 -   clonedReq->receiverSlv= semReq->receiverSlv;
   24.26 -   clonedReq->msg        = semReq->msg;
   24.27 -   clonedReq->nextReqInHashEntry = NULL;
   24.28 -   
   24.29 -   return clonedReq;
   24.30 - }
   24.31 -
   24.32 -
   24.33 -
   24.34 -HashEntry *
   24.35 -giveEntryElseInsertReqst32( int32 *key, PRServSemReq *semReq,
   24.36 -                            HashTable   *commHashTbl )
   24.37 - { HashEntry    *entry;
   24.38 -   PRServSemReq    *waitingReq;
   24.39 -
   24.40 -   entry = getEntryFromTable32( key, commHashTbl );
   24.41 -   if( entry == NULL )
   24.42 -    {    //no waiting sends or receives, so add this request and exit
   24.43 -         // note: have to clone the request because it's on stack of sender
   24.44 -      addValueIntoTable32( key, cloneReq( semReq ), commHashTbl );
   24.45 -      return NULL;
   24.46 -    }
   24.47 -   waitingReq = (PRServSemReq *)entry->content;
   24.48 -   if( waitingReq == NULL )  //might happen when last waiting gets paired
   24.49 -    {    //no waiting sends or receives, so add this request and exit
   24.50 -      entry->content = semReq;
   24.51 -      return NULL;
   24.52 -    }
   24.53 -   return entry;
   24.54 - }
   24.55 -
   24.56 -      
   24.57 -inline PRServPointerEntry *
   24.58 -create_pointer_entry( )
   24.59 - { PRServPointerEntry *newEntry;
   24.60 -   
   24.61 -   newEntry = PR_PI__malloc( sizeof(PRServPointerEntry) );
   24.62 -   newEntry->hasEnabledNonFinishedWriter = FALSE;
   24.63 -   newEntry->numEnabledNonDoneReaders    = 0;
   24.64 -   newEntry->waitersQ                    = makePrivQ();
   24.65 -      
   24.66 -   return newEntry;
   24.67 - }
   24.68 -
   24.69 -/*malloc's space and initializes fields -- and COPIES the arg values
   24.70 - * to new space
   24.71 - */
   24.72 -inline PRServTaskStub *
   24.73 -create_task_stub( PRServTaskType *taskType, void **args )
   24.74 - { void **newArgs;
   24.75 -   PRServTaskStub* newStub = PR_int__malloc( sizeof(PRMetaTask) + taskType->sizeOfArgs );
   24.76 -   newStub->numBlockingProp = taskType->numCtldArgs;
   24.77 -   newStub->taskType   = taskType;
   24.78 -   newStub->ptrEntries = 
   24.79 -      PR_int__malloc( taskType->numCtldArgs * sizeof(PRServPointerEntry *) );
   24.80 -   newArgs = (void **)( (uint8 *)newStub + sizeof(PRMetaTask) );
   24.81 -   newStub->args = newArgs;
   24.82 -   newStub->numLiveChildTasks   = 0;
   24.83 -   newStub->numLiveChildThreads = 0;
   24.84 -   newStub->isEnded = FALSE;
   24.85 -   
   24.86 -      //Copy the arg-pointers.. can be more arguments than just the ones 
   24.87 -      // that StarSs uses to control ordering of task execution.
   24.88 -   memcpy( newArgs, args, taskType->sizeOfArgs );
   24.89 -   
   24.90 -   return newStub;
   24.91 - }
   24.92 -
   24.93 -inline PRServTaskStubCarrier *
   24.94 -create_task_carrier( PRServTaskStub *taskStub, int32 argNum, int32 rdOrWrite )
   24.95 - { PRServTaskStubCarrier *newCarrier;
   24.96 - 
   24.97 -   newCarrier = PR_PI__malloc( sizeof(PRServTaskStubCarrier) );
   24.98 -   newCarrier->taskStub = taskStub;
   24.99 -   newCarrier->argNum   = argNum;
  24.100 -   newCarrier->isReader = rdOrWrite == READER;
  24.101 - }
  24.102 -
  24.103 -
  24.104 -
  24.105 -//===========================  ==============================
  24.106 -
  24.107 -/*Application invokes this via wrapper library, when it explicitly creates a
  24.108 - * thread with the "PRServ__create_thread()" command.
  24.109 - * 
  24.110 - *Slave creation is a special form, so PR does handling before calling this.
  24.111 - * It does creation of the new slave, and hands it to this handler.  
  24.112 - *This handler is registered with PR during PRServ__start().
  24.113 - * 
  24.114 - *So, here, create a task Stub that contains a marker stating this is a thread. 
  24.115 - * Then, attach the task stub to the slave's meta Task via a PR command.
  24.116 - * 
  24.117 - *When slave dissipates, PR will call the registered recycler for the task stub.
  24.118 - */
  24.119 -inline void
  24.120 -handleCreateThd( PRReqst *req, SlaveVP *requestingSlv, SlaveVP *newSlv, PRServSemEnv *semEnv )
  24.121 - { PRServSemReq  *semReq;
  24.122 -   PRServTaskStub *taskStub, *parentTaskStub;
  24.123 -   
  24.124 -   semReq = PR_PI__take_sem_reqst_from( req );
  24.125 -
  24.126 -   parentTaskStub = PR_PI__give_lang_meta_task( requestingSlv );
  24.127 -   parentTaskStub->numLiveChildThreads += 1;
  24.128 -   
  24.129 -   taskStub = create_thread_task_stub(); //only used for wait info
  24.130 -   taskStub->parentTaskStub = parentTaskStub;
  24.131 -
  24.132 -      //note, semantic data will be initialized by separate, registered 
  24.133 -      // initializer, at the point it is accessed the first time.   
  24.134 -
  24.135 -   //================= Assign the new thread to a core ===================
  24.136 -   #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
  24.137 -   newSlv->coreAnimatedBy = 0;
  24.138 -
  24.139 -   #else
  24.140 -      //Assigning slaves to cores is part of SSR code..
  24.141 -   int32 coreToAssignOnto = semReq->coreToAssignOnto;
  24.142 -   if(coreToAssignOnto < 0 || coreToAssignOnto >= NUM_CORES )
  24.143 -    {    //out-of-range, so round-robin assignment
  24.144 -      newSlv->coreAnimatedBy = semEnv->nextCoreToGetNewSlv;
  24.145 -
  24.146 -      if( semEnv->nextCoreToGetNewSlv >= NUM_CORES - 1 )
  24.147 -          semEnv->nextCoreToGetNewSlv  = 0;
  24.148 -      else
  24.149 -          semEnv->nextCoreToGetNewSlv += 1;
  24.150 -    }
  24.151 -   else //core num in-range, so use it
  24.152 -    { newSlv->coreAnimatedBy = coreToAssignOnto;
  24.153 -    }
  24.154 -   #endif
  24.155 -   //========================================================================
  24.156 -   
  24.157 -   
  24.158 -
  24.159 -         DEBUG__printf2(dbgRqstHdlr,"Create from: %d, new VP: %d",
  24.160 -                                    requestingSlv->slaveID, newSlv->slaveID)
  24.161 -
  24.162 -   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  24.163 -   Dependency newD;
  24.164 -   newD.from_vp = requestingSlv->slaveID;
  24.165 -   newD.from_task = requestingSlv->numTimesAssignedToASlot;
  24.166 -   newD.to_vp = newSlv->slaveID;
  24.167 -   newD.to_task = 1;
  24.168 -   addToListOfArrays(Dependency,newD,semEnv->commDependenciesList);   
  24.169 -   #endif
  24.170 -
  24.171 -      //For PRServ, caller needs ptr to created thread returned to it
  24.172 -   requestingSlv->dataRetFromReq = newSlv;
  24.173 -   PR_PI__make_slave_ready(requestingSlv , semEnv );
  24.174 -   PR_PI__make_slave_ready( newSlv,        semEnv );
  24.175 - }
  24.176 -
  24.177 -/*Initialize semantic data struct..  this initializer doesn't need any input,
  24.178 - * but some languages may need something from inside the request that was sent
  24.179 - * to create a slave..  in that case, just make initializer do the malloc then
  24.180 - * use the PR_PI__give_sem_data  inside the create handler, and fill in the
  24.181 - * semData values there.
  24.182 - */
  24.183 -void * PRServ__create_lang_data_in_slave( )
  24.184 - { PRServSemData *semData;
  24.185 - 
  24.186 -   semData = PR_PI__malloc( sizeof(PRServSemData) );
  24.187 -   
  24.188 -   semData->highestTransEntered = -1;
  24.189 -   semData->lastTransEntered    = NULL;
  24.190 -   return semData;
  24.191 - }
  24.192 -
  24.193 -/*SlaveVP dissipate -- this is NOT task-end!, only call this to end explicitly
  24.194 - * created threads
  24.195 - */
  24.196 -inline void
  24.197 -handleDissipate( SlaveVP *requestingSlv, PRServSemEnv *semEnv )
  24.198 - { PRServSemData  *semData;
  24.199 -   PRServTaskStub  *parentTaskStub, *ownTaskStub;
  24.200 - 
  24.201 -         DEBUG__printf1(dbgRqstHdlr,"Dissipate request from processor %d",
  24.202 -                                                     requestingSlv->slaveID)
  24.203 -             
  24.204 -   ownTaskStub    = PR_PI__give_lang_meta_task( requestingSlv, PRServ_MAGIC_NUMBER );
  24.205 -   parentTaskStub = ownTaskStub->parentTaskStub;
  24.206 -   parentTaskStub->numLiveChildThreads -= 1;  //parent wasn't freed, even if ended
  24.207 -   
  24.208 -      //if all children ended, then free this task's stub
  24.209 -      // else, keep stub around, and last child will free it (below)
  24.210 -   if( ownTaskStub->numLiveChildTasks   == 0 &&
  24.211 -       ownTaskStub->numLiveChildThreads == 0 )
  24.212 -      free_task_stub( ownTaskStub );
  24.213 -   else
  24.214 -      ownTaskStub->isEnded = TRUE; //for children to see when they end
  24.215 -
  24.216 -      //Now, check on parents waiting on child threads to end
  24.217 -   if( parentTaskStub->isWaitingForChildThreadsToEnd &&
  24.218 -       parentTaskStub->numLiveChildThreads == 0 )
  24.219 -    { parentTaskStub->isWaitingForChildThreadsToEnd = FALSE;
  24.220 -      if( parentTaskStub->isWaitingForChildTasksToEnd )
  24.221 -        return; //still waiting on tasks (should be impossible)
  24.222 -      else //parent free to resume
  24.223 -        PR_PI__make_slave_ready( PR_PI__give_slave_assigned_to(parentTaskStub), semEnv );
  24.224 -    }
  24.225 -   
  24.226 -      //check if this is last child of ended parent (note, not possible to
  24.227 -      // have more than one level of ancestor waiting to be freed)
  24.228 -   if( parentTaskStub->isEnded &&
  24.229 -       parentTaskStub->numLiveChildTasks   == 0 && 
  24.230 -       parentTaskStub->numLiveChildThreads == 0 )
  24.231 -    { free_task_stub( parentTaskStub ); //just stub, semData already freed
  24.232 -    }
  24.233 -
  24.234 - FreeSlaveStateAndReturn:
  24.235 -      //Used to free the semData and requesting slave's base state, but
  24.236 -      // now PR does those things, so nothing more to do..
  24.237 -//PR handles this:   PR_PI__free( semData );
  24.238 -//PR handles this:   PR_PI__dissipate_slaveVP( requestingSlv );
  24.239 -   return; 
  24.240 - }
  24.241 -
  24.242 -/*Register this with PR, during PRServ start
  24.243 - *
  24.244 - *At some point, may change PR so that it recycles semData, in which case this
  24.245 - * only gets called when a process shuts down..  at that point, PR will call
  24.246 - * dissipate on all the slaves it has in the recycle Q.
  24.247 - */
  24.248 -void
  24.249 -freePRServSemData( void *_semData )
  24.250 - { //
  24.251 -   PR_PI__free( _semData );
  24.252 - }
  24.253 -
  24.254 -void resetPRServSemData( void *_semData ) 
  24.255 - { PRServSemData *semData = (PRServSemData *)_semData;
  24.256 -   
  24.257 -   semData->highestTransEntered = -1;
  24.258 -   semData->lastTransEntered    = NULL;
  24.259 - }
  24.260 -
  24.261 -//==========================================================================
  24.262 -//
  24.263 -//
  24.264 -/*Submit Task
  24.265 - *
  24.266 - *PR creates a PRMetaTask and passes it in.  This handler adds language-
  24.267 - * specific stuff to it.  The language-specific stuff is linked to the
  24.268 - * PRMetaTask, but if the task is suspended for any reason, the lang-specific
  24.269 - * part is moved to the semData of the slave that is animating the task.
  24.270 - *So, while the PRMetaTask is inside the creating language's semantic
  24.271 - * env, waiting to be assigned to a slave for animation, the lang-specific
  24.272 - * task info is accessed from the PRMetaTask.  But once the task suspends,
  24.273 - * that lang-specific task info transfers to the slave's semData.  All lang
  24.274 - * constructs that want to access it must get it from the semData.
  24.275 - *However, taskEnd still accesses the lang-specific task info from the 
  24.276 - * PRMetaTask, whether it suspended or not..  and the task code can access
  24.277 - * data to be used within the application behavior via 
  24.278 - * PR__give_task_info( animatingSlave ).
  24.279 - *  
  24.280 - *Uses a hash table to match the arg-pointers to each other. So, an
  24.281 - * argument-pointer is one-to-one with a hash-table entry.
  24.282 - * 
  24.283 - *If overlapping region detection is enabled, then a hash entry is one
  24.284 - * link in a ring of all entries that overlap each other.  For example,
  24.285 - * say region A shared common addresses with region B, but the pointers
  24.286 - * to them are different, then the hash entries for the two would be
  24.287 - * linked in a ring.  When a pointer is processed, all the pointers in
  24.288 - * the ring are processed (Doesn't differentiate independent siblings
  24.289 - * from parent-child or conjoined twins overlap..)
  24.290 - * NOT ENABLED AS OF MAY 25 2012
  24.291 - * 
  24.292 - *A hash entry has a queue of tasks that are waiting to access the
  24.293 - * pointed-to  region.  The queue goes in the order of creation of
  24.294 - * the tasks.  Each entry in the queue has a pointer to the task-stub
  24.295 - * and whether the task reads-only vs writes to the hash-entry's region.
  24.296 - * 
  24.297 - *A hash entry also has a count of the enabled but not yet finished readers
  24.298 - * of the region. It also has a flag that says whether a writer has been
  24.299 - * enabled and is not yet finished.
  24.300 - * 
  24.301 - *There are two kinds of events that access a hash entry: creation of a
  24.302 - * task and end of a task.
  24.303 - *
  24.304 - * 
  24.305 - * ==========================  creation  ========================== 
  24.306 - * 
  24.307 - *At creation, make a task-stub.  Set the count of blocking propendents
  24.308 - * to the number of controlled arguments (a task can have
  24.309 - * arguments that are not controlled by the language, like simple integer
  24.310 - * inputs from the sequential portion. Note that all controlled arguments
  24.311 - * are pointers, and marked as controlled in the application code).
  24.312 - * 
  24.313 - *The controlled arguments are then processed one by one.
  24.314 - *Processing an argument means getting the hash of the pointer.  Then,
  24.315 - * looking up the hash entry.  (If none, create one).
  24.316 - *With the hash entry:
  24.317 - *
  24.318 - *If the arg is a reader, and the entry does not have an enabled
  24.319 - * non-finished writer, and the queue is empty (could be prev readers,
  24.320 - * then a writer that got queued and now new readers that have to also be
  24.321 - * queued).
  24.322 - *The reader is free.  So, decrement the blocking-propendent count in
  24.323 - * the task-stub. If the count is zero, then put the task-stub into the
  24.324 - * readyQ.
  24.325 - *At the same time, increment the hash-entry's count of enabled and
  24.326 - * non-finished readers. 
  24.327 - * 
  24.328 - *Otherwise, the reader is put into the hash-entry's Q of waiters
  24.329 - * 
  24.330 - *If the arg is a writer, plus the entry does not have a current writer,
  24.331 - * plus the number of enabled non-finished readers is zero, plus the Q is
  24.332 - * empty, then the writer is free.  Mark the entry has having an
  24.333 - * enabled and non-finished writer.  Decrement the blocking-propendent
  24.334 - * count in the writer's task-stub. If the count is zero, then put the
  24.335 - * task-stub into the readyQ.
  24.336 - * 
  24.337 - *Otherwise, put the writer into the entry's Q of waiters.
  24.338 - * 
  24.339 - *No matter what, if the hash entry was chained, put it at the start of
  24.340 - * the chain.  (Means no-longer-used pointers accumulate at end of chain,
  24.341 - * decide garbage collection of no-longer-used pointers later)
  24.342 - *
  24.343 - */
  24.344 -inline 
  24.345 -void *
  24.346 -handleSubmitTask( PRServSemReq *semReq, PRServSemEnv *semEnv )
  24.347 - { uint32           key[3];
  24.348 -   HashEntry       *rawHashEntry; //has char *, but use with uint32 *
  24.349 -   PRServPointerEntry *ptrEntry; //contents of hash table entry for an arg pointer
  24.350 -   void           **args;
  24.351 -   PRServTaskStub     *taskStub, *parentTaskStub;
  24.352 -   PRServTaskType     *taskType;
  24.353 -   PRServTaskStubCarrier *taskCarrier;
  24.354 -   
  24.355 -   HashTable *
  24.356 -   argPtrHashTbl = semEnv->argPtrHashTbl;
  24.357 -   
  24.358 - 
  24.359 -   /* ==========================  creation  ========================== 
  24.360 -    *Make a task-stub.  Set the count of blocking propendents
  24.361 -    * to the number of controlled arguments (a task can have
  24.362 -    * arguments that are not controlled by the language, like simple integer
  24.363 -    * inputs from the sequential portion. Note that all controlled arguments
  24.364 -    * are pointers, and marked as controlled in the application code).
  24.365 -    */
  24.366 -   args     = semReq->args;
  24.367 -   taskType = semReq->taskType; //this is PRServ task type struct
  24.368 -   taskStub = create_task_stub( taskType, args );//copies arg ptrs
  24.369 -   
  24.370 -   taskStub->numBlockingProp = taskType->numCtldArgs;
  24.371 -   //PR does this (metaTask contains taskID): taskStub->taskID = semReq->taskID;
  24.372 -      
  24.373 -   parentTaskStub = (PRServTaskStub *)PR_PI__give_lang_meta_task(semReq->callingSlv, PRServ_MAGIC_NUMBER);
  24.374 -   taskStub->parentTaskStub = parentTaskStub; 
  24.375 -   parentTaskStub->numLiveChildTasks += 1;
  24.376 -   
  24.377 -         //DEBUG__printf3(dbgRqstHdlr,"Submit req from slaveID: %d, from task: %d, for task: %d", semReq->callingSlv->slaveID, parentSemData->taskStub->taskID[1], taskStub->taskID[1])
  24.378 -         DEBUG__printf2(dbgRqstHdlr,"Submit req from slaveID: %d, for task: %d", semReq->callingSlv->slaveID, taskStub->taskID[1])
  24.379 -          
  24.380 -   /*=============== Process args =================
  24.381 -    *The controlled arguments are processed one by one.
  24.382 -    *Processing an argument means getting the hash of the pointer.  Then,
  24.383 -    * looking up the hash entry.  (If none, create one).
  24.384 -    */
  24.385 -   int32 argNum;
  24.386 -   for( argNum = 0; argNum < taskType->numCtldArgs; argNum++ )
  24.387 -    { 
  24.388 -      key[0] = 2; //two 32b values in key
  24.389 -      *( (uint64*)&key[1]) = (uint64)args[argNum];  //write 64b into two 32b
  24.390 -
  24.391 -      /*If the hash entry was chained, put it at the
  24.392 -       * start of the chain.  (Means no-longer-used pointers accumulate
  24.393 -       * at end of chain, decide garbage collection later) */
  24.394 -      rawHashEntry = getEntryFromTable32( key, argPtrHashTbl );
  24.395 -      if( rawHashEntry == NULL )
  24.396 -       {    //adding a value auto-creates the hash-entry
  24.397 -         ptrEntry = create_pointer_entry();
  24.398 -         rawHashEntry = addValueIntoTable32( key, ptrEntry, argPtrHashTbl );
  24.399 -       }
  24.400 -      else
  24.401 -       { ptrEntry = (PRServPointerEntry *)rawHashEntry->content;
  24.402 -         if( ptrEntry == NULL )
  24.403 -          { ptrEntry = create_pointer_entry();
  24.404 -            rawHashEntry = addValueIntoTable32(key, ptrEntry, argPtrHashTbl);
  24.405 -          }
  24.406 -       }
  24.407 -      taskStub->ptrEntries[argNum] = ptrEntry;
  24.408 -      
  24.409 -      /*Have the hash entry.
  24.410 -       *If the arg is a reader and the entry does not have an enabled
  24.411 -       * non-finished writer, and the queue is empty. */
  24.412 -      if( taskType->argTypes[argNum] == READER )
  24.413 -       { if( !ptrEntry->hasEnabledNonFinishedWriter && 
  24.414 -             isEmptyPrivQ( ptrEntry->waitersQ ) )
  24.415 -          { /*The reader is free.  So, decrement the blocking-propendent
  24.416 -             * count in the task-stub. If the count is zero, then put the
  24.417 -             * task-stub into the readyQ.  At the same time, increment
  24.418 -             * the hash-entry's count of enabled and non-finished readers.*/
  24.419 -            taskStub->numBlockingProp -= 1;
  24.420 -            if( taskStub->numBlockingProp == 0 )
  24.421 -             { writePrivQ( taskStub, semEnv->taskReadyQ );
  24.422 -               if( semEnv->protoSemEnv->hasWork != TRUE ) 
  24.423 -                   semEnv->protoSemEnv->hasWork = TRUE;
  24.424 -             }
  24.425 -            ptrEntry->numEnabledNonDoneReaders += 1;
  24.426 -          }
  24.427 -         else
  24.428 -          { /*Otherwise, the reader is put into the hash-entry's Q of
  24.429 -             * waiters*/
  24.430 -            taskCarrier = create_task_carrier( taskStub, argNum, READER );
  24.431 -            writePrivQ( taskCarrier, ptrEntry->waitersQ );
  24.432 -          }
  24.433 -       }
  24.434 -      else //arg is a writer
  24.435 -       { /*the arg is a writer, plus the entry does not have a current
  24.436 -          * writer, plus the number of enabled non-finished readers is
  24.437 -          * zero, (the Q must be empty, else bug!) then the writer is free*/
  24.438 -         if( !ptrEntry->hasEnabledNonFinishedWriter &&
  24.439 -              ptrEntry->numEnabledNonDoneReaders == 0 )
  24.440 -          { /*Mark the entry has having a enabled and non-finished writer.
  24.441 -              * Decrement the blocking-propenden count in the writer's
  24.442 -              * task-stub. If the count is zero, then put the task-stub
  24.443 -              * into the readyQ.*/
  24.444 -            taskStub->numBlockingProp -= 1;
  24.445 -            if( taskStub->numBlockingProp == 0 )
  24.446 -             { writePrivQ( taskStub, semEnv->taskReadyQ );
  24.447 -               if( semEnv->protoSemEnv->hasWork != TRUE ) 
  24.448 -                   semEnv->protoSemEnv->hasWork = TRUE;
  24.449 -             }
  24.450 -            ptrEntry->hasEnabledNonFinishedWriter = TRUE;
  24.451 -          }
  24.452 -         else
  24.453 -          {/*Otherwise, put the writer into the entry's Q of waiters.*/
  24.454 -            taskCarrier = create_task_carrier( taskStub, argNum, WRITER );
  24.455 -            writePrivQ( taskCarrier, ptrEntry->waitersQ );            
  24.456 -          }
  24.457 -       }
  24.458 -    } //for argNum
  24.459 -   
  24.460 -      //resume the parent, creator
  24.461 -   PR_PI__make_slave_ready( semReq->callingSlv, semEnv );
  24.462 -
  24.463 -   return;
  24.464 - }
  24.465 -
  24.466 -
  24.467 -/* ========================== end of task ===========================
  24.468 - * 
  24.469 - *At the end of a task,
  24.470 - *The task's controlled arguments are processed one by one.
  24.471 - *Processing an argument means getting the hash of the pointer.  Then,
  24.472 - * looking up the hash entry (and putting the entry at the start of the
  24.473 - * chain, if there was a chain).
  24.474 - *With the hash entry:
  24.475 - *
  24.476 - *If the arg is a reader, then decrement the enabled and non-finished
  24.477 - * reader-count in the hash-entry. If the count becomes zero, then take
  24.478 - * the next entry from the Q. It should be a writer, or else there's a
  24.479 - * bug in this algorithm.
  24.480 - *Set the hash-entry to have an enabled non-finished writer.  Decrement
  24.481 - * the blocking-propendent-count of the writer's task-stub.  If the count
  24.482 - * has reached zero, then put the task-stub into the readyQ.
  24.483 - * 
  24.484 - *If the arg is a writer, then clear the enabled non-finished writer flag
  24.485 - * of the hash-entry. Take the next entry from the waiters Q. 
  24.486 - *If it is a writer, then turn the flag back on.  Decrement the writer's
  24.487 - * blocking-propendent-count in its task-stub.  If it becomes zero, then
  24.488 - * put the task-stub into the readyQ.
  24.489 - *
  24.490 - *If waiter is a reader, then do a loop, getting all waiting readers.
  24.491 - * For each, increment the hash-entry's count of enabled
  24.492 - * non-finished readers.  Decrement the blocking propendents count of the
  24.493 - * reader's task-stub.  If it reaches zero, then put the task-stub into the
  24.494 - * readyQ.
  24.495 - *Repeat until encounter a writer -- put that writer back into the Q.
  24.496 - * 
  24.497 - *May 2012 -- not keeping track of how many references to a given ptrEntry
  24.498 - * exist, so no way to garbage collect..
  24.499 - *TODO: Might be safe to delete an entry when task ends and waiterQ empty
  24.500 - * and no readers and no writers..
  24.501 - */
  24.502 -inline void
  24.503 -handleEndTask( void *langMetaTask, PRServSemReq *semReq, PRServSemEnv *semEnv )
  24.504 - { PRServPointerEntry  *ptrEntry; //contents of hash table entry for an arg pointer
  24.505 -   void            **args;
  24.506 -   PRServSemData       *endingSlvSemData;
  24.507 -   PRServTaskStub      *endingTaskStub, *waitingTaskStub, *parentStub;
  24.508 -   PRServTaskType      *endingTaskType;
  24.509 -   PRServTaskStubCarrier *waitingTaskCarrier;
  24.510 -   PRServPointerEntry **ptrEntries;
  24.511 -         
  24.512 - 
  24.513 -//   endingTaskStub   = (PRServTaskStub *)PR_PI__give_lang_spec_task_info( semReq->callingSlv );
  24.514 -   
  24.515 -   endingTaskStub   = (PRServTaskStub *)langMetaTask;
  24.516 -   args             = endingTaskStub->args;
  24.517 -   endingTaskType   = endingTaskStub->taskType;
  24.518 -   ptrEntries       = endingTaskStub->ptrEntries; //saved in stub when create
  24.519 -   
  24.520 -         DEBUG__printf2(dbgRqstHdlr,"EndTask req from slaveID: %d, task: %d",semReq->callingSlv->slaveID, endingTaskStub->taskID[1])
  24.521 -          
  24.522 -      //"wait" functionality: Check if parent was waiting on this task
  24.523 -   parentStub = endingTaskStub->parentTaskStub;
  24.524 -   parentStub->numLiveChildTasks -= 1;
  24.525 -   if( parentStub->isWaitingForChildTasksToEnd && 
  24.526 -       parentStub->numLiveChildTasks == 0)
  24.527 -    {
  24.528 -      parentStub->isWaitingForChildTasksToEnd = FALSE;
  24.529 -      PR_PI__make_slave_ready( PR_PI__give_slave_assigned_to(parentStub), semEnv );
  24.530 -    }
  24.531 -   
  24.532 -      //Check if parent ended, and this was last descendent, then free it
  24.533 -   if( parentStub->isEnded && parentStub->numLiveChildTasks == 0 )
  24.534 -    { free_task_stub( parentStub );
  24.535 -    }
  24.536 -   
  24.537 -   
  24.538 -      //Now, update state of dependents and start ready tasks
  24.539 -   /*The task's controlled arguments are processed one by one.
  24.540 -    *Processing an argument means getting arg-pointer's entry.
  24.541 -    */
  24.542 -   int32 argNum;
  24.543 -   for( argNum = 0; argNum < endingTaskType->numCtldArgs; argNum++ )
  24.544 -    {       
  24.545 -      ptrEntry = ptrEntries[argNum];
  24.546 -      //check if the ending task was reader of this arg
  24.547 -      if( endingTaskType->argTypes[argNum] == READER )
  24.548 -       { //then decrement the enabled and non-finished reader-count in
  24.549 -         // the hash-entry. 
  24.550 -         ptrEntry->numEnabledNonDoneReaders -= 1;
  24.551 -         
  24.552 -         //If the count becomes zero, then take the next entry from the Q. 
  24.553 -         //It should be a writer, or else there's a bug in this algorithm.
  24.554 -         if( ptrEntry->numEnabledNonDoneReaders == 0 )
  24.555 -          { waitingTaskCarrier = readPrivQ( ptrEntry->waitersQ );
  24.556 -            if( waitingTaskCarrier == NULL ) 
  24.557 -             { //TODO: looks safe to delete the ptr entry at this point 
  24.558 -               continue; //next iter of loop
  24.559 -             }
  24.560 -            if( waitingTaskCarrier->isReader ) 
  24.561 -               PR_App__throw_exception("READER waiting", NULL, NULL);
  24.562 -                   
  24.563 -            waitingTaskStub = waitingTaskCarrier->taskStub;
  24.564 -            
  24.565 -            //Set the hash-entry to have an enabled non-finished writer.
  24.566 -            ptrEntry->hasEnabledNonFinishedWriter = TRUE;
  24.567 -            
  24.568 -            // Decrement the blocking-propendent-count of the writer's
  24.569 -            // task-stub.  If the count has reached zero, then put the
  24.570 -            // task-stub into the readyQ.
  24.571 -            waitingTaskStub->numBlockingProp -= 1;
  24.572 -            if( waitingTaskStub->numBlockingProp == 0 )
  24.573 -             { writePrivQ( waitingTaskStub, semEnv->taskReadyQ );
  24.574 -               if( semEnv->protoSemEnv->hasWork != TRUE ) 
  24.575 -                   semEnv->protoSemEnv->hasWork = TRUE;
  24.576 -             }
  24.577 -          }
  24.578 -       }
  24.579 -      else //the ending task is a writer of this arg 
  24.580 -       { //clear the enabled non-finished writer flag of the hash-entry.
  24.581 -         ptrEntry->hasEnabledNonFinishedWriter = FALSE;
  24.582 -         
  24.583 -         //Take the next waiter from the hash-entry's Q.
  24.584 -         waitingTaskCarrier = readPrivQ( ptrEntry->waitersQ );
  24.585 -         if( waitingTaskCarrier == NULL )
  24.586 -          { //TODO: looks safe to delete ptr entry at this point
  24.587 -            continue; //go to next iter of loop, done here.
  24.588 -          }
  24.589 -         waitingTaskStub = waitingTaskCarrier->taskStub;
  24.590 -         
  24.591 -         //If task is a writer of this hash-entry's pointer
  24.592 -         if( !waitingTaskCarrier->isReader ) 
  24.593 -          { // then turn the flag back on.
  24.594 -            ptrEntry->hasEnabledNonFinishedWriter = TRUE;
  24.595 -            //Decrement the writer's blocking-propendent-count in task-stub
  24.596 -            // If it becomes zero, then put the task-stub into the readyQ.
  24.597 -            waitingTaskStub->numBlockingProp -= 1;
  24.598 -            if( waitingTaskStub->numBlockingProp == 0 )
  24.599 -             { writePrivQ( waitingTaskStub, semEnv->taskReadyQ );
  24.600 -                if( semEnv->protoSemEnv->hasWork != TRUE ) 
  24.601 -                    semEnv->protoSemEnv->hasWork = TRUE;
  24.602 -             }
  24.603 -          }
  24.604 -         else
  24.605 -          { //Waiting task is a reader, so do a loop, of all waiting readers
  24.606 -            // until encounter a writer or waitersQ is empty
  24.607 -            while( TRUE ) //The checks guarantee have a waiting reader
  24.608 -             { //Increment the hash-entry's count of enabled non-finished
  24.609 -               // readers.
  24.610 -               ptrEntry->numEnabledNonDoneReaders += 1;
  24.611 -
  24.612 -               //Decrement the blocking propendents count of the reader's
  24.613 -               // task-stub.  If it reaches zero, then put the task-stub
  24.614 -               // into the readyQ.
  24.615 -               waitingTaskStub->numBlockingProp -= 1;
  24.616 -               if( waitingTaskStub->numBlockingProp == 0 )
  24.617 -                { writePrivQ( waitingTaskStub, semEnv->taskReadyQ );
  24.618 -                   if( semEnv->protoSemEnv->hasWork != TRUE ) 
  24.619 -                       semEnv->protoSemEnv->hasWork = TRUE;
  24.620 -                }
  24.621 -               //Get next waiting task
  24.622 -               waitingTaskCarrier = peekPrivQ( ptrEntry->waitersQ );
  24.623 -               if( waitingTaskCarrier == NULL )    break; //no more waiting readers
  24.624 -               if( !waitingTaskCarrier->isReader ) break; //no more waiting readers
  24.625 -               waitingTaskCarrier = readPrivQ( ptrEntry->waitersQ );               
  24.626 -               waitingTaskStub = waitingTaskCarrier->taskStub;
  24.627 -             }//while waiter is a reader
  24.628 -          }//if-else, first waiting task is a reader
  24.629 -       }//if-else, check of ending task, whether writer or reader
  24.630 -    }//for argnum in ending task
  24.631 -   
  24.632 -   
  24.633 -      //done ending the task, if still has live children, then keep stub around
  24.634 -      // else, free the stub and args copy
  24.635 -   if( endingTaskStub->numLiveChildTasks   == 0 &&
  24.636 -       endingTaskStub->numLiveChildThreads == 0 )
  24.637 -    { free_task_stub( endingTaskStub ); 
  24.638 -    }
  24.639 -   
  24.640 -   return; 
  24.641 - }
  24.642 -
  24.643 -
  24.644 -inline void
  24.645 -free_task_stub( PRServTaskStub *stubToFree )
  24.646 - { if(stubToFree->ptrEntries != NULL ) //a thread stub has NULL entry
  24.647 -    { PR_PI__free( stubToFree->ptrEntries );
  24.648 -    }
  24.649 -   PR_PI__free( stubToFree );
  24.650 - }
  24.651 -
  24.652 -//========================== Task Comm handlers ===========================
  24.653 -
  24.654 -
  24.655 -
  24.656 -//============================  Send Handlers ==============================
  24.657 -/*Send of Type -- The semantic request has the receiving task ID and Type
  24.658 - *
  24.659 - *Messages of a given Type have to be kept separate..  so need a separate
  24.660 - * entry in the hash table for each pair: receiverID, Type
  24.661 - *
  24.662 - *Also, if same sender sends multiple before any get received, then need to
  24.663 - * stack the sends up -- even if a send waits until it's paired, several
  24.664 - * separate tasks can send to the same receiver, and doing hash on the
  24.665 - * receive task, so they will stack up.
  24.666 - */
  24.667 -inline void
  24.668 -handleSendTypeTo( PRServSemReq *semReq, PRServSemEnv *semEnv )
  24.669 - { SlaveVP    *senderSlv, *receiverSlv;
  24.670 -   int32      *senderID, *receiverID;
  24.671 -   int32      *key, keySz, receiverIDNumInt;
  24.672 -   PRServSemReq  *waitingReq;
  24.673 -   HashEntry  *entry;
  24.674 -   HashTable  *commHashTbl = semEnv->commHashTbl;
  24.675 -   
  24.676 -   receiverID  = semReq->receiverID; //For "send", know both send & recv procrs
  24.677 -   senderSlv   = semReq->senderSlv;
  24.678 -
  24.679 -         DEBUG__printf2(dbgRqstHdlr,"SendType req from sender slaveID: %d, recTask: %d", senderSlv->slaveID, receiverID[1])
  24.680 -          
  24.681 -         
  24.682 -   receiverIDNumInt = receiverID[0] + 1; //pos 0 doesn't include itself
  24.683 -   keySz = receiverIDNumInt * sizeof(int32) + 2 * sizeof(int32);
  24.684 -   key = PR_PI__malloc( keySz );
  24.685 -   key[0] = receiverIDNumInt + 1; //loc 0 is num int32 in key
  24.686 -   memcpy( &key[1], receiverID, receiverIDNumInt * sizeof(int32) );
  24.687 -   key[ 1 + receiverIDNumInt ] = semReq->msgType; 
  24.688 -   
  24.689 -   entry = giveEntryElseInsertReqst32( key, semReq, commHashTbl );
  24.690 -   if( entry == NULL ) //was just inserted, means task has to wait
  24.691 -    { return;
  24.692 -    }
  24.693 -
  24.694 -      //if here, found a waiting request with same key
  24.695 -   waitingReq = (PRServSemReq *)entry->content;
  24.696 -
  24.697 -      //At this point, know have waiting request(s) -- either sends or recv
  24.698 -      //Note, can only have max of one receive waiting, and cannot have both
  24.699 -      // sends and receives waiting (they would have paired off)
  24.700 -      // but can have multiple sends from diff sending VPs, all same msg-type
  24.701 -   if( waitingReq->reqType == send_type_to )
  24.702 -    {    //waiting request is another send, so stack this up on list
  24.703 -         // but first clone the sending request so it persists.
  24.704 -      PRServSemReq *clonedReq = cloneReq( semReq );
  24.705 -      clonedReq-> nextReqInHashEntry = waitingReq->nextReqInHashEntry;
  24.706 -      waitingReq->nextReqInHashEntry = clonedReq;
  24.707 -         DEBUG__printf2( dbgRqstHdlr, "linked requests: %p, %p ", clonedReq,\
  24.708 -                                                                 waitingReq )
  24.709 -      return;
  24.710 -    }
  24.711 -   else
  24.712 -    {    
  24.713 -       #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  24.714 -        Dependency newD;
  24.715 -        newD.from_vp = senderID->slaveID;
  24.716 -        newD.from_task = senderID->numTimesAssignedToASlot;
  24.717 -        newD.to_vp = receiverID->slaveID;
  24.718 -        newD.to_task = receiverID->numTimesAssignedToASlot +1;
  24.719 -        //(newD,semEnv->commDependenciesList);  
  24.720 -        addToListOfArrays(Dependency,newD,semEnv->dynDependenciesList);  
  24.721 -                int32 groupId = semReq->msgType;
  24.722 -        if(semEnv->ntonGroupsInfo->numInArray <= groupId){
  24.723 -            makeHighestDynArrayIndexBeAtLeast(semEnv->ntonGroupsInfo, groupId);
  24.724 -        }
  24.725 -        if(semEnv->ntonGroups[groupId] == NULL){
  24.726 -            semEnv->ntonGroups[groupId] = new_NtoN(groupId);
  24.727 -        }
  24.728 -        Unit u;
  24.729 -        u.vp = senderID->slaveID;
  24.730 -        u.task = senderID->numTimesAssignedToASlot;
  24.731 -        addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->senders);
  24.732 -        u.vp = receiverID->slaveID;
  24.733 -        u.task = receiverID->numTimesAssignedToASlot +1;
  24.734 -        addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->receivers);
  24.735 -       #endif
  24.736 -
  24.737 -         //set receiver slave, from the waiting request
  24.738 -      receiverSlv = waitingReq->receiverSlv;
  24.739 -      
  24.740 -         //waiting request is a receive_type_to, so it pairs to this send
  24.741 -         //First, remove the waiting receive request from the entry
  24.742 -      entry->content = waitingReq->nextReqInHashEntry;
  24.743 -      PR_PI__free( waitingReq ); //Don't use contents -- so free it
  24.744 -      
  24.745 -      if( entry->content == NULL )
  24.746 -       {    //TODO: mod hash table to double-link, so can delete entry from
  24.747 -            // table without hashing the key and looking it up again
  24.748 -         deleteEntryFromTable32( (uint32*)entry->key, commHashTbl );  //frees hashEntry
  24.749 -       }
  24.750 -      
  24.751 -         //attach msg that's in this send request to receiving task's Slv
  24.752 -         // when comes back from suspend will have msg in dataRetFromReq
  24.753 -      receiverSlv->dataRetFromReq = semReq->msg;
  24.754 -
  24.755 -         //bring both processors back from suspend
  24.756 -      PR_PI__make_slave_ready( senderSlv,   semEnv );
  24.757 -      PR_PI__make_slave_ready( receiverSlv, semEnv );
  24.758 -
  24.759 -      return;
  24.760 -    }
  24.761 - }
  24.762 -
  24.763 -
  24.764 -/*If Send or Receive are called within a task, it causes the task to suspend,
  24.765 - * which converts the slave animating it to a free slave and suspends that slave.
  24.766 - *Which means that send and receive operate upon slaves, no matter whether they
  24.767 - * were called from within a task or a slave.
  24.768 - *  
  24.769 - *Looks like can make single handler for both kinds of send..
  24.770 - */
  24.771 -//TODO: combine both send handlers into single handler
  24.772 -inline void
  24.773 -handleSendFromTo( PRServSemReq *semReq, PRServSemEnv *semEnv)
  24.774 - { SlaveVP     *senderSlv, *receiverSlv;
  24.775 -   int32       *senderID, *receiverID;
  24.776 -   int32       *key, keySz, receiverIDNumInt, senderIDNumInt;
  24.777 -   PRServSemReq   *waitingReq;
  24.778 -   HashEntry   *entry;
  24.779 -   HashTable   *commHashTbl = semEnv->commHashTbl;
  24.780 -
  24.781 -         DEBUG__printf2(dbgRqstHdlr,"SendFromTo req from task %d to %d",
  24.782 -                        semReq->senderID[1],semReq->receiverID[1])
  24.783 -   
  24.784 -   receiverID  = semReq->receiverID; //For "send", know both send & recv procrs
  24.785 -   senderID    = semReq->senderID;
  24.786 -   senderSlv   = semReq->senderSlv;
  24.787 -
  24.788 -   
  24.789 -   receiverIDNumInt = receiverID[0] + 1; //include the count in the key
  24.790 -   senderIDNumInt   = senderID[0] + 1;
  24.791 -   keySz = (receiverIDNumInt + senderIDNumInt) * sizeof(int32) + sizeof(int32);
  24.792 -   key   = PR_PI__malloc( keySz );
  24.793 -   key[0] = receiverIDNumInt + senderIDNumInt;
  24.794 -   memcpy( &key[1], receiverID, receiverIDNumInt * sizeof(int32) );
  24.795 -   memcpy( &key[1 + receiverIDNumInt], senderID, senderIDNumInt * sizeof(int32) );
  24.796 -
  24.797 -   entry = giveEntryElseInsertReqst32( key, semReq, commHashTbl );
  24.798 -   if( entry == NULL ) //was just inserted, means task has to wait
  24.799 -    { return;
  24.800 -    }
  24.801 -
  24.802 -   waitingReq = (PRServSemReq *)entry->content;
  24.803 -
  24.804 -      //At this point, know have waiting request(s) -- either sends or recv
  24.805 -   if( waitingReq->reqType == send_from_to )
  24.806 -    { printf("\n ERROR: shouldn't be two send-from-tos waiting \n");
  24.807 -    }
  24.808 -   else
  24.809 -    {    //waiting request is a receive, so it completes pair with this send
  24.810 -      #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  24.811 -        Dependency newD;
  24.812 -        newD.from_vp = sendPr->slaveID;
  24.813 -        newD.from_task = sendPr->numTimesAssignedToASlot;
  24.814 -        newD.to_vp = receivePr->slaveID;
  24.815 -        newD.to_task = receivePr->numTimesAssignedToASlot +1;
  24.816 -        //addToListOfArraysDependency(newD,semEnv->commDependenciesList);  
  24.817 -        addToListOfArrays(Dependency,newD,semEnv->commDependenciesList);   
  24.818 -      #endif 
  24.819 -
  24.820 -         //set receiver slave, from the waiting request
  24.821 -      receiverSlv = waitingReq->receiverSlv;
  24.822 -       
  24.823 -         //First, remove the waiting receive request from the entry
  24.824 -      entry->content = waitingReq->nextReqInHashEntry;
  24.825 -      PR_PI__free( waitingReq ); //Don't use contents -- so free it
  24.826 -      
  24.827 -         //can only be one waiting req for "from-to" semantics
  24.828 -      if( entry->content != NULL )
  24.829 -       {
  24.830 -         printf("\nERROR in handleSendFromTo\n");
  24.831 -       }
  24.832 -      deleteEntryFromTable32( (uint32*)entry->key, commHashTbl );  //frees HashEntry
  24.833 -
  24.834 -         //attach msg that's in this send request to receiving procr
  24.835 -         // when comes back from suspend, will have msg in dataRetFromReq
  24.836 -      receiverSlv->dataRetFromReq = semReq->msg;
  24.837 -
  24.838 -         //bring both processors back from suspend
  24.839 -      PR_PI__make_slave_ready( senderSlv,   semEnv );
  24.840 -      PR_PI__make_slave_ready( receiverSlv, semEnv );
  24.841 -            
  24.842 -      return;
  24.843 -    }
  24.844 - }
  24.845 -
  24.846 -
  24.847 -
  24.848 -//==============================  Receives  ===========================
  24.849 -//
  24.850 -
  24.851 -
  24.852 -inline void
  24.853 -handleReceiveTypeTo( PRServSemReq *semReq, PRServSemEnv *semEnv)
  24.854 - { SlaveVP    *senderSlv, *receiverSlv;
  24.855 -   int32      *receiverID;
  24.856 -   int32      *key, keySz, receiverIDNumInt;
  24.857 -   PRServSemReq  *waitingReq;
  24.858 -   HashEntry  *entry;
  24.859 -   HashTable  *commHashTbl = semEnv->commHashTbl;
  24.860 -   
  24.861 -         DEBUG__printf2(dbgRqstHdlr,"ReceiveType req to ID: %d type: %d",semReq->receiverID[1], semReq->msgType)
  24.862 - 
  24.863 -   receiverID  = semReq->receiverID; //For "send", know both send & recv procrs
  24.864 -   receiverSlv = semReq->receiverSlv;
  24.865 -   
  24.866 -
  24.867 -      //key is the receiverID plus the type -- have to copy them into key
  24.868 -   receiverIDNumInt = receiverID[0] + 1; //pos 0 doesn't include itself
  24.869 -   keySz = receiverIDNumInt * sizeof(int32) + 2 * sizeof(int32);
  24.870 -   key = PR_PI__malloc( keySz );
  24.871 -   key[0] = receiverIDNumInt + 1; //loc 0 is num int32s in key
  24.872 -   memcpy( &key[1], receiverID, receiverIDNumInt * sizeof(int32) );
  24.873 -   key[ 1 + receiverIDNumInt ] = semReq->msgType; 
  24.874 -
  24.875 -   entry = giveEntryElseInsertReqst32( key, semReq, commHashTbl );//clones
  24.876 -   if( entry == NULL ) //was just inserted, means task has to wait
  24.877 -    { return;
  24.878 -    }
  24.879 -
  24.880 -   waitingReq = (PRServSemReq *)entry->content;  //previously cloned by insert
  24.881 -
  24.882 -      //At this point, know have waiting request(s) -- should be send(s)
  24.883 -   if( waitingReq->reqType == send_type_to )
  24.884 -    {    
  24.885 -         //set sending slave  from the request
  24.886 -      senderSlv = waitingReq->senderSlv;
  24.887 -      
  24.888 -         //waiting request is a send, so pair it with this receive
  24.889 -         //first, remove the waiting send request from the list in entry
  24.890 -      entry->content = waitingReq->nextReqInHashEntry;
  24.891 -      if( entry->content == NULL )
  24.892 -       { deleteEntryFromTable32( (uint32*)entry->key, commHashTbl );  //frees HashEntry
  24.893 -       }
  24.894 -      
  24.895 -         //attach msg that's in the send request to receiving procr
  24.896 -         // when comes back from suspend, will have msg in dataRetFromReq
  24.897 -      receiverSlv->dataRetFromReq = waitingReq->msg;
  24.898 -
  24.899 -         //bring both processors back from suspend
  24.900 -      PR_PI__free( waitingReq );
  24.901 -
  24.902 -       #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  24.903 -        Dependency newD;
  24.904 -        newD.from_vp = sendPr->slaveID;
  24.905 -        newD.from_task = sendPr->numTimesAssignedToASlot;
  24.906 -        newD.to_vp = receivePr->slaveID;
  24.907 -        newD.to_task = receivePr->numTimesAssignedToASlot +1;
  24.908 -        //addToListOfArraysDependency(newD,semEnv->commDependenciesList);  
  24.909 -        addToListOfArrays(Dependency,newD,semEnv->dynDependenciesList); 
  24.910 -        int32 groupId = semReq->msgType;
  24.911 -        if(semEnv->ntonGroupsInfo->numInArray <= groupId){
  24.912 -            makeHighestDynArrayIndexBeAtLeast(semEnv->ntonGroupsInfo, groupId);
  24.913 -        }
  24.914 -        if(semEnv->ntonGroups[groupId] == NULL){
  24.915 -            semEnv->ntonGroups[groupId] = new_NtoN(groupId);
  24.916 -        }
  24.917 -        Unit u;
  24.918 -        u.vp = sendPr->slaveID;
  24.919 -        u.task = sendPr->numTimesAssignedToASlot;
  24.920 -        addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->senders);
  24.921 -        u.vp = receivePr->slaveID;
  24.922 -        u.task = receivePr->numTimesAssignedToASlot +1;
  24.923 -        addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->receivers);
  24.924 -       #endif
  24.925 -      
  24.926 -      PR_PI__make_slave_ready( senderSlv,   semEnv );
  24.927 -      PR_PI__make_slave_ready( receiverSlv, semEnv );
  24.928 -
  24.929 -      return;
  24.930 -    }
  24.931 -   printf("\nLang Impl Error: Should never be two waiting receives!\n");
  24.932 - }
  24.933 -
  24.934 -
  24.935 -/*
  24.936 - */
  24.937 -inline void
  24.938 -handleReceiveFromTo( PRServSemReq *semReq, PRServSemEnv *semEnv)
  24.939 - { SlaveVP     *senderSlv, *receiverSlv;
  24.940 -   int32       *senderID,  *receiverID;
  24.941 -   int32       *key, keySz, receiverIDNumInt, senderIDNumInt;
  24.942 -   PRServSemReq   *waitingReq;
  24.943 -   HashEntry   *entry;
  24.944 -   HashTable   *commHashTbl = semEnv->commHashTbl;
  24.945 -
  24.946 -         DEBUG__printf2(dbgRqstHdlr,"RecFromTo req from ID: %d to ID: %d",semReq->senderID[1],semReq->receiverID[1])
  24.947 -   
  24.948 -   receiverID  = semReq->receiverID; //For "send", know both send & recv procrs
  24.949 -   senderID    = semReq->senderID;
  24.950 -   receiverSlv = semReq->receiverSlv;
  24.951 -   
  24.952 -   receiverIDNumInt = receiverID[0] + 1; //pos 0 doesn't include itself
  24.953 -   senderIDNumInt   = senderID[0] + 1;
  24.954 -   keySz = (receiverIDNumInt + senderIDNumInt) * sizeof(int32) + sizeof(int32);
  24.955 -   key = PR_PI__malloc( keySz );
  24.956 -   key[0] = receiverIDNumInt + senderIDNumInt; //loc 0 is num int32s in key
  24.957 -   memcpy( &key[1], receiverID, receiverIDNumInt * sizeof(int32) );
  24.958 -   memcpy( &key[1 + receiverIDNumInt], senderID, senderIDNumInt * sizeof(int32));
  24.959 -
  24.960 -   entry = giveEntryElseInsertReqst32( key, semReq, commHashTbl );
  24.961 -   if( entry == NULL ) //was just inserted, means task has to wait
  24.962 -    { return;
  24.963 -    }
  24.964 -
  24.965 -   waitingReq = (PRServSemReq *)entry->content;
  24.966 -
  24.967 -      //At this point, know have a request to rendez-vous -- should be send
  24.968 -   if( waitingReq->reqType == send_from_to )
  24.969 -    {    //waiting request is a send, so pair it with this receive
  24.970 -      #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  24.971 -        Dependency newD;
  24.972 -        newD.from_vp = sendPr->slaveID;
  24.973 -        newD.from_task = sendPr->numTimesAssignedToASlot;
  24.974 -        newD.to_vp = receivePr->slaveID;
  24.975 -        newD.to_task = receivePr->numTimesAssignedToASlot +1;
  24.976 -        //addToListOfArraysDependency(newD,semEnv->commDependenciesList);  
  24.977 -        addToListOfArrays(Dependency,newD,semEnv->commDependenciesList);    
  24.978 -      #endif
  24.979 -      
  24.980 -         //have receiver slave, now set sender slave
  24.981 -      senderSlv = waitingReq->senderSlv;
  24.982 -      
  24.983 -         //For from-to, should only ever be a single reqst waiting tobe paird
  24.984 -      entry->content = waitingReq->nextReqInHashEntry;
  24.985 -      if( entry->content != NULL ) printf("\nERROR in handleRecvFromTo\n");
  24.986 -      deleteEntryFromTable32( (uint32*)entry->key, commHashTbl );  //frees entry too
  24.987 -
  24.988 -         //attach msg that's in the send request to receiving procr
  24.989 -         // when comes back from suspend, will have msg in dataRetFromReq
  24.990 -      receiverSlv->dataRetFromReq = waitingReq->msg;
  24.991 -
  24.992 -         //bring both processors back from suspend
  24.993 -      PR_PI__free( waitingReq );
  24.994 -
  24.995 -      PR_PI__make_slave_ready( senderSlv,   semEnv );
  24.996 -      PR_PI__make_slave_ready( receiverSlv, semEnv );
  24.997 -
  24.998 -      return;
  24.999 -    }
 24.1000 -   printf("\nLang Impl Error: Should never be two waiting receives!\n");
 24.1001 - }
 24.1002 -
 24.1003 -
 24.1004 -/*Waits for all tasks that are direct children to end, then resumes calling
 24.1005 - * task or thread
 24.1006 - */
 24.1007 -inline void
 24.1008 -handleTaskwait( PRServSemReq *semReq, SlaveVP *requestingSlv, PRServSemEnv *semEnv)
 24.1009 - { PRServTaskStub* taskStub;
 24.1010 - 
 24.1011 -            DEBUG__printf1(dbgRqstHdlr,"Taskwait request from processor %d",
 24.1012 -                                                      requestingSlv->slaveID)
 24.1013 -    
 24.1014 -   taskStub = (PRServTaskStub *)PR_PI__give_lang_meta_task( requestingSlv, PRServ_MAGIC_NUMBER);
 24.1015 -   
 24.1016 -   if( taskStub->numLiveChildTasks == 0 )
 24.1017 -    {    //nobody to wait for, resume
 24.1018 -      PR_PI__make_slave_ready( requestingSlv, semEnv );
 24.1019 -    }
 24.1020 -   else  //have to wait, mark waiting
 24.1021 -    {        
 24.1022 -      taskStub->isWaitingForChildTasksToEnd = TRUE;
 24.1023 -    }    
 24.1024 - }
 24.1025  
 24.1026  
 24.1027  //==========================================================================
 24.1028  /*
 24.1029   */
 24.1030  void
 24.1031 -handleMalloc( PRServSemReq *semReq, SlaveVP *requestingSlv, PRServSemEnv *semEnv )
 24.1032 +PRServ__handleMalloc( PRServLangReq *langReq, SlaveVP *requestingSlv, PRServLangEnv *langEnv )
 24.1033   { void *ptr;
 24.1034   
 24.1035 -      DEBUG__printf1(dbgRqstHdlr,"Malloc request from processor %d",requestingSlv->slaveID)
 24.1036 +      DEBUG__printf1(dbgRqstHdlr,"Malloc request from processor %d",requestingSlv->slaveNum)
 24.1037  
 24.1038 -   ptr = PR_PI__malloc( semReq->sizeToMalloc );
 24.1039 +   ptr = PR_PI__malloc( langReq->sizeToMalloc );
 24.1040     requestingSlv->dataRetFromReq = ptr;
 24.1041 -   PR_PI__make_slave_ready( requestingSlv, semEnv );
 24.1042 +   PR_PI__make_slave_ready( requestingSlv, langEnv );
 24.1043   }
 24.1044  
 24.1045  /*
 24.1046   */
 24.1047  void
 24.1048 -handleFree( PRServSemReq *semReq, SlaveVP *requestingSlv, PRServSemEnv *semEnv )
 24.1049 +PRServ__handleFree( PRServLangReq *langReq, SlaveVP *requestingSlv, PRServLangEnv *langEnv )
 24.1050   {
 24.1051 -         DEBUG__printf1(dbgRqstHdlr,"Free request from processor %d",requestingSlv->slaveID)
 24.1052 -   PR_PI__free( semReq->ptrToFree );
 24.1053 -   PR_PI__make_slave_ready( requestingSlv, semEnv );
 24.1054 +         DEBUG__printf1(dbgRqstHdlr,"Free request from processor %d",requestingSlv->slaveNum)
 24.1055 +   PR_PI__free( langReq->ptrToFree );
 24.1056 +   PR_PI__make_slave_ready( requestingSlv, langEnv );
 24.1057   }
 24.1058  
 24.1059  
 24.1060 @@ -1067,14 +49,15 @@
 24.1061  /*Uses ID as index into array of flags.  If flag already set, resumes from
 24.1062   * end-label.  Else, sets flag and resumes normally.
 24.1063   */
 24.1064 -void inline
 24.1065 -handleStartSingleton_helper( PRServSingleton *singleton, SlaveVP *reqstingSlv,
 24.1066 -                             PRServSemEnv    *semEnv )
 24.1067 +void 
 24.1068 +//inline
 24.1069 +PRServ__handleStartSingleton_helper( PRServSingleton *singleton, SlaveVP *reqstingSlv,
 24.1070 +                             PRServLangEnv    *langEnv )
 24.1071   {
 24.1072     if( singleton->hasFinished )
 24.1073      {    //the code that sets the flag to true first sets the end instr addr
 24.1074        reqstingSlv->dataRetFromReq = singleton->endInstrAddr;
 24.1075 -      PR_PI__make_slave_ready( reqstingSlv, semEnv );
 24.1076 +      PR_PI__make_slave_ready( reqstingSlv, langEnv );
 24.1077        return;
 24.1078      }
 24.1079     else if( singleton->hasBeenStarted )
 24.1080 @@ -1086,42 +69,45 @@
 24.1081      {    //hasn't been started, so this is the first attempt at the singleton
 24.1082        singleton->hasBeenStarted = TRUE;
 24.1083        reqstingSlv->dataRetFromReq = 0x0;
 24.1084 -      PR_PI__make_slave_ready( reqstingSlv, semEnv );
 24.1085 +      PR_PI__make_slave_ready( reqstingSlv, langEnv );
 24.1086        return;
 24.1087      }
 24.1088   }
 24.1089 -void inline
 24.1090 -handleStartFnSingleton( PRServSemReq *semReq, SlaveVP *requestingSlv,
 24.1091 -                      PRServSemEnv *semEnv )
 24.1092 +void 
 24.1093 +//inline
 24.1094 +PRServ__handleStartFnSingleton( PRServLangReq *langReq, SlaveVP *requestingSlv,
 24.1095 +                      PRServLangEnv *langEnv )
 24.1096   { PRServSingleton *singleton;
 24.1097 -         DEBUG__printf1(dbgRqstHdlr,"StartFnSingleton request from processor %d",requestingSlv->slaveID)
 24.1098 +         DEBUG__printf1(dbgRqstHdlr,"StartFnSingleton request from processor %d",requestingSlv->slaveNum)
 24.1099  
 24.1100 -   singleton = &(semEnv->fnSingletons[ semReq->singletonID ]);
 24.1101 -   handleStartSingleton_helper( singleton, requestingSlv, semEnv );
 24.1102 +   singleton = &(langEnv->fnSingletons[ langReq->singletonID ]);
 24.1103 +   PRServ__handleStartSingleton_helper( singleton, requestingSlv, langEnv );
 24.1104   }
 24.1105 -void inline
 24.1106 -handleStartDataSingleton( PRServSemReq *semReq, SlaveVP *requestingSlv,
 24.1107 -                      PRServSemEnv *semEnv )
 24.1108 +void 
 24.1109 +//inline
 24.1110 +PRServ__handleStartDataSingleton( PRServLangReq *langReq, SlaveVP *requestingSlv,
 24.1111 +                      PRServLangEnv *langEnv )
 24.1112   { PRServSingleton *singleton;
 24.1113  
 24.1114 -         DEBUG__printf1(dbgRqstHdlr,"StartDataSingleton request from processor %d",requestingSlv->slaveID)
 24.1115 -   if( *(semReq->singletonPtrAddr) == NULL )
 24.1116 +         DEBUG__printf1(dbgRqstHdlr,"StartDataSingleton request from processor %d",requestingSlv->slaveNum)
 24.1117 +   if( *(langReq->singletonPtrAddr) == NULL )
 24.1118      { singleton                 = PR_PI__malloc( sizeof(PRServSingleton) );
 24.1119        singleton->waitQ          = makePRQ();
 24.1120        singleton->endInstrAddr   = 0x0;
 24.1121        singleton->hasBeenStarted = FALSE;
 24.1122        singleton->hasFinished    = FALSE;
 24.1123 -      *(semReq->singletonPtrAddr)  = singleton;
 24.1124 +      *(langReq->singletonPtrAddr)  = singleton;
 24.1125      }
 24.1126     else
 24.1127 -      singleton = *(semReq->singletonPtrAddr);
 24.1128 -   handleStartSingleton_helper( singleton, requestingSlv, semEnv );
 24.1129 +      singleton = *(langReq->singletonPtrAddr);
 24.1130 +   PRServ__handleStartSingleton_helper( singleton, requestingSlv, langEnv );
 24.1131   }
 24.1132  
 24.1133  
 24.1134 -void inline
 24.1135 -handleEndSingleton_helper( PRServSingleton *singleton, SlaveVP *requestingSlv,
 24.1136 -                           PRServSemEnv    *semEnv )
 24.1137 +void 
 24.1138 +//inline
 24.1139 +PRServ__handleEndSingleton_helper( PRServSingleton *singleton, SlaveVP *requestingSlv,
 24.1140 +                           PRServLangEnv    *langEnv )
 24.1141   { PrivQueueStruc *waitQ;
 24.1142     int32           numWaiting, i;
 24.1143     SlaveVP      *resumingSlv;
 24.1144 @@ -1139,33 +125,33 @@
 24.1145      {    //they will resume inside start singleton, then jmp to end singleton
 24.1146        resumingSlv = readPrivQ( waitQ );
 24.1147        resumingSlv->dataRetFromReq = singleton->endInstrAddr;
 24.1148 -      PR_PI__make_slave_ready( resumingSlv, semEnv );
 24.1149 +      PR_PI__make_slave_ready( resumingSlv, langEnv );
 24.1150      }
 24.1151  
 24.1152 -   PR_PI__make_slave_ready( requestingSlv, semEnv );
 24.1153 +   PR_PI__make_slave_ready( requestingSlv, langEnv );
 24.1154  
 24.1155  }
 24.1156 -void inline
 24.1157 -handleEndFnSingleton( PRServSemReq *semReq, SlaveVP *requestingSlv,
 24.1158 -                        PRServSemEnv *semEnv )
 24.1159 +void
 24.1160 +PRServ__handleEndFnSingleton( PRServLangReq *langReq, SlaveVP *requestingSlv,
 24.1161 +                        PRServLangEnv *langEnv )
 24.1162   {
 24.1163     PRServSingleton   *singleton;
 24.1164  
 24.1165 -         DEBUG__printf1(dbgRqstHdlr,"EndFnSingleton request from processor %d",requestingSlv->slaveID)
 24.1166 +         DEBUG__printf1(dbgRqstHdlr,"EndFnSingleton request from processor %d",requestingSlv->slaveNum)
 24.1167     
 24.1168 -   singleton = &(semEnv->fnSingletons[ semReq->singletonID ]);
 24.1169 -   handleEndSingleton_helper( singleton, requestingSlv, semEnv );
 24.1170 +   singleton = &(langEnv->fnSingletons[ langReq->singletonID ]);
 24.1171 +   PRServ__handleEndSingleton_helper( singleton, requestingSlv, langEnv );
 24.1172    }
 24.1173 -void inline
 24.1174 -handleEndDataSingleton( PRServSemReq *semReq, SlaveVP *requestingSlv,
 24.1175 -                        PRServSemEnv *semEnv )
 24.1176 +void
 24.1177 +PRServ__handleEndDataSingleton( PRServLangReq *langReq, SlaveVP *requestingSlv,
 24.1178 +                        PRServLangEnv *langEnv )
 24.1179   {
 24.1180     PRServSingleton   *singleton;
 24.1181  
 24.1182 -         DEBUG__printf1(dbgRqstHdlr,"EndDataSingleton request from processor %d",requestingSlv->slaveID)
 24.1183 +         DEBUG__printf1(dbgRqstHdlr,"EndDataSingleton request from processor %d",requestingSlv->slaveNum)
 24.1184     
 24.1185 -   singleton = *(semReq->singletonPtrAddr);
 24.1186 -   handleEndSingleton_helper( singleton, requestingSlv, semEnv );
 24.1187 +   singleton = *(langReq->singletonPtrAddr);
 24.1188 +   PRServ__handleEndSingleton_helper( singleton, requestingSlv, langEnv );
 24.1189    }
 24.1190  
 24.1191  
 24.1192 @@ -1173,11 +159,11 @@
 24.1193   * pointer out of the request and call it, then resume the VP.
 24.1194   */
 24.1195  void
 24.1196 -handleAtomic( PRServSemReq *semReq, SlaveVP *requestingSlv, PRServSemEnv *semEnv )
 24.1197 +PRServ__handleAtomic( PRServLangReq *langReq, SlaveVP *requestingSlv, PRServLangEnv *langEnv )
 24.1198   {
 24.1199 -         DEBUG__printf1(dbgRqstHdlr,"Atomic request from processor %d",requestingSlv->slaveID)
 24.1200 -   semReq->fnToExecInMaster( semReq->dataForFn );
 24.1201 -   PR_PI__make_slave_ready( requestingSlv, semEnv );
 24.1202 +         DEBUG__printf1(dbgRqstHdlr,"Atomic request from processor %d",requestingSlv->slaveNum)
 24.1203 +   langReq->fnToExecInMaster( langReq->dataForFn );
 24.1204 +   PR_PI__make_slave_ready( requestingSlv, langEnv );
 24.1205   }
 24.1206  
 24.1207  /*First, it looks at the VP's semantic data, to see the highest transactionID
 24.1208 @@ -1195,35 +181,35 @@
 24.1209   *If NULL, then write requesting into the field and resume.
 24.1210   */
 24.1211  void
 24.1212 -handleTransStart( PRServSemReq *semReq, SlaveVP *requestingSlv,
 24.1213 -                  PRServSemEnv *semEnv )
 24.1214 - { PRServSemData *semData;
 24.1215 -   TransListElem *nextTransElem;
 24.1216 +PRServ__handleTransStart( PRServLangReq *langReq, SlaveVP *requestingSlv,
 24.1217 +                  PRServLangEnv *langEnv )
 24.1218 + { PRServLangData *langData;
 24.1219 +   PRServTransListElem *nextTransElem;
 24.1220  
 24.1221 -         DEBUG__printf1(dbgRqstHdlr,"TransStart request from processor %d",requestingSlv->slaveID)
 24.1222 +         DEBUG__printf1(dbgRqstHdlr,"TransStart request from processor %d",requestingSlv->slaveNum)
 24.1223     
 24.1224        //check ordering of entering transactions is correct
 24.1225 -   semData = requestingSlv->semanticData;
 24.1226 -   if( semData->highestTransEntered > semReq->transID )
 24.1227 +   langData = PR_PI__give_lang_data_from_slave(requestingSlv, PRServ_MAGIC_NUMBER);
 24.1228 +   if( langData->highestTransEntered > langReq->transID )
 24.1229      {    //throw PR exception, which shuts down PR.
 24.1230        PR_PI__throw_exception( "transID smaller than prev", requestingSlv, NULL);
 24.1231      }
 24.1232        //add this trans ID to the list of transactions entered -- check when
 24.1233        // end a transaction
 24.1234 -   semData->highestTransEntered = semReq->transID;
 24.1235 -   nextTransElem = PR_PI__malloc( sizeof(TransListElem) );
 24.1236 -   nextTransElem->transID = semReq->transID;
 24.1237 -   nextTransElem->nextTrans = semData->lastTransEntered;
 24.1238 -   semData->lastTransEntered = nextTransElem;
 24.1239 +   langData->highestTransEntered = langReq->transID;
 24.1240 +   nextTransElem = PR_PI__malloc( sizeof(PRServTransListElem) );
 24.1241 +   nextTransElem->transID = langReq->transID;
 24.1242 +   nextTransElem->nextTrans = langData->lastTransEntered;
 24.1243 +   langData->lastTransEntered = nextTransElem;
 24.1244  
 24.1245        //get the structure for this transaction ID
 24.1246     PRServTrans *
 24.1247 -   transStruc = &(semEnv->transactionStrucs[ semReq->transID ]);
 24.1248 +   transStruc = &(langEnv->transactionStrucs[ langReq->transID ]);
 24.1249  
 24.1250     if( transStruc->VPCurrentlyExecuting == NULL )
 24.1251      {
 24.1252        transStruc->VPCurrentlyExecuting = requestingSlv;
 24.1253 -      PR_PI__make_slave_ready( requestingSlv, semEnv );
 24.1254 +      PR_PI__make_slave_ready( requestingSlv, langEnv );
 24.1255      }
 24.1256     else
 24.1257      {    //note, might make future things cleaner if save request with VP and
 24.1258 @@ -1248,15 +234,15 @@
 24.1259   * resume both.
 24.1260   */
 24.1261  void
 24.1262 -handleTransEnd(PRServSemReq *semReq, SlaveVP *requestingSlv, PRServSemEnv *semEnv)
 24.1263 - { PRServSemData    *semData;
 24.1264 +PRServ__handleTransEnd(PRServLangReq *langReq, SlaveVP *requestingSlv, PRServLangEnv *langEnv)
 24.1265 + { PRServLangData    *langData;
 24.1266     SlaveVP     *waitingSlv;
 24.1267     PRServTrans      *transStruc;
 24.1268 -   TransListElem *lastTrans;
 24.1269 +   PRServTransListElem *lastTrans;
 24.1270     
 24.1271 -         DEBUG__printf1(dbgRqstHdlr,"TransEnd request from processor %d",requestingSlv->slaveID)
 24.1272 +         DEBUG__printf1(dbgRqstHdlr,"TransEnd request from processor %d",requestingSlv->slaveNum)
 24.1273     
 24.1274 -   transStruc = &(semEnv->transactionStrucs[ semReq->transID ]);
 24.1275 +   transStruc = &(langEnv->transactionStrucs[ langReq->transID ]);
 24.1276  
 24.1277        //make sure transaction ended in same VP as started it.
 24.1278     if( transStruc->VPCurrentlyExecuting != requestingSlv )
 24.1279 @@ -1265,21 +251,163 @@
 24.1280      }
 24.1281  
 24.1282        //make sure nesting is correct -- last ID entered should == this ID
 24.1283 -   semData = requestingSlv->semanticData;
 24.1284 -   lastTrans = semData->lastTransEntered;
 24.1285 -   if( lastTrans->transID != semReq->transID )
 24.1286 +   langData = PR_PI__give_lang_data_from_slave(requestingSlv, PRServ_MAGIC_NUMBER);
 24.1287 +   lastTrans = langData->lastTransEntered;
 24.1288 +   if( lastTrans->transID != langReq->transID )
 24.1289      {
 24.1290        PR_PI__throw_exception( "trans incorrectly nested", requestingSlv, NULL );
 24.1291      }
 24.1292  
 24.1293 -   semData->lastTransEntered = semData->lastTransEntered->nextTrans;
 24.1294 +   langData->lastTransEntered = langData->lastTransEntered->nextTrans;
 24.1295  
 24.1296  
 24.1297     waitingSlv = readPrivQ( transStruc->waitingVPQ );
 24.1298     transStruc->VPCurrentlyExecuting = waitingSlv;
 24.1299  
 24.1300     if( waitingSlv != NULL )
 24.1301 -      PR_PI__make_slave_ready( waitingSlv, semEnv );
 24.1302 +      PR_PI__make_slave_ready( waitingSlv, langEnv );
 24.1303  
 24.1304 -   PR_PI__make_slave_ready( requestingSlv, semEnv );
 24.1305 +   PR_PI__make_slave_ready( requestingSlv, langEnv );
 24.1306   }
 24.1307 +
 24.1308 +
 24.1309 +//==========================================================================
 24.1310 +//                           Helpers
 24.1311 +//
 24.1312 +void
 24.1313 +PRServ__make_task_ready( void *taskStub, void *_langEnv )
 24.1314 + {
 24.1315 +   writePrivQ( taskStub, ((PRServLangEnv*)_langEnv)->taskReadyQ );
 24.1316 + }
 24.1317 +
 24.1318 +
 24.1319 +/*Proto Runtime has a special call-chain for resuming a slaveVP.  The langlet
 24.1320 + * supplies a function to perform the resume, but then registers it with
 24.1321 + * PR, and instead calls PR's version..  PR then decides whether to handle
 24.1322 + * the resume itself, or pass resume along to this registered handler. 
 24.1323 + */
 24.1324 +void
 24.1325 +PRServ__resume_slave( SlaveVP *slave, void *_langEnv )
 24.1326 + { PRServLangEnv *langEnv = (PRServLangEnv *)_langEnv;
 24.1327 + 
 24.1328 +      //both suspended tasks and suspended explicit slaves resumed with this
 24.1329 +   writePrivQ( slave, langEnv->slavesReadyToResumeQ );
 24.1330 +//PR handles this..   PR_int__set_work_in_lang_env(langEnv);
 24.1331 +   
 24.1332 +   #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS
 24.1333 +/*
 24.1334 +   int lastRecordIdx = slave->counter_history_array_info->numInArray -1;
 24.1335 +   CounterRecord* lastRecord = slave->counter_history[lastRecordIdx];
 24.1336 +   saveLowTimeStampCountInto(lastRecord->unblocked_timestamp);
 24.1337 +*/
 24.1338 +   #endif
 24.1339 +   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
 24.1340 +   slave->numTimesAssignedToASlot++; //Somewhere here!
 24.1341 +   Unit newU;
 24.1342 +   newU.vp = slave->slaveNum;
 24.1343 +   newU.task = slave->numTimesAssignedToASlot;
 24.1344 +   addToListOfArrays(Unit,newU,langEnv->unitList);
 24.1345 +   
 24.1346 +   if (slave->numTimesAssignedToASlot > 1)
 24.1347 +    { Dependency newD;
 24.1348 +      newD.from_vp = slave->slaveNum;
 24.1349 +      newD.from_task = slave->numTimesAssignedToASlot - 1;
 24.1350 +      newD.to_vp = slave->slaveNum;
 24.1351 +      newD.to_task = slave->numTimesAssignedToASlot;
 24.1352 +      addToListOfArrays(Dependency, newD ,langEnv->ctlDependenciesList);  
 24.1353 +    }
 24.1354 +   #endif
 24.1355 + }
 24.1356 +
 24.1357 +void
 24.1358 +PRServ__handleDissipateSeed(void *langReq, SlaveVP *seedSlv, VSsLangEnv *langEnv )
 24.1359 + { 
 24.1360 + 
 24.1361 +         DEBUG__printf1(dbgRqstHdlr,"Dissipate in PRServ %d",
 24.1362 +                                                     requestingSlv->slaveNum);
 24.1363 +   //This should only ever be called for the seed slave -- for which there's
 24.1364 +   // nothing to do..
 24.1365 +   if( seedSlv->typeOfVP != SeedSlv )
 24.1366 +    {
 24.1367 +      PR_int__throw_exception( "PR__end_seed called on non-seed slave\n", NULL, NULL);
 24.1368 +    }
 24.1369 + }
 24.1370 +
 24.1371 +void
 24.1372 +PRServ__handle_end_process_from_inside( void *langReq, SlaveVP *reqSlave, PRServLangEnv *langEnv )
 24.1373 + { PR_SS__end_process_normally( reqSlave->processSlaveIsIn );
 24.1374 + }
 24.1375 +
 24.1376 +
 24.1377 +/*Initialize semantic data struct..  this initializer doesn't need any input,
 24.1378 + * but some languages may need something from inside the request that was sent
 24.1379 + * to create a slave..  in that case, just make initializer do the malloc then
 24.1380 + * use the PR_PI__give_lang_data  inside the create handler, and fill in the
 24.1381 + * langData values there.
 24.1382 + */
 24.1383 +void * 
 24.1384 +PRServ__create_lang_data_in_slave( SlaveVP *slave )
 24.1385 + { PRServLangData *langData;
 24.1386 +
 24.1387 + 
 24.1388 +   langData = PR_PI__create_lang_data_in_slave( sizeof(PRServLangData), 
 24.1389 +                                 &PRServ__free_lang_data, slave, PRServ_MAGIC_NUMBER );
 24.1390 +   
 24.1391 +   langData->highestTransEntered = -1;
 24.1392 +   langData->lastTransEntered    = NULL;
 24.1393 +   return langData;
 24.1394 + }
 24.1395 +
 24.1396 +
 24.1397 +/*Register this by passing a pointer to this to PR's lang data creator Fn
 24.1398 + * 
 24.1399 + *It deletes all the transactions that the slave had entered..
 24.1400 + *Probably a bug -- need to do something more to free blocked slaves waiting. 
 24.1401 + *
 24.1402 + *At some point, may change PR so that it recycles langData, in which case this
 24.1403 + * only gets called when a process shuts down..  at that point, PR will call
 24.1404 + * dissipate on all the slaves it has in the recycle Q.
 24.1405 + */
 24.1406 +void
 24.1407 +PRServ__free_lang_data( void *_langData )
 24.1408 + { PRServLangData *langData;
 24.1409 +   PRServTransListElem *transElem, *nextTransElem;
 24.1410 +
 24.1411 +   langData = (PRServLangData *)_langData;
 24.1412 +   transElem = langData->lastTransEntered;
 24.1413 +   
 24.1414 +   //Each trans the slave has entered was saved in a linked list elem inside
 24.1415 +   // lang data -- delete those linked list elements
 24.1416 +   //Bug: if this is not part of shutdown, then update state of transactions
 24.1417 +   // to free blocked VPs
 24.1418 +   while( transElem != NULL)
 24.1419 +    { nextTransElem = transElem->nextTrans;
 24.1420 +      PR_int__free( transElem );
 24.1421 +      transElem = nextTransElem;
 24.1422 +    }
 24.1423 +   PR_PI__free( _langData );
 24.1424 + }
 24.1425 +
 24.1426 +
 24.1427 +void
 24.1428 +PRServ__lang_meta_task_freer( void *_langMetaTask )
 24.1429 + { //no PRServ meta tasks created, so nothing to do
 24.1430 + }
 24.1431 +
 24.1432 +
 24.1433 +/*Will be used by a langData recycler, when (and if) such a thing added
 24.1434 + * to PR
 24.1435 + */
 24.1436 +void 
 24.1437 +resetPRServLangData( void *_langData ) 
 24.1438 + { PRServLangData *langData = (PRServLangData *)_langData;
 24.1439 +   
 24.1440 +   langData->highestTransEntered = -1;
 24.1441 +   langData->lastTransEntered    = NULL;
 24.1442 + }
 24.1443 +
 24.1444 +//==========================================================================
 24.1445 +//
 24.1446 +//
 24.1447 +
 24.1448 +
    25.1 --- a/Services_Offered_by_PR/Services_Language/PRServ_Request_Handlers.h	Tue Feb 05 20:23:27 2013 -0800
    25.2 +++ b/Services_Offered_by_PR/Services_Language/PRServ_Request_Handlers.h	Sat Mar 02 09:43:45 2013 -0800
    25.3 @@ -1,5 +1,5 @@
    25.4  /*
    25.5 - *  Copyright 2009 OpenSourceStewardshipFoundation.org
    25.6 + *  Copyright 2009 OpenSourceResearchInstitute.org
    25.7   *  Licensed under GNU General Public License version 2
    25.8   *
    25.9   * Author: seanhalle@yahoo.com
   25.10 @@ -14,46 +14,55 @@
   25.11  /*This header defines everything specific to the PRServ semantic plug-in
   25.12   */
   25.13  
   25.14 +void
   25.15 +PRServ__handleMalloc( PRServLangReq *langReq, SlaveVP *requestingSlv, PRServLangEnv *langEnv);
   25.16 +void
   25.17 +PRServ__handleFree( PRServLangReq *langReq, SlaveVP *requestingSlv, PRServLangEnv *langEnv );
   25.18 +
   25.19 +//============================================
   25.20 +void
   25.21 +PRServ__handleStartFnSingleton( PRServLangReq *langReq, SlaveVP *reqstingSlv,
   25.22 +                      PRServLangEnv *langEnv );
   25.23 +void
   25.24 +PRServ__handleEndFnSingleton( PRServLangReq *langReq, SlaveVP *requestingSlv,
   25.25 +                    PRServLangEnv *langEnv );
   25.26  inline void
   25.27 -handleSubmitTask( PRServSemReq *semReq, PRServSemEnv *semEnv);
   25.28 +PRServ__handleStartDataSingleton( PRServLangReq *langReq, SlaveVP *reqstingSlv,
   25.29 +                      PRServLangEnv *langEnv );
   25.30  inline void
   25.31 -handleEndTask( PRServSemReq *semReq, PRServSemEnv *semEnv);
   25.32 -inline void
   25.33 -handleSendTypeTo( PRServSemReq *semReq, PRServSemEnv *semEnv);
   25.34 -inline void
   25.35 -handleSendFromTo( PRServSemReq *semReq, PRServSemEnv *semEnv);
   25.36 -inline void
   25.37 -handleReceiveTypeTo( PRServSemReq *semReq, PRServSemEnv *semEnv);
   25.38 -inline void
   25.39 -handleReceiveFromTo( PRServSemReq *semReq, PRServSemEnv *semEnv);
   25.40 -inline void
   25.41 -handleTaskwait(PRServSemReq *semReq, SlaveVP *requestingSlv, PRServSemEnv *semEnv);
   25.42 +PRServ__handleEndDataSingleton( PRServLangReq *langReq, SlaveVP *requestingSlv,
   25.43 +                    PRServLangEnv *langEnv );
   25.44 +void
   25.45 +PRServ__handleTransStart( PRServLangReq *langReq, SlaveVP *requestingSlv,
   25.46 +                  PRServLangEnv *langEnv );
   25.47 +void
   25.48 +PRServ__handleTransEnd(PRServLangReq *langReq, SlaveVP *requestingSlv, PRServLangEnv*langEnv);
   25.49  
   25.50 -inline void
   25.51 -handleMalloc( PRServSemReq *semReq, SlaveVP *requestingSlv, PRServSemEnv *semEnv);
   25.52 -inline void
   25.53 -handleFree( PRServSemReq *semReq, SlaveVP *requestingSlv, PRServSemEnv *semEnv );
   25.54 -inline void
   25.55 -handleTransEnd(PRServSemReq *semReq, SlaveVP *requestingSlv, PRServSemEnv*semEnv);
   25.56 -inline void
   25.57 -handleTransStart( PRServSemReq *semReq, SlaveVP *requestingSlv,
   25.58 -                  PRServSemEnv *semEnv );
   25.59 -inline void
   25.60 -handleAtomic( PRServSemReq *semReq, SlaveVP *requestingSlv, PRServSemEnv *semEnv);
   25.61 -inline void
   25.62 -handleStartFnSingleton( PRServSemReq *semReq, SlaveVP *reqstingSlv,
   25.63 -                      PRServSemEnv *semEnv );
   25.64 -inline void
   25.65 -handleEndFnSingleton( PRServSemReq *semReq, SlaveVP *requestingSlv,
   25.66 -                    PRServSemEnv *semEnv );
   25.67 -inline void
   25.68 -handleStartDataSingleton( PRServSemReq *semReq, SlaveVP *reqstingSlv,
   25.69 -                      PRServSemEnv *semEnv );
   25.70 -inline void
   25.71 -handleEndDataSingleton( PRServSemReq *semReq, SlaveVP *requestingSlv,
   25.72 -                    PRServSemEnv *semEnv );
   25.73 -inline void
   25.74 -free_task_stub( PRMetaTask *stubToFree );
   25.75 +void
   25.76 +PRServ__handleAtomic( PRServLangReq *langReq, SlaveVP *requestingSlv, PRServLangEnv *langEnv);
   25.77 +//==================================
   25.78 +void
   25.79 +PRServ__make_task_ready( void *taskStub, void *_langEnv );
   25.80 +void
   25.81 +PRServ__resume_slave( SlaveVP *slave, void *langEnv );
   25.82 +
   25.83 +void
   25.84 +PRServ__handleDissipateSeed(void *langReq, SlaveVP *seedSlv, PRServLangEnv *langEnv );
   25.85 +
   25.86 +void
   25.87 +PRServ__handle_end_process_from_inside( void *langReq, SlaveVP *reqSlave, PRServLangEnv *langEnv );
   25.88 +
   25.89 +void
   25.90 +PRServ__handle_shutdown( void *_langEnv );
   25.91 +
   25.92 +void * 
   25.93 +PRServ__create_lang_data_in_slave( SlaveVP *slave );
   25.94 +
   25.95 +void
   25.96 +PRServ__free_lang_data( void *_langData );
   25.97 +
   25.98 +void
   25.99 +PRServ__lang_meta_task_freer( void *_langMetaTask );
  25.100  
  25.101  
  25.102  #endif	/* _PRServ_REQ_H */
    26.1 --- a/Services_Offered_by_PR/Services_Language/PRServ_SS.c	Tue Feb 05 20:23:27 2013 -0800
    26.2 +++ b/Services_Offered_by_PR/Services_Language/PRServ_SS.c	Sat Mar 02 09:43:45 2013 -0800
    26.3 @@ -12,8 +12,7 @@
    26.4  #include "Hash_impl/PrivateHash.h"
    26.5  
    26.6  #include "PRServ.h"
    26.7 -#include "Measurement/PRServ_Counter_Recording.h"
    26.8 -
    26.9 +#include "PR_impl/Services_Offered_by_PR/Measurement_and_Stats/PR_MEAS__Counter_Recording.h"
   26.10  //==========================================================================
   26.11  
   26.12  
   26.13 @@ -22,90 +21,69 @@
   26.14  
   26.15  /*
   26.16   */
   26.17 -void
   26.18 +PRServLangEnv *
   26.19  PRServ__start( SlaveVP *seedSlv )
   26.20 - { PRServSemEnv       *semEnv;
   26.21 -   int32            i, coreNum, slotNum;
   26.22 -   PRServSemData      *semData;
   26.23 -   PRServTaskStub     *threadTaskStub, *parentTaskStub;
   26.24 + { PRServLangEnv       *langEnv;
   26.25 +   int32                i;
   26.26     
   26.27 -   semEnv = PR_WL__malloc( sizeof(PRServSemEnv) );
   26.28 +   langEnv = 
   26.29 +         PR_SS__create_lang_env( sizeof(PRServLangEnv), seedSlv, PRServ_MAGIC_NUMBER);
   26.30     
   26.31 -   PR_SS__register_langlets_semEnv( semEnv, seedSlv, PRServ_MAGIC_NUMBER );
   26.32 + 
   26.33 +      //create the ready queues
   26.34 +   langEnv->slavesReadyToResumeQ = makePRQ();
   26.35 +   langEnv->taskReadyQ           = makePRQ();
   26.36     
   26.37 -      //seed slave is a thread slave, so make a thread's task stub for it
   26.38 -      // and then make another to stand for the seed's parent task.  Make
   26.39 -      // the parent be already ended, and have one child (the seed).  This
   26.40 -      // will make the dissipate handler do the right thing when the seed
   26.41 -      // is dissipated.
   26.42 -   threadTaskStub = create_thread_task_stub( initData );
   26.43 -   parentTaskStub = create_thread_task_stub( NULL );
   26.44 -   parentTaskStub->isEnded = TRUE;
   26.45 -   parentTaskStub->numLiveChildThreads = 1; //so dissipate works for seed
   26.46 -   threadTaskStub->parentTaskStub = parentTaskStub;
   26.47 -   
   26.48 -   PR_SS__set_langMetaTask_for_seedSlv( threadTaskStub, seedSlv );
   26.49 -   
   26.50 -      //Hook up the semantic layer's plug-ins to the Master virt procr
   26.51 -   PR_SS__register_create_task_handler(     &createTaskHandler, seedVP, PRServ_MAGIC_NUMBER );
   26.52 -   PR_SS__register_end_task_handler(        &endTaskHandler, seedVP, PRServ_MAGIC_NUMBER );
   26.53 -   PR_SS__register_create_slave_handler(    &createThreadHandler, seedVP, PRServ_MAGIC_NUMBER );
   26.54 -   PR_SS__register_dissipate_slave_handler( &endThreadHandler, seedVP, PRServ_MAGIC_NUMBER );
   26.55 -   PR_SS__register_request_handler(         &PRServ__Request_Handler, seedVP, PRServ_MAGIC_NUMBER );
   26.56 -   PR_SS__register_assigner(                &PRServ__assign_work_to_slot, seedVP, PRServ_MAGIC_NUMBER );
   26.57 -    RequestHandler createInitialSemDataFn;
   26.58 -   RequestHandler resetSemDataFn;
   26.59 -  
   26.60 +      //register the langlet's handlers with PR
   26.61 +   PR_SS__register_assigner(                &PRServ__assign_work_to_slot, seedSlv, PRServ_MAGIC_NUMBER );
   26.62 +   PR_SS__register_lang_shutdown_handler(        &PRServ__handle_shutdown, seedSlv, PRServ_MAGIC_NUMBER );
   26.63 +   PR_SS__register_lang_data_creator(       &PRServ__create_lang_data_in_slave, seedSlv, PRServ_MAGIC_NUMBER );
   26.64 +//   PR_SS__register_lang_meta_task_creator(  &PRServ__create_empty_lang_meta_task_in_slave, seedSlv, PRServ_MAGIC_NUMBER );
   26.65 +   PR_SS__register_make_slave_ready_fn(     &PRServ__resume_slave, seedSlv, PRServ_MAGIC_NUMBER );
   26.66 +   PR_SS__register_make_task_ready_fn(      &PRServ__make_task_ready, seedSlv, PRServ_MAGIC_NUMBER );
   26.67 +
   26.68     #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS
   26.69 -   _PRTopEnv->counterHandler = &PRServ__counter_handler;
   26.70 -   PRServ__init_counter_data_structs();
   26.71 +   _PRTopEnv->counterHandler = &PR_MEAS__counter_handler;
   26.72 +   PR_MEAS__init_counter_data_structs_for_lang( seedSlv, PRServ_MAGIC_NUMBER );
   26.73     #endif
   26.74  
   26.75 -
   26.76 -      //create the ready queues, hash tables used for matching and so forth
   26.77 -   semEnv->slavesReadyToResumeQ = makePRQ();
   26.78 -   semEnv->taskReadyQ           = makePRQ();
   26.79     
   26.80 -   semEnv->argPtrHashTbl  = makeHashTable32( 16, &PR_int__free );
   26.81 -   semEnv->commHashTbl    = makeHashTable32( 16, &PR_int__free );
   26.82 -   
   26.83 -   semEnv->nextCoreToGetNewSlv = 0;
   26.84 -   
   26.85 -
   26.86     //TODO: bug -- turn these arrays into dyn arrays to eliminate limit
   26.87 -   //semanticEnv->singletonHasBeenExecutedFlags = makeDynArrayInfo( );
   26.88 -   //semanticEnv->transactionStrucs = makeDynArrayInfo( );
   26.89 -   for( i = 0; i < NUM_STRUCS_IN_SEM_ENV; i++ )
   26.90 +   //langEnv->singletonHasBeenExecutedFlags = makeDynArrayInfo( );
   26.91 +   //langEnv->transactionStrucs = makeDynArrayInfo( );
   26.92 +   for( i = 0; i < NUM_STRUCS_IN_LANG_ENV; i++ )
   26.93      {
   26.94 -      semEnv->fnSingletons[i].endInstrAddr      = NULL;
   26.95 -      semEnv->fnSingletons[i].hasBeenStarted    = FALSE;
   26.96 -      semEnv->fnSingletons[i].hasFinished       = FALSE;
   26.97 -      semEnv->fnSingletons[i].waitQ             = makePRQ();
   26.98 -      semEnv->transactionStrucs[i].waitingVPQ   = makePRQ();
   26.99 +      langEnv->fnSingletons[i].endInstrAddr      = NULL;
  26.100 +      langEnv->fnSingletons[i].hasBeenStarted    = FALSE;
  26.101 +      langEnv->fnSingletons[i].hasFinished       = FALSE;
  26.102 +      langEnv->fnSingletons[i].waitQ             = makePRQ();
  26.103 +      langEnv->transactionStrucs[i].waitingVPQ   = makePRQ();
  26.104      }
  26.105  
  26.106  
  26.107     #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  26.108 -   semEnv->unitList = makeListOfArrays(sizeof(Unit),128);
  26.109 -   semEnv->ctlDependenciesList = makeListOfArrays(sizeof(Dependency),128);
  26.110 -   semEnv->commDependenciesList = makeListOfArrays(sizeof(Dependency),128);
  26.111 -   semEnv->dynDependenciesList = makeListOfArrays(sizeof(Dependency),128);
  26.112 -   semEnv->ntonGroupsInfo = makePrivDynArrayOfSize((void***)&(semEnv->ntonGroups),8);
  26.113 +   langEnv->unitList = makeListOfArrays(sizeof(Unit),128);
  26.114 +   langEnv->ctlDependenciesList = makeListOfArrays(sizeof(Dependency),128);
  26.115 +   langEnv->commDependenciesList = makeListOfArrays(sizeof(Dependency),128);
  26.116 +   langEnv->dynDependenciesList = makeListOfArrays(sizeof(Dependency),128);
  26.117 +   langEnv->ntonGroupsInfo = makePrivDynArrayOfSize((void***)&(langEnv->ntonGroups),8);
  26.118     
  26.119 -   semEnv->hwArcs = makeListOfArrays(sizeof(Dependency),128);
  26.120 -   memset(semEnv->last_in_slot,0,sizeof(NUM_CORES * NUM_ANIM_SLOTS * sizeof(Unit)));
  26.121 +   langEnv->hwArcs = makeListOfArrays(sizeof(Dependency),128);
  26.122 +   memset(langEnv->last_in_slot,0,sizeof(NUM_CORES * NUM_ANIM_SLOTS * sizeof(Unit)));
  26.123     #endif
  26.124 +
  26.125 +   return langEnv;
  26.126   }
  26.127  
  26.128  
  26.129 -/*Frees any memory allocated by PRServ__init() then calls PR_int__shutdown
  26.130 +/*This shuts down the langlet
  26.131 + * Frees any memory allocated by PRServ__init() and deletes any slaves or tasks
  26.132 + * still in ready Qs.
  26.133   */
  26.134  void
  26.135 -PRServ__cleanup_after_shutdown()
  26.136 - { PRServSemEnv *semanticEnv;
  26.137 +PRServ__handle_shutdown( void *_langEnv )
  26.138 + { PRServLangEnv *langEnv = (PRServLangEnv *)_langEnv;
  26.139     
  26.140 -   semanticEnv = _PRTopEnv->semanticEnv;
  26.141 -
  26.142     #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  26.143     //UCC
  26.144     FILE* output;
  26.145 @@ -131,10 +109,10 @@
  26.146          //set_dot_file(output);
  26.147          //FIXME:  first line still depends on counters being enabled, replace w/ unit struct!
  26.148          //forAllInDynArrayDo(_PRTopEnv->counter_history_array_info, &print_dot_node_info );
  26.149 -        forAllInListOfArraysDo(semanticEnv->unitList, &print_unit_to_file);
  26.150 -        forAllInListOfArraysDo( semanticEnv->commDependenciesList, &print_comm_dependency_to_file );
  26.151 -        forAllInListOfArraysDo( semanticEnv->ctlDependenciesList, &print_ctl_dependency_to_file );
  26.152 -        forAllInDynArrayDo(semanticEnv->ntonGroupsInfo,&print_nton_to_file);
  26.153 +        forAllInListOfArraysDo(langEnv->unitList, &print_unit_to_file);
  26.154 +        forAllInListOfArraysDo( langEnv->commDependenciesList, &print_comm_dependency_to_file );
  26.155 +        forAllInListOfArraysDo( langEnv->ctlDependenciesList, &print_ctl_dependency_to_file );
  26.156 +        forAllInDynArrayDo(langEnv->ntonGroupsInfo,&print_nton_to_file);
  26.157          //fprintf(output,"}\n");
  26.158          fflush(output);
  26.159  
  26.160 @@ -164,11 +142,11 @@
  26.161          //set_dot_file(output);
  26.162          //FIXME:  first line still depends on counters being enabled, replace w/ unit struct!
  26.163          //forAllInDynArrayDo(_PRTopEnv->counter_history_array_info, &print_dot_node_info );
  26.164 -        forAllInListOfArraysDo( semanticEnv->unitList, &print_unit_to_file );
  26.165 -        forAllInListOfArraysDo( semanticEnv->commDependenciesList, &print_comm_dependency_to_file );
  26.166 -        forAllInListOfArraysDo( semanticEnv->ctlDependenciesList, &print_ctl_dependency_to_file );
  26.167 -        forAllInListOfArraysDo( semanticEnv->dynDependenciesList, &print_dyn_dependency_to_file );
  26.168 -        forAllInListOfArraysDo( semanticEnv->hwArcs, &print_hw_dependency_to_file );
  26.169 +        forAllInListOfArraysDo( langEnv->unitList, &print_unit_to_file );
  26.170 +        forAllInListOfArraysDo( langEnv->commDependenciesList, &print_comm_dependency_to_file );
  26.171 +        forAllInListOfArraysDo( langEnv->ctlDependenciesList, &print_ctl_dependency_to_file );
  26.172 +        forAllInListOfArraysDo( langEnv->dynDependenciesList, &print_dyn_dependency_to_file );
  26.173 +        forAllInListOfArraysDo( langEnv->hwArcs, &print_hw_dependency_to_file );
  26.174          //fprintf(output,"}\n");
  26.175          fflush(output);
  26.176  
  26.177 @@ -179,10 +157,10 @@
  26.178     }
  26.179     
  26.180     
  26.181 -   freeListOfArrays(semanticEnv->unitList);
  26.182 -   freeListOfArrays(semanticEnv->commDependenciesList);
  26.183 -   freeListOfArrays(semanticEnv->ctlDependenciesList);
  26.184 -   freeListOfArrays(semanticEnv->dynDependenciesList);
  26.185 +   freeListOfArrays(langEnv->unitList);
  26.186 +   freeListOfArrays(langEnv->commDependenciesList);
  26.187 +   freeListOfArrays(langEnv->ctlDependenciesList);
  26.188 +   freeListOfArrays(langEnv->dynDependenciesList);
  26.189     
  26.190     #endif
  26.191  #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS    
  26.192 @@ -201,12 +179,13 @@
  26.193      printf("Saving Counter measurements to File: %s ...\n", filename);
  26.194      output = fopen(filename,"w+");
  26.195      if(output!=NULL){
  26.196 +        int i;
  26.197          set_counter_file(output);
  26.198 -        int i;
  26.199 -        for(i=0;i<NUM_CORES;i++){
  26.200 -            forAllInListOfArraysDo( semanticEnv->counterList[i], &print_counter_events_to_file );
  26.201 -            fflush(output);
  26.202 -        }
  26.203 +        for(i=0;i<NUM_CORES;i++)
  26.204 +         {
  26.205 +           forAllInListOfArraysDo( langEnv->counterList[i], &PR_MEAS__print_counter_event_to_file );
  26.206 +           fflush(output);
  26.207 +         }
  26.208  
  26.209      } else
  26.210          printf("Opening UCC file failed. Please check that folder \"counters\" exists in run directory and has write permission.\n");
  26.211 @@ -215,21 +194,39 @@
  26.212     }
  26.213      
  26.214  #endif
  26.215 -/* It's all allocated inside PR's big chunk -- that's about to be freed, so
  26.216 - *  nothing to do here
  26.217     
  26.218 -
  26.219 -   for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
  26.220 +   //Things to free:
  26.221 +   // tasks and slaves in ready Qs
  26.222 +   // ready Qs
  26.223 +   // tasks and slaves in the comm hash table
  26.224 +   // comm hash table
  26.225 +   // tasks in the argPtrHashTbl
  26.226 +   // the argPtrHashTbl
  26.227 +   PrivQueueStruc *queue;
  26.228 +   SlaveVP *slave;
  26.229 +   
  26.230 +   //dissipate any slaves still in the readyQ, because this is last lang
  26.231 +   queue = langEnv->slavesReadyToResumeQ;
  26.232 +   slave = readPrivQ( queue );
  26.233 +   while( slave != NULL )
  26.234 +    { 
  26.235 +      PR_int__recycle_slaveVP( slave ); //recycler is for all of PR
  26.236 +      slave = readPrivQ( queue );
  26.237 +    }
  26.238 +   freePrivQ( queue );
  26.239 +   
  26.240 +   //no any tasks in the readyQ
  26.241 +   queue = langEnv->taskReadyQ;
  26.242 +   freePrivQ( queue );
  26.243 +      
  26.244 +   int32 i;
  26.245 +   for( i = 0; i < NUM_STRUCS_IN_LANG_ENV; i++ )
  26.246      {
  26.247 -      PR_int__free( semanticEnv->readyVPQs[coreIdx]->startOfData );
  26.248 -      PR_int__free( semanticEnv->readyVPQs[coreIdx] );
  26.249 +      freePrivQ( langEnv->fnSingletons[i].waitQ );
  26.250 +      freePrivQ( langEnv->transactionStrucs[i].waitingVPQ );
  26.251      }
  26.252 -   PR_int__free( semanticEnv->readyVPQs );
  26.253     
  26.254 -   freeHashTable( semanticEnv->commHashTbl );
  26.255 -   PR_int__free( _PRTopEnv->semanticEnv );
  26.256 - */
  26.257 -   PR_SS__cleanup_at_end_of_shutdown();
  26.258 +   PR_int__remove_lang_env_from_process_and_free( langEnv ); 
  26.259   }
  26.260  
  26.261  
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/Services_Offered_by_PR/Services_Language/PRServ_singleton_asm.s	Sat Mar 02 09:43:45 2013 -0800
    27.3 @@ -0,0 +1,21 @@
    27.4 +
    27.5 +//Assembly code takes the return addr off the stack and saves
    27.6 +// into the singleton.  The first field in the singleton is the
    27.7 +// "endInstrAddr" field, and the return addr is at 0x4(%ebp)
    27.8 +.globl asm_save_ret_to_singleton
    27.9 +asm_save_ret_to_singleton:
   27.10 +    movq 0x8(%rbp),     %rax   #get ret address, ebp is the same as in the calling function
   27.11 +    movq     %rax,     (%rdi) #write ret addr to endInstrAddr field
   27.12 +    ret
   27.13 +
   27.14 +
   27.15 +//Assembly code changes the return addr on the stack to the one
   27.16 +// saved into the singleton by the end-singleton-fn
   27.17 +//The stack's return addr is at 0x4(%%ebp)
   27.18 +.globl asm_write_ret_from_singleton
   27.19 +asm_write_ret_from_singleton:
   27.20 +    movq    (%rdi),    %rax  #get endInstrAddr field
   27.21 +    movq      %rax,    0x8(%rbp) #write return addr to the stack of the caller
   27.22 +    ret
   27.23 +
   27.24 +