changeset 6:1780f6b00e3d dev_expl_VP_and_DKU

Not working -- checkpoint while making explicitly created VPs work, and DKU pattern
author Sean Halle <seanhalle@yahoo.com>
date Wed, 01 Aug 2012 00:18:53 -0700
parents 8188c5b4bfd7
children 3999b8429ddd
files VSs.c VSs.h VSs_PluginFns.c VSs_Request_Handlers.c VSs_Request_Handlers.h __brch__default __brch__dev_expl_VP_and_DKU
diffstat 7 files changed, 320 insertions(+), 195 deletions(-) [+]
line diff
     1.1 --- a/VSs.c	Fri Jul 13 17:35:49 2012 +0200
     1.2 +++ b/VSs.c	Wed Aug 01 00:18:53 2012 -0700
     1.3 @@ -73,8 +73,10 @@
     1.4   */
     1.5  void
     1.6  VSs__create_seed_slave_and_do_work( TopLevelFnPtr fnPtr, void *initData )
     1.7 - { VSsSemEnv *semEnv;
     1.8 -   SlaveVP *seedSlv;
     1.9 + { VSsSemEnv   *semEnv;
    1.10 +   SlaveVP     *seedSlv;
    1.11 +   VSsSemData  *semData;
    1.12 +   VSsTaskStub *explPrTaskStub;
    1.13  
    1.14     VSs__init();      //normal multi-thd
    1.15     
    1.16 @@ -83,12 +85,18 @@
    1.17        //VSs starts with one processor, which is put into initial environ,
    1.18        // and which then calls create() to create more, thereby expanding work
    1.19     seedSlv = VSs__create_slave_helper( fnPtr, initData,
    1.20 -                                      semEnv, semEnv->nextCoreToGetNewSlv++ );
    1.21 +                                     semEnv, semEnv->nextCoreToGetNewSlv++ );
    1.22     
    1.23 -      //seedVP doesn't do tasks
    1.24 -   ((VSsSemData *)seedSlv->semanticData)->needsTaskAssigned = FALSE;
    1.25 +      //seed slave is an explicit processor, so make one of the special
    1.26 +      // task stubs for explicit processors, and attach it to the slave
    1.27 +   explPrTaskStub = create_expl_proc_task_stub( initData );
    1.28 +   
    1.29 +   semData = (VSsSemData *)seedSlv->semanticData;
    1.30 +      //seedVP already has a permanent task
    1.31 +   semData->needsTaskAssigned = FALSE;
    1.32 +   semData->taskStub = explPrTaskStub;
    1.33  
    1.34 -   resume_slaveVP( seedSlv, semEnv );
    1.35 +   resume_slaveVP( seedSlv, semEnv ); //returns right away, just queues Slv
    1.36     
    1.37     VMS_SS__start_the_work_then_wait_until_done();      //normal multi-thd
    1.38  
    1.39 @@ -169,8 +177,7 @@
    1.40  void
    1.41  VSs__init_Helper()
    1.42   { VSsSemEnv       *semanticEnv;
    1.43 -   PrivQueueStruc **readyVPQs;
    1.44 -   int              coreIdx, i, j;
    1.45 +   int32            i, coreNum, slotNum;
    1.46   
    1.47        //Hook up the semantic layer's plug-ins to the Master virt procr
    1.48     _VMSMasterEnv->requestHandler = &VSs__Request_Handler;
    1.49 @@ -190,43 +197,35 @@
    1.50  
    1.51     semanticEnv->shutdownInitiated = FALSE;
    1.52     semanticEnv->coreIsDone = VMS_int__malloc( NUM_CORES * sizeof( bool32 ) );
    1.53 -   for( i = 0; i < NUM_CORES; ++i )
    1.54 -    { semanticEnv->coreIsDone[i] = FALSE;
    1.55 -      for( j = 0; j < NUM_ANIM_SLOTS; ++j )
    1.56 -       {
    1.57 -         semanticEnv->idleSlv[i][j] = VMS_int__create_slaveVP(&idle_fn,NULL);
    1.58 -         semanticEnv->idleSlv[i][j]->coreAnimatedBy = i;
    1.59 +      //For each animation slot, there is an idle slave, and an initial
    1.60 +      // slave assigned as the current-task-slave.  Create them here.
    1.61 +   SlaveVP *idleSlv, *currTaskSlv;
    1.62 +   for( coreNum = 0; coreNum < NUM_CORES; coreNum++ )
    1.63 +    { semanticEnv->coreIsDone[coreNum] = FALSE; //use during shutdown
    1.64 +    
    1.65 +      for( slotNum = 0; slotNum < NUM_ANIM_SLOTS; ++slotNum )
    1.66 +       { idleSlv = VMS_int__create_slaveVP(&idle_fn,NULL);
    1.67 +         idleSlv->coreAnimatedBy                = coreNum;
    1.68 +         idleSlv->animSlotAssignedTo            = slotNum;
    1.69 +         semanticEnv->idleSlv[coreNum][slotNum] = idleSlv;
    1.70 +         
    1.71 +         currTaskSlv = VMS_int__create_slaveVP( &idle_fn, NULL );
    1.72 +         currTaskSlv->coreAnimatedBy                 = coreNum;
    1.73 +         currTaskSlv->animSlotAssignedTo             = slotNum;
    1.74 +         semanticEnv->currTaskSlvs[coreNum][slotNum] = currTaskSlv;
    1.75         }
    1.76      }
    1.77  
    1.78 -   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
    1.79 -   semanticEnv->unitList = makeListOfArrays(sizeof(Unit),128);
    1.80 -   semanticEnv->ctlDependenciesList = makeListOfArrays(sizeof(Dependency),128);
    1.81 -   semanticEnv->commDependenciesList = makeListOfArrays(sizeof(Dependency),128);
    1.82 -   semanticEnv->dynDependenciesList = makeListOfArrays(sizeof(Dependency),128);
    1.83 -   semanticEnv->ntonGroupsInfo = makePrivDynArrayOfSize((void***)&(semanticEnv->ntonGroups),8);
    1.84 -   
    1.85 -   semanticEnv->hwArcs = makeListOfArrays(sizeof(Dependency),128);
    1.86 -   memset(semanticEnv->last_in_slot,0,sizeof(NUM_CORES * NUM_ANIM_SLOTS * sizeof(Unit)));
    1.87 -   #endif
    1.88 -
    1.89 -      //create the ready queue, hash tables used for matching and so forth
    1.90 -   readyVPQs = VMS_int__malloc( NUM_CORES * sizeof(PrivQueueStruc *) );
    1.91 -
    1.92 -   for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
    1.93 -    {
    1.94 -      readyVPQs[ coreIdx ] = makeVMSQ();
    1.95 -    }
    1.96 -   
    1.97 -   semanticEnv->readyVPQs = readyVPQs;
    1.98 -   
    1.99 -   semanticEnv->taskReadyQ = makeVMSQ();
   1.100 -   
   1.101 -   semanticEnv->nextCoreToGetNewSlv = 0;
   1.102 -   semanticEnv->numSlaveVP = 0;
   1.103 +      //create the ready queues, hash tables used for matching and so forth
   1.104 +   semanticEnv->slavesReadyToResumeQ = makeVMSQ();
   1.105 +   semanticEnv->extraTaskSlvQ        = makeVMSQ();
   1.106 +   semanticEnv->taskReadyQ           = makeVMSQ();
   1.107     
   1.108     semanticEnv->argPtrHashTbl  = makeHashTable32( 16, &VMS_int__free );
   1.109     semanticEnv->commHashTbl    = makeHashTable32( 16, &VMS_int__free );
   1.110 +   
   1.111 +   semanticEnv->nextCoreToGetNewSlv = 0;
   1.112 +   
   1.113  
   1.114     //TODO: bug -- turn these arrays into dyn arrays to eliminate limit
   1.115     //semanticEnv->singletonHasBeenExecutedFlags = makeDynArrayInfo( );
   1.116 @@ -239,6 +238,19 @@
   1.117        semanticEnv->fnSingletons[i].waitQ             = makeVMSQ();
   1.118        semanticEnv->transactionStrucs[i].waitingVPQ   = makeVMSQ();
   1.119      }
   1.120 +
   1.121 +   semanticEnv->numAdditionalSlvs   = 0; //must be last
   1.122 +
   1.123 +   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   1.124 +   semanticEnv->unitList = makeListOfArrays(sizeof(Unit),128);
   1.125 +   semanticEnv->ctlDependenciesList = makeListOfArrays(sizeof(Dependency),128);
   1.126 +   semanticEnv->commDependenciesList = makeListOfArrays(sizeof(Dependency),128);
   1.127 +   semanticEnv->dynDependenciesList = makeListOfArrays(sizeof(Dependency),128);
   1.128 +   semanticEnv->ntonGroupsInfo = makePrivDynArrayOfSize((void***)&(semanticEnv->ntonGroups),8);
   1.129 +   
   1.130 +   semanticEnv->hwArcs = makeListOfArrays(sizeof(Dependency),128);
   1.131 +   memset(semanticEnv->last_in_slot,0,sizeof(NUM_CORES * NUM_ANIM_SLOTS * sizeof(Unit)));
   1.132 +   #endif
   1.133   }
   1.134  
   1.135  
     2.1 --- a/VSs.h	Fri Jul 13 17:35:49 2012 +0200
     2.2 +++ b/VSs.h	Wed Aug 01 00:18:53 2012 -0700
     2.3 @@ -61,9 +61,7 @@
     2.4   }
     2.5  VSsPointerEntry;
     2.6  
     2.7 -typedef struct _VSsTaskStub VSsTaskStub;
     2.8 -
     2.9 -struct _VSsTaskStub
    2.10 +typedef struct
    2.11   {
    2.12     void       **args; //ctld args must come first, as ptrs
    2.13     VSsTaskType *taskType;
    2.14 @@ -74,17 +72,19 @@
    2.15     void*        parent;
    2.16     bool32       parentIsTask;
    2.17     int32        numChildTasks;
    2.18 -   bool32         isWaiting;
    2.19 +   bool32       isWaiting;
    2.20   }
    2.21 -;
    2.22 +VSsTaskStub;
    2.23  
    2.24 -typedef struct {
    2.25 +typedef struct 
    2.26 + {
    2.27      void* parent;
    2.28      bool32       parentIsTask;
    2.29      int32        numChildTasks;
    2.30      bool32       isWaiting;
    2.31     SlaveVP     *slaveAssignedTo;    
    2.32 -} VSsThreadInfo;
    2.33 + }
    2.34 +VSsThreadInfo;
    2.35  
    2.36  typedef struct
    2.37   {
    2.38 @@ -185,11 +185,13 @@
    2.39  
    2.40  typedef struct
    2.41   {
    2.42 -   PrivQueueStruc **readyVPQs;
    2.43 -   PrivQueueStruc  *taskReadyQ;  //Q: shared or local?
    2.44 +   PrivQueueStruc **slavesReadyToResumeQ; //Shared (slaves not pinned)
    2.45 +   PrivQueueStruc **extraTaskSlvQ;     //Shared
    2.46 +   PrivQueueStruc  *taskReadyQ;        //Shared (tasks not pinned)
    2.47 +   SlaveVP         *currTaskSlvs[NUM_CORES][NUM_ANIM_SLOTS];
    2.48     HashTable       *argPtrHashTbl;
    2.49     HashTable       *commHashTbl;
    2.50 -   int32            numSlaveVP;
    2.51 +   int32            numAdditionalSlvs;
    2.52     int32            nextCoreToGetNewSlv;
    2.53     int32            primitiveStartTime;
    2.54  
     3.1 --- a/VSs_PluginFns.c	Fri Jul 13 17:35:49 2012 +0200
     3.2 +++ b/VSs_PluginFns.c	Wed Aug 01 00:18:53 2012 -0700
     3.3 @@ -15,26 +15,42 @@
     3.4  void
     3.5  resume_slaveVP( SlaveVP *slave, VSsSemEnv *semEnv );
     3.6  
     3.7 -void
     3.8 +inline void
     3.9  handleSemReq( VMSReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv );
    3.10  
    3.11 -void
    3.12 +inline void
    3.13  handleDissipate(                SlaveVP *requestingSlv, VSsSemEnv *semEnv );
    3.14  
    3.15 -void
    3.16 +inline void
    3.17  handleCreate(    VMSReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv );
    3.18  
    3.19  //============================== Assigner ==================================
    3.20  //
    3.21 -/*For VSs, assigning a slave simply takes the next work-unit off the
    3.22 - * ready-to-go work-unit queue and assigns it to the offered slot.
    3.23 - *If the ready-to-go work-unit queue is empty, then nothing to assign
    3.24 - * to the animation slot -- return FALSE to let Master loop know assigning
    3.25 - * that slot failed.
    3.26 +/*The assigner is complicated by having both tasks and explicitly created
    3.27 + * VPs, and by tasks being able to suspend.
    3.28 + *It can't use an explicit slave to animate a task because of stack
    3.29 + * pollution. So, it has to keep the two kinds separate.
    3.30 + *Simplest way for the assigner logic is with a Q for extra empty task
    3.31 + * slaves, and another Q for slaves of both types that are ready to resume.
    3.32 + *
    3.33 + *Keep a current task slave for each anim slot. The request handler manages
    3.34 + * it by pulling from the extraTaskSlvQ when a task suspends, or else
    3.35 + * creating a new task slave if taskSlvQ empty. 
    3.36 + *Assigner only assigns a task to the current task slave for the slot.
    3.37 + *If no more tasks, then takes a ready to resume slave, if also none of them
    3.38 + * then dissipates extra task slaves (one per invocation).
    3.39 + *Shutdown condition is: must have no suspended tasks, and no suspended
    3.40 + * explicit slaves and no more tasks in taskQ.  Will only have the masters
    3.41 + * plus a current task slave for each slot.. detects this condition. 
    3.42 + * 
    3.43 + *Having the two types of slave is part of having communications directly
    3.44 + * between tasks, and tasks to explicit slaves, which requires the ability
    3.45 + * to suspend both kinds, but also to keep explicit slave stacks clean from
    3.46 + * the junk tasks are allowed to leave behind.
    3.47   */
    3.48  SlaveVP *
    3.49  VSs__assign_slaveVP_to_slot( void *_semEnv, AnimSlot *slot )
    3.50 - { SlaveVP    *assignSlv;
    3.51 + { SlaveVP    *returnSlv;
    3.52     VSsSemEnv  *semEnv;
    3.53     VSsSemData *semData;
    3.54     int32       coreNum, slotNum;
    3.55 @@ -44,111 +60,113 @@
    3.56     
    3.57     semEnv  = (VSsSemEnv *)_semEnv;
    3.58  
    3.59 -   /*At this point, could do an optimization -- have one slave for each slot
    3.60 -    * and make it ALWAYS the one to assign to that slot -- so there is no
    3.61 -    * read fromQ.  However, going to keep this compatible with other
    3.62 -    * languages, like VOMP and SSR.  So, leave the normal slave fetch
    3.63 -    * from readyQ. For example, allows SSR constructs, to create extra
    3.64 -    * slaves, and send communications direction between them, while still
    3.65 -    * having the StarSs-style spawning of tasks..  so one of the tasks
    3.66 -    * can now suspend and do more interesting things..  means keep a pool
    3.67 -    * of slaves, and take one from pool when a task suspends.
    3.68 -    */
    3.69 -   //TODO: fix false sharing in array
    3.70 -   assignSlv = readPrivQ( semEnv->readyVPQs[coreNum] );
    3.71 -   if( assignSlv == NULL )
    3.72 +   
    3.73 +   //Speculatively set the return slave to the current taskSlave
    3.74 +   //TODO: false sharing ?  Always read..
    3.75 +   returnSlv = semEnv->currTaskSlvs[coreNum][slotNum];
    3.76 +
    3.77 +/* request handlers do this now..  move it to there..
    3.78 +   if( returnSlv == NULL )
    3.79      {    //make a new slave to animate
    3.80           //This happens for the first task on the core and when all available
    3.81 -         // slaves are blocked by constructs like send, or mutex, and so on..
    3.82 -      assignSlv = VSs__create_slave_helper( NULL, NULL, semEnv, coreNum );
    3.83 +         //slaves are blocked by constructs like send, or mutex, and so on.
    3.84 +      returnSlv = VSs__create_slave_helper( NULL, NULL, semEnv, coreNum );
    3.85      }
    3.86 -   semData = (VSsSemData *)assignSlv->semanticData;
    3.87 -      //slave could be resuming a task in progress, check for this
    3.88 -   if( semData->needsTaskAssigned )
    3.89 -    {    //no, not resuming, needs a task..
    3.90 -      VSsTaskStub *newTaskStub;
    3.91 -      SlaveVP *extraSlv;
    3.92 -      newTaskStub = readPrivQ( semEnv->taskReadyQ );
    3.93 -      if( newTaskStub == NULL )
    3.94 -       { //No task, so slave unused, so put it back and return "no-slave"
    3.95 -         //But first check if have extra free slaves
    3.96 -         extraSlv = readPrivQ( semEnv->readyVPQs[coreNum] );
    3.97 -         if( extraSlv == NULL )
    3.98 -          {    //means no tasks and no slave on this core can generate more
    3.99 -            //TODO: false sharing
   3.100 -            if( semEnv->coreIsDone[coreNum] == FALSE)
   3.101 + */ 
   3.102 +   semData = (VSsSemData *)returnSlv->semanticData;
   3.103 +
   3.104 +      //There is always a curr task slave, and it always needs a task
   3.105 +      //(task slaves that are resuming are in resumeQ)
   3.106 +   VSsTaskStub *newTaskStub;
   3.107 +   SlaveVP *extraSlv;
   3.108 +   newTaskStub = readPrivQ( semEnv->taskReadyQ );
   3.109 +   if( newTaskStub != NULL )
   3.110 +    { //point slave to task's function, and mark slave as having task
   3.111 +      VMS_int__reset_slaveVP_to_TopLvlFn( returnSlv, 
   3.112 +                          newTaskStub->taskType->fn, newTaskStub->args );
   3.113 +      semData->taskStub            = newTaskStub;
   3.114 +      newTaskStub->slaveAssignedTo = returnSlv;
   3.115 +      semData->needsTaskAssigned   = FALSE;
   3.116 +      if( semEnv->coreIsDone[coreNum] == TRUE ) //reads are higher perf
   3.117 +         semEnv->coreIsDone[coreNum] = FALSE;   //don't just write always
   3.118 +      goto ReturnTheSlv;
   3.119 +    }
   3.120 +   else
   3.121 +    { //no task, so try to get a ready to resume slave
   3.122 +      returnSlv = readPrivQ( semEnv->slavesReadyToResumeQ );
   3.123 +      if( returnSlv != NULL )  //Yes, have a slave, so return it.
   3.124 +       { returnSlv->coreAnimatedBy   = coreNum;
   3.125 +         if( semEnv->coreIsDone[coreNum] == TRUE ) //reads are higher perf
   3.126 +            semEnv->coreIsDone[coreNum] = FALSE;   //don't just write always
   3.127 +         goto ReturnTheSlv;
   3.128 +       }
   3.129 +      //If get here, then no task, so check if have extra free slaves
   3.130 +      extraSlv = readPrivQ( semEnv->extraTaskSlvQ );
   3.131 +      if( extraSlv != NULL )
   3.132 +       {    //means have two slaves need tasks -- redundant, kill one
   3.133 +         handleDissipate( extraSlv, semEnv );
   3.134 +            //then return NULL
   3.135 +         returnSlv = NULL;
   3.136 +         goto ReturnTheSlv;
   3.137 +       }
   3.138 +      else
   3.139 +       { //candidate for shutdown.. if all extras dissipated, and no tasks
   3.140 +         // and no ready to resume slaves, then then no way to generate
   3.141 +         // more tasks..
   3.142 +         if( semEnv->numAdditionalSlvs == 0 ) //means none suspended
   3.143 +          { //This core sees no way to generate more tasks, so say it
   3.144 +            if( semEnv->coreIsDone[coreNum] == FALSE )
   3.145               { semEnv->numCoresDone += 1;
   3.146                 semEnv->coreIsDone[coreNum] = TRUE;
   3.147                 #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
   3.148                 semEnv->shutdownInitiated = TRUE;
   3.149                 #else
   3.150                 if( semEnv->numCoresDone == NUM_CORES )
   3.151 -                {    //means no cores have work, and none can generate more
   3.152 +                { //means no cores have work, and none can generate more
   3.153                    semEnv->shutdownInitiated = TRUE;
   3.154                  }
   3.155                 #endif
   3.156               }
   3.157 -               //put slave back into Q and return NULL
   3.158 -            writePrivQ( assignSlv, semEnv->readyVPQs[coreNum] );
   3.159 -            assignSlv = NULL;
   3.160 -               //except if shutdown has been initiated by this or other core
   3.161 -            if(semEnv->shutdownInitiated) 
   3.162 -             { assignSlv = VMS_SS__create_shutdown_slave();
   3.163 -             }
   3.164            }
   3.165 -         else //extra slave exists, but no tasks for either slave
   3.166 -          { if(((VSsSemData *)extraSlv->semanticData)->needsTaskAssigned == TRUE)
   3.167 -             {    //means have two slaves need tasks -- redundant, kill one
   3.168 -               handleDissipate( extraSlv, semEnv );
   3.169 -                  //then put other back into Q and return NULL
   3.170 -               writePrivQ( assignSlv, semEnv->readyVPQs[coreNum] );
   3.171 -               assignSlv = NULL;
   3.172 -             }
   3.173 -            else
   3.174 -             {    //extra slave has work -- so take it instead
   3.175 -               writePrivQ( assignSlv, semEnv->readyVPQs[coreNum] );
   3.176 -               assignSlv = extraSlv;
   3.177 -               //semData = (VSsSemData *)assignSlv->semanticData; Don't use
   3.178 -             }
   3.179 +            //return NULL.. no task and none to resume
   3.180 +         returnSlv = NULL;
   3.181 +            //except if shutdown has been initiated by this or other core
   3.182 +         if(semEnv->shutdownInitiated) 
   3.183 +          { returnSlv = VMS_SS__create_shutdown_slave();
   3.184            }
   3.185 -       }
   3.186 -      else //have a new task for the slave.
   3.187 -       { //point slave to task's function, and mark slave as having task
   3.188 -         VMS_int__reset_slaveVP_to_TopLvlFn( assignSlv, 
   3.189 -                             newTaskStub->taskType->fn, newTaskStub->args );
   3.190 -         semData->taskStub = newTaskStub;
   3.191 -         newTaskStub->slaveAssignedTo = assignSlv;
   3.192 -         semData->needsTaskAssigned = FALSE;
   3.193 -       }
   3.194 -    } //outcome: 1)slave didn't need a new task 2)slave just pointed at one
   3.195 -      //         3)no tasks, so slave NULL
   3.196 -   
   3.197 +         goto ReturnTheSlv; //don't need, but completes pattern
   3.198 +       } //if( extraSlv != NULL )
   3.199 +    } //if( newTaskStub == NULL )
   3.200 +   //outcome: 1)slave was just pointed to task, 2)no tasks, so slave NULL
   3.201 +
   3.202 +ReturnTheSlv:  //Nina, doing gotos to here should help with holistic..
   3.203 +
   3.204     #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   3.205 -   if( assignSlv == NULL )
   3.206 -    { assignSlv = semEnv->idleSlv[coreNum][slotNum]; 
   3.207 +   if( returnSlv == NULL )
   3.208 +    { returnSlv = semEnv->idleSlv[coreNum][slotNum]; 
   3.209        if(semEnv->shutdownInitiated) 
   3.210 -       { assignSlv = VMS_SS__create_shutdown_slave();
   3.211 +       { returnSlv = VMS_SS__create_shutdown_slave();
   3.212         }
   3.213           //things that would normally happen in resume(), but these VPs
   3.214           // never go there
   3.215 -      assignSlv->assignCount++; //Somewhere here!
   3.216 +      returnSlv->assignCount++; //Somewhere here!
   3.217        Unit newu;
   3.218 -      newu.vp = assignSlv->slaveID;
   3.219 -      newu.task = assignSlv->assignCount;
   3.220 +      newu.vp = returnSlv->slaveID;
   3.221 +      newu.task = returnSlv->assignCount;
   3.222        addToListOfArrays(Unit,newu,semEnv->unitList);
   3.223  
   3.224 -      if (assignSlv->assignCount > 1)
   3.225 +      if (returnSlv->assignCount > 1)
   3.226         { Dependency newd;
   3.227 -         newd.from_vp = assignSlv->slaveID;
   3.228 -         newd.from_task = assignSlv->assignCount - 1;
   3.229 -         newd.to_vp = assignSlv->slaveID;
   3.230 -         newd.to_task = assignSlv->assignCount;
   3.231 +         newd.from_vp = returnSlv->slaveID;
   3.232 +         newd.from_task = returnSlv->assignCount - 1;
   3.233 +         newd.to_vp = returnSlv->slaveID;
   3.234 +         newd.to_task = returnSlv->assignCount;
   3.235           addToListOfArrays(Dependency, newd ,semEnv->ctlDependenciesList);  
   3.236         }
   3.237      }
   3.238     #endif
   3.239     #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   3.240 -   if( assignSlv != NULL )
   3.241 +   if( returnSlv != NULL )
   3.242      { //assignSlv->numTimesAssigned++;
   3.243        Unit prev_in_slot = 
   3.244           semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum];
   3.245 @@ -156,23 +174,24 @@
   3.246         { Dependency newd;
   3.247           newd.from_vp = prev_in_slot.vp;
   3.248           newd.from_task = prev_in_slot.task;
   3.249 -         newd.to_vp = assignSlv->slaveID;
   3.250 -         newd.to_task = assignSlv->assignCount;
   3.251 +         newd.to_vp = returnSlv->slaveID;
   3.252 +         newd.to_task = returnSlv->assignCount;
   3.253           addToListOfArrays(Dependency,newd,semEnv->hwArcs);   
   3.254         }
   3.255 -      prev_in_slot.vp = assignSlv->slaveID;
   3.256 -      prev_in_slot.task = assignSlv->assignCount;
   3.257 +      prev_in_slot.vp = returnSlv->slaveID;
   3.258 +      prev_in_slot.task = returnSlv->assignCount;
   3.259        semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum] =
   3.260           prev_in_slot;        
   3.261      }
   3.262     #endif
   3.263 -   return( assignSlv );
   3.264 +   return( returnSlv );
   3.265   }
   3.266  
   3.267  
   3.268  //===========================  Request Handler  ============================
   3.269  //
   3.270  /*
   3.271 + * (BTW not inline because invoked indirectly via a pointer)
   3.272   */
   3.273  void
   3.274  VSs__Request_Handler( SlaveVP *requestingSlv, void *_semEnv )
   3.275 @@ -186,14 +205,14 @@
   3.276     while( req != NULL )
   3.277      {
   3.278        switch( req->reqType )
   3.279 -       { case semantic:     handleSemReq(         req, requestingSlv, semEnv);
   3.280 +       { case semantic:     handleSemReq(        req, requestingSlv, semEnv);
   3.281              break;
   3.282 -         case createReq:    handleCreate(         req, requestingSlv, semEnv);
   3.283 +         case createReq:    handleCreate(        req, requestingSlv, semEnv);
   3.284              break;
   3.285 -         case dissipate:    handleDissipate(           requestingSlv, semEnv);
   3.286 +         case dissipate:    handleDissipate(          requestingSlv, semEnv);
   3.287              break;
   3.288           case VMSSemantic:  VMS_PI__handle_VMSSemReq(req, requestingSlv, semEnv,
   3.289 -                                             (ResumeSlvFnPtr) &resume_slaveVP);
   3.290 +                                           (ResumeSlvFnPtr) &resume_slaveVP);
   3.291              break;
   3.292           default:
   3.293              break;
   3.294 @@ -205,7 +224,7 @@
   3.295   }
   3.296  
   3.297  
   3.298 -void
   3.299 +inline void
   3.300  handleSemReq( VMSReqst *req, SlaveVP *reqSlv, VSsSemEnv *semEnv )
   3.301   { VSsSemReq *semReq;
   3.302  
   3.303 @@ -213,22 +232,22 @@
   3.304     if( semReq == NULL ) return;
   3.305     switch( semReq->reqType )  //sem handlers are all in other file
   3.306      {
   3.307 -      case submit_task:     handleSubmitTask(   semReq,        semEnv);
   3.308 +      case submit_task:     handleSubmitTask(   semReq,         semEnv);
   3.309 +         break; 
   3.310 +      case end_task:        handleEndTask(      semReq,         semEnv);
   3.311           break;
   3.312 -      case end_task:        handleEndTask(      semReq,        semEnv);
   3.313 +      case send_type_to:    handleSendTypeTo(   semReq,         semEnv);
   3.314           break;
   3.315 -      case send_type_to:    handleSendTypeTo(   semReq,        semEnv);
   3.316 +      case send_from_to:    handleSendFromTo(   semReq,         semEnv);
   3.317           break;
   3.318 -      case send_from_to:    handleSendFromTo(   semReq,        semEnv);
   3.319 +      case receive_type_to: handleReceiveTypeTo(semReq,         semEnv);
   3.320           break;
   3.321 -      case receive_type_to: handleReceiveTypeTo(semReq,        semEnv);
   3.322 +      case receive_from_to: handleReceiveFromTo(semReq,         semEnv);
   3.323           break;
   3.324 -      case receive_from_to: handleReceiveFromTo(semReq,        semEnv);
   3.325 -         break;
   3.326 +      case taskwait:        handleTaskwait(     semReq, reqSlv, semEnv);
   3.327 +           break;
   3.328           
   3.329        //====================================================================
   3.330 -       case taskwait:   handleTaskwait(semReq, reqSlv, semEnv);
   3.331 -           break;
   3.332        case malloc_req:      handleMalloc(       semReq, reqSlv, semEnv);
   3.333           break;
   3.334        case free_req:        handleFree(         semReq, reqSlv, semEnv);
   3.335 @@ -255,10 +274,14 @@
   3.336  //=========================== VMS Request Handlers ==============================
   3.337  /*SlaveVP dissipate  (NOT task-end!)
   3.338   */
   3.339 -void
   3.340 +inline void
   3.341  handleDissipate( SlaveVP *requestingSlv, VSsSemEnv *semEnv )
   3.342   {
   3.343 -    DEBUG__printf1(dbgRqstHdlr,"Dissipate request from processor %d",requestingSlv->slaveID)
   3.344 +         DEBUG__printf1(dbgRqstHdlr,"Dissipate request from processor %d",
   3.345 +                                                     requestingSlv->slaveID)
   3.346 +       
   3.347 +   semEnv->numAdditionalSlvs -= 1;
   3.348 +   
   3.349        //free any semantic data allocated to the virt procr
   3.350     VMS_PI__free( requestingSlv->semanticData );
   3.351  
   3.352 @@ -268,7 +291,7 @@
   3.353  
   3.354  /*Re-use this in the entry-point fn
   3.355   */
   3.356 -SlaveVP *
   3.357 +inline SlaveVP *
   3.358  VSs__create_slave_helper( TopLevelFnPtr fnPtr, void *initData,
   3.359                            VSsSemEnv *semEnv,    int32 coreToAssignOnto )
   3.360   { SlaveVP    *newSlv;
   3.361 @@ -277,7 +300,7 @@
   3.362        //This is running in master, so use internal version
   3.363     newSlv = VMS_PI__create_slaveVP( fnPtr, initData );
   3.364  
   3.365 -   semEnv->numSlaveVP += 1;
   3.366 +   semEnv->numAdditionalSlvs += 1;
   3.367  
   3.368     semData = VMS_PI__malloc( sizeof(VSsSemData) );
   3.369     semData->highestTransEntered = -1;
   3.370 @@ -298,7 +321,7 @@
   3.371     newSlv->coreAnimatedBy = 0;
   3.372  
   3.373     #else
   3.374 -
   3.375 +      //Assigning slaves to cores is part of SSR code..
   3.376     if(coreToAssignOnto < 0 || coreToAssignOnto >= NUM_CORES )
   3.377      {    //out-of-range, so round-robin assignment
   3.378        newSlv->coreAnimatedBy = semEnv->nextCoreToGetNewSlv;
   3.379 @@ -317,9 +340,17 @@
   3.380     return newSlv;
   3.381   }
   3.382  
   3.383 -/*SlaveVP create  (NOT task create!)
   3.384 +/*This has been removed, because have changed things.. the only way to 
   3.385 + * create a slaveVP now is to either do an explicit create in the app, or
   3.386 + * else for req hdlr to create it when a task suspends if no extras are
   3.387 + * free.
   3.388 + *So, only have handleExplCreate for now.. and have the req hdlrs use the
   3.389 + * helper
   3.390 + *SlaveVP create  (NOT task create!)
   3.391 + *
   3.392   */
   3.393 -void
   3.394 +/*
   3.395 +inline void
   3.396  handleCreate( VMSReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv  )
   3.397   { VSsSemReq *semReq;
   3.398     SlaveVP    *newSlv;
   3.399 @@ -327,12 +358,13 @@
   3.400     
   3.401     semReq = VMS_PI__take_sem_reqst_from( req );
   3.402   
   3.403 -   newSlv = VSs__create_slave_helper( semReq->fnPtr, semReq->initData, semEnv,
   3.404 -                                     semReq->coreToAssignOnto );
   3.405 +   newSlv = VSs__create_slave_helper( semReq->fnPtr, semReq->initData,
   3.406 +                                         semEnv, semReq->coreToAssignOnto );
   3.407     
   3.408     ((VSsSemData*)newSlv->semanticData)->threadInfo->parent = requestingSlv;
   3.409     
   3.410 -         DEBUG__printf2(dbgRqstHdlr,"Create from: %d, new VP: %d", requestingSlv->slaveID, newSlv->slaveID)
   3.411 +         DEBUG__printf2(dbgRqstHdlr,"Create from: %d, new VP: %d",
   3.412 +                                    requestingSlv->slaveID, newSlv->slaveID)
   3.413  
   3.414     #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   3.415     Dependency newd;
   3.416 @@ -340,7 +372,75 @@
   3.417     newd.from_task = requestingSlv->assignCount;
   3.418     newd.to_vp = newSlv->slaveID;
   3.419     newd.to_task = 1;
   3.420 -   //addToListOfArraysDependency(newd,semEnv->commDependenciesList);  
   3.421 +   addToListOfArrays(Dependency,newd,semEnv->commDependenciesList);   
   3.422 +   #endif
   3.423 +
   3.424 +      //For VSs, caller needs ptr to created processor returned to it
   3.425 +   requestingSlv->dataRetFromReq = newSlv;
   3.426 +
   3.427 +   resume_slaveVP( requestingSlv, semEnv );
   3.428 +   resume_slaveVP( newSlv,        semEnv );
   3.429 + }
   3.430 +*/
   3.431 +
   3.432 +VSsTaskStub *
   3.433 +create_expl_proc_task_stub( void *initData )
   3.434 + { VSsTaskStub *newStub;
   3.435 +         
   3.436 +   newStub = VMS_PI__malloc( sizeof(VSsTaskStub) );
   3.437 +   newStub->numBlockingProp = 0;
   3.438 +   newStub->slaveAssignedTo = NULL; //set later
   3.439 +   newStub->taskType        = NULL; //Identifies as an explicit processor
   3.440 +   newStub->ptrEntries      = NULL;
   3.441 +   newStub->args            = initData;  
   3.442 +   newStub->numChildTasks   = 0;
   3.443 +   newStub->parent          = NULL;
   3.444 +   newStub->isWaiting       = FALSE;
   3.445 +   newStub->taskID          = NULL;
   3.446 +   newStub->parentIsTask    = FALSE;
   3.447 +
   3.448 +   return newStub;
   3.449 + }
   3.450 +
   3.451 +/*Application invokes this when it explicitly creates a "processor" via the
   3.452 + * "SSR__create_processor()" command.
   3.453 + * 
   3.454 + *Make everything in VSs be a task.  An explicitly created VP is just a
   3.455 + * suspendable task, and the seedVP is also a suspendable task. 
   3.456 + *So, here, create a task Stub. 
   3.457 + * Then, see if there are any extra slaveVPs hanging around, and if not,
   3.458 + * call the helper to make a new one.
   3.459 + * Then, put the task stub into the slave's semantic Data.
   3.460 + *When the slave calls dissipate, have to recycle the task stub.
   3.461 + */
   3.462 +inline void
   3.463 +handleExplCreate( VMSReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv )
   3.464 + { VSsSemReq  *semReq;
   3.465 +   SlaveVP    *newSlv;
   3.466 +   VSsSemData *semData;
   3.467 +   
   3.468 +   semReq = VMS_PI__take_sem_reqst_from( req );
   3.469 +
   3.470 +   taskStub = create_expl_proc_task_stub( initData );
   3.471 +   
   3.472 +   newSlv = readPrivQ( semEnv->extraTaskSlvQ );
   3.473 +   if( newSlv == NULL )
   3.474 +      newSlv = VSs__create_slave_helper( semReq->fnPtr, semReq->initData,
   3.475 +                                         semEnv, semReq->coreToAssignOnto );
   3.476 +   
   3.477 +   semData = ( (VSsSemData *)newSlv->semanticData );
   3.478 +   semData->threadInfo->parent = requestingSlv;
   3.479 +   semData->taskStub = newPrTaskStub;
   3.480 +   
   3.481 +         DEBUG__printf2(dbgRqstHdlr,"Create from: %d, new VP: %d",
   3.482 +                                    requestingSlv->slaveID, newSlv->slaveID)
   3.483 +
   3.484 +   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   3.485 +   Dependency newd;
   3.486 +   newd.from_vp = requestingSlv->slaveID;
   3.487 +   newd.from_task = requestingSlv->assignCount;
   3.488 +   newd.to_vp = newSlv->slaveID;
   3.489 +   newd.to_task = 1;
   3.490     addToListOfArrays(Dependency,newd,semEnv->commDependenciesList);   
   3.491     #endif
   3.492  
   3.493 @@ -356,6 +456,9 @@
   3.494  void
   3.495  resume_slaveVP( SlaveVP *slave, VSsSemEnv *semEnv )
   3.496   {
   3.497 +      //both suspended tasks and suspended explicit slaves resumed with this
   3.498 +   writePrivQ( slave, semEnv->slavesReadyToResumeQ );
   3.499 +   
   3.500     #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS
   3.501  /*
   3.502     int lastRecordIdx = slave->counter_history_array_info->numInArray -1;
   3.503 @@ -379,5 +482,4 @@
   3.504          addToListOfArrays(Dependency, newd ,semEnv->ctlDependenciesList);  
   3.505     }
   3.506     #endif
   3.507 -   writePrivQ( slave, semEnv->readyVPQs[ slave->coreAnimatedBy] );
   3.508   }
     4.1 --- a/VSs_Request_Handlers.c	Fri Jul 13 17:35:49 2012 +0200
     4.2 +++ b/VSs_Request_Handlers.c	Wed Aug 01 00:18:53 2012 -0700
     4.3 @@ -212,7 +212,7 @@
     4.4   * 
     4.5   *That should be it -- that should work.
     4.6   */
     4.7 -void
     4.8 +inline void
     4.9  handleSubmitTask( VSsSemReq *semReq, VSsSemEnv *semEnv )
    4.10   { uint32           key[3];
    4.11     HashEntry       *rawHashEntry; //has char *, but use with uint32 *
    4.12 @@ -335,11 +335,6 @@
    4.13     return;
    4.14   }
    4.15  
    4.16 -inline void
    4.17 -handleSubmitTaskWID( VSsSemReq *semReq, VSsSemEnv *semEnv)
    4.18 - {
    4.19 - }
    4.20 -
    4.21  
    4.22  /* ========================== end of task ===========================
    4.23   * 
    4.24 @@ -376,7 +371,7 @@
    4.25   *TODO: Might be safe to delete an entry when task ends and waiterQ empty
    4.26   * and no readers and no writers..
    4.27   */
    4.28 -void
    4.29 +inline void
    4.30  handleEndTask( VSsSemReq *semReq, VSsSemEnv *semEnv )
    4.31   { uint32            key[3];
    4.32     HashEntry        *rawHashEntry;
    4.33 @@ -402,21 +397,24 @@
    4.34     ptrEntries     = endingTaskStub->ptrEntries; //saved in stub when create
    4.35     
    4.36     /* Check if parent was waiting on this task */
    4.37 -   if(endingTaskStub->parentIsTask){
    4.38 -       VSsTaskStub* parent = (VSsTaskStub*) endingTaskStub->parent;
    4.39 -       parent->numChildTasks--;
    4.40 -       if(parent->isWaiting && parent->numChildTasks == 0){
    4.41 -           parent->isWaiting = FALSE;
    4.42 -           resume_slaveVP( parent->slaveAssignedTo, semEnv );
    4.43 +   if(endingTaskStub->parentIsTask)
    4.44 +    { VSsTaskStub* parent = (VSsTaskStub*) endingTaskStub->parent;
    4.45 +      parent->numChildTasks--;
    4.46 +      if(parent->isWaiting && parent->numChildTasks == 0)
    4.47 +       {
    4.48 +         parent->isWaiting = FALSE;
    4.49 +         resume_slaveVP( parent->slaveAssignedTo, semEnv );
    4.50         }
    4.51 -   } else {
    4.52 -       VSsThreadInfo* parent = (VSsThreadInfo*) endingTaskStub->parent;
    4.53 -       parent->numChildTasks--;
    4.54 -       if(parent->isWaiting && parent->numChildTasks == 0){
    4.55 -           parent->isWaiting = FALSE;
    4.56 -           resume_slaveVP( parent->slaveAssignedTo, semEnv );
    4.57 +    } 
    4.58 +   else 
    4.59 +    { VSsThreadInfo* parent = (VSsThreadInfo*) endingTaskStub->parent;
    4.60 +      parent->numChildTasks--;
    4.61 +      if(parent->isWaiting && parent->numChildTasks == 0)
    4.62 +       {
    4.63 +         parent->isWaiting = FALSE;
    4.64 +         resume_slaveVP( parent->slaveAssignedTo, semEnv );
    4.65         }
    4.66 -   }
    4.67 +    }
    4.68     
    4.69     /*The task's controlled arguments are processed one by one.
    4.70      *Processing an argument means getting arg-pointer's entry.
    4.71 @@ -549,7 +547,7 @@
    4.72   * separate tasks can send to the same receiver, and doing hash on the
    4.73   * receive task, so they will stack up.
    4.74   */
    4.75 -void
    4.76 +inline void
    4.77  handleSendTypeTo( VSsSemReq *semReq, VSsSemEnv *semEnv )
    4.78   { SlaveVP    *senderSlv, *receiverSlv;
    4.79     int32      *senderID, *receiverID;
    4.80 @@ -645,7 +643,7 @@
    4.81  /*Looks like can make single handler for both sends..
    4.82   */
    4.83  //TODO: combine both send handlers into single handler
    4.84 -void
    4.85 +inline void
    4.86  handleSendFromTo( VSsSemReq *semReq, VSsSemEnv *semEnv)
    4.87   { SlaveVP     *senderSlv, *receiverSlv;
    4.88     int32       *senderID, *receiverID;
    4.89 @@ -721,7 +719,7 @@
    4.90  //
    4.91  
    4.92  
    4.93 -void
    4.94 +inline void
    4.95  handleReceiveTypeTo( VSsSemReq *semReq, VSsSemEnv *semEnv)
    4.96   { SlaveVP    *senderSlv, *receiverSlv;
    4.97     int32      *receiverID;
    4.98 @@ -803,7 +801,7 @@
    4.99  
   4.100  /*
   4.101   */
   4.102 -void
   4.103 +inline void
   4.104  handleReceiveFromTo( VSsSemReq *semReq, VSsSemEnv *semEnv)
   4.105   { SlaveVP     *senderSlv, *receiverSlv;
   4.106     int32       *senderID,  *receiverID;
   4.107 @@ -867,8 +865,8 @@
   4.108   }
   4.109  
   4.110  //==========================================================================
   4.111 -void
   4.112 -handleTaskwait( VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv )
   4.113 +inline void
   4.114 +handleTaskwait( VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv)
   4.115   {
   4.116      VSsTaskStub* requestingTaskStub;
   4.117      
     5.1 --- a/VSs_Request_Handlers.h	Fri Jul 13 17:35:49 2012 +0200
     5.2 +++ b/VSs_Request_Handlers.h	Wed Aug 01 00:18:53 2012 -0700
     5.3 @@ -19,6 +19,17 @@
     5.4  inline void
     5.5  handleEndTask( VSsSemReq *semReq, VSsSemEnv *semEnv);
     5.6  inline void
     5.7 +handleSendTypeTo( VSsSemReq *semReq, VSsSemEnv *semEnv);
     5.8 +inline void
     5.9 +handleSendFromTo( VSsSemReq *semReq, VSsSemEnv *semEnv);
    5.10 +inline void
    5.11 +handleReceiveTypeTo( VSsSemReq *semReq, VSsSemEnv *semEnv);
    5.12 +inline void
    5.13 +handleReceiveFromTo( VSsSemReq *semReq, VSsSemEnv *semEnv);
    5.14 +inline void
    5.15 +handleTaskwait(VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv);
    5.16 +
    5.17 +inline void
    5.18  handleMalloc( VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv);
    5.19  inline void
    5.20  handleFree( VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv );
     6.1 --- a/__brch__default	Fri Jul 13 17:35:49 2012 +0200
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,4 +0,0 @@
     6.4 -This branch is for the project structure defined Jan 2012..  the #includes reflect this directory structure.
     6.5 -
     6.6 -More importantly, the MC_shared  version of VMS requires a separat malloc implemeted by VMS code..  so this branch has modified the library to use the VMS-specific malloc.
     6.7 -
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/__brch__dev_expl_VP_and_DKU	Wed Aug 01 00:18:53 2012 -0700
     7.3 @@ -0,0 +1,4 @@
     7.4 +This branch is for the project structure defined Jan 2012..  the #includes reflect this directory structure.
     7.5 +
     7.6 +More importantly, the MC_shared  version of VMS requires a separat malloc implemeted by VMS code..  so this branch has modified the library to use the VMS-specific malloc.
     7.7 +