changeset 2:2845dca6a28b

Updated VCilk to same VMS version as SSR, for correct blocked MM Nov 8
author Me
date Mon, 08 Nov 2010 03:58:41 -0800
parents b6ce47a0909b
children b98f0f8da7d9
files VCilk.h VCilk_PluginFns.c VCilk_lib.c
diffstat 3 files changed, 368 insertions(+), 55 deletions(-) [+]
line diff
     1.1 --- a/VCilk.h	Sun Nov 07 06:53:21 2010 -0800
     1.2 +++ b/VCilk.h	Mon Nov 08 03:58:41 2010 -0800
     1.3 @@ -13,9 +13,19 @@
     1.4  #include "VMS/Hash_impl/PrivateHash.h"
     1.5  #include "VMS/VMS.h"
     1.6  
     1.7 +
     1.8 +
     1.9  /*This header defines everything specific to the VCilk semantic plug-in
    1.10   */
    1.11 +
    1.12 +//===========================================================================
    1.13 +#define NUM_STRUCS_IN_SEM_ENV 1000
    1.14 +
    1.15 +//===========================================================================
    1.16  typedef struct _VCilkSemReq   VCilkSemReq;
    1.17 +typedef void  (*PtrToAtomicFn )   ( void * ); //executed atomically in master
    1.18 +
    1.19 +//===========================================================================
    1.20  
    1.21  
    1.22  /*Semantic layer-specific data sent inside a request from lib called in app
    1.23 @@ -25,35 +35,71 @@
    1.24   {
    1.25     syncReq = 1,
    1.26     mallocReq,
    1.27 -   freeReq
    1.28 +   freeReq,
    1.29 +   singleton,
    1.30 +   atomic,
    1.31 +   trans_start,
    1.32 +   trans_end
    1.33   };
    1.34  
    1.35  struct _VCilkSemReq
    1.36   { enum VCilkReqType    reqType;
    1.37     VirtProcr           *requestingPr;
    1.38 +   
    1.39     int32                sizeToMalloc;
    1.40     void                *ptrToFree;
    1.41 +   
    1.42     VirtProcrFnPtr       fnPtr;
    1.43     void                *initData;
    1.44     int32                coreToSpawnOnto;
    1.45 +
    1.46 +   int32              singletonID;
    1.47 +   void              *endJumpPt;
    1.48 +
    1.49 +   PtrToAtomicFn      fnToExecInMaster;
    1.50 +   void              *dataForFn;
    1.51 +
    1.52 +   int32              transID;
    1.53   }
    1.54  /* VCilkSemReq */;
    1.55  
    1.56  typedef struct
    1.57   {
    1.58 +   VirtProcr      *VPCurrentlyExecuting;
    1.59 +   PrivQueueStruc *waitingVPQ;
    1.60 + }
    1.61 +VCilkTrans;
    1.62 +
    1.63 +typedef struct
    1.64 + {
    1.65     PrivQueueStruc **readyVPQs;
    1.66     HashTable       *commHashTbl;
    1.67     int32            numVirtPr;
    1.68     int32            nextCoreToGetNewPr;
    1.69     int32            primitiveStartTime;
    1.70 +
    1.71 +                       //fix limit on num with dynArray
    1.72 +   int32            singletonHasBeenExecutedFlags[NUM_STRUCS_IN_SEM_ENV];
    1.73 +   VCilkTrans       transactionStrucs[NUM_STRUCS_IN_SEM_ENV];
    1.74   }
    1.75  VCilkSemEnv;
    1.76  
    1.77 +typedef struct _TransListElem TransListElem;
    1.78 +struct _TransListElem
    1.79 + {
    1.80 +   int32          transID;
    1.81 +   TransListElem *nextTrans;
    1.82 + };
    1.83 +//TransListElem
    1.84 +
    1.85  typedef struct
    1.86   {
    1.87 -   int32 syncPending;
    1.88 -   int32 numLiveChildren;
    1.89 -   VirtProcr *parentPr;
    1.90 +   int32          syncPending;
    1.91 +   int32          numLiveChildren;
    1.92 +   VirtProcr     *parentPr;
    1.93 +   
    1.94 +   int32          highestTransEntered;
    1.95 +   TransListElem *lastTransEntered;
    1.96   }
    1.97  VCilkSemData;
    1.98  
    1.99 @@ -80,7 +126,7 @@
   1.100  VCilk__init();
   1.101  
   1.102  void
   1.103 -VCilk__cleanup_after_shutdown();
   1.104 +VCilk__cleanup_at_end_of_shutdown();
   1.105  
   1.106  //=======================
   1.107  
   1.108 @@ -103,10 +149,21 @@
   1.109  void
   1.110  VCilk__dissipate_procr( VirtProcr *procrToDissipate );
   1.111  
   1.112 -//=======================
   1.113 +
   1.114 +//======================= Concurrency Stuff ======================
   1.115 +void
   1.116 +VCilk__start_singleton( int32 singletonID, void *endSingletonLabelAddr,
   1.117 +                        VirtProcr *animPr );
   1.118  
   1.119  void
   1.120 -VCilk__free_semantic_request( VCilkSemReq *semReq );
   1.121 +VCilk__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
   1.122 +                                      void *data, VirtProcr *animPr );
   1.123 +
   1.124 +void
   1.125 +VCilk__start_transaction( int32 transactionID, VirtProcr *animPr );
   1.126 +
   1.127 +void
   1.128 +VCilk__end_transaction( int32 transactionID, VirtProcr *animPr );
   1.129  
   1.130  
   1.131  //=========================  Internal use only  =============================
     2.1 --- a/VCilk_PluginFns.c	Sun Nov 07 06:53:21 2010 -0800
     2.2 +++ b/VCilk_PluginFns.c	Mon Nov 08 03:58:41 2010 -0800
     2.3 @@ -6,7 +6,6 @@
     2.4  
     2.5  #include <stdio.h>
     2.6  #include <stdlib.h>
     2.7 -#include <malloc.h>
     2.8  
     2.9  #include "VMS/Queue_impl/PrivateQueue.h"
    2.10  #include "VCilk.h"
    2.11 @@ -27,15 +26,26 @@
    2.12  handleDissipate( VirtProcr *requestingPr, VCilkSemEnv *semEnv );
    2.13  
    2.14  void inline
    2.15 -handleSpawn( VCilkSemReq *semReq, VirtProcr *requestingPr,
    2.16 -             VCilkSemEnv *semEnv  );
    2.17 +handleSpawn( VMSReqst *req, VirtProcr *requestingPr, VCilkSemEnv *semEnv );
    2.18  
    2.19  void inline
    2.20 -dispatchSemReq( VCilkSemReq *semReq, VirtProcr *requestingPr,
    2.21 -                VCilkSemEnv *semEnv );
    2.22 +dispatchSemReq( VMSReqst *req, VirtProcr *requestingPr, VCilkSemEnv *semEnv);
    2.23  
    2.24  void inline
    2.25 -resumePr( VirtProcr *procr, VCilkSemEnv *semEnv );
    2.26 +handleTransEnd( VCilkSemReq *semReq, VirtProcr *requestingPr,
    2.27 +                VCilkSemEnv*semEnv);
    2.28 +void inline
    2.29 +handleTransStart( VCilkSemReq *semReq, VirtProcr *requestingPr,
    2.30 +                  VCilkSemEnv *semEnv );
    2.31 +void inline
    2.32 +handleAtomic( VCilkSemReq *semReq, VirtProcr *requestingPr,
    2.33 +              VCilkSemEnv *semEnv);
    2.34 +void inline
    2.35 +handleSingleton( VCilkSemReq *semReq, VirtProcr *requestingPr,
    2.36 +                 VCilkSemEnv *semEnv );
    2.37 +
    2.38 +void inline
    2.39 +resume_procr( VirtProcr *procr, VCilkSemEnv *semEnv );
    2.40  
    2.41  //===========================================================================
    2.42  
    2.43 @@ -87,21 +97,19 @@
    2.44     while( req != NULL )
    2.45      {
    2.46        switch( req->reqType )
    2.47 -       { case semantic:     dispatchSemReq( VMS__take_sem_reqst_from(req),
    2.48 -                                            requestingPr, semEnv );
    2.49 +       { case semantic:     dispatchSemReq( req, requestingPr, semEnv );
    2.50              break;
    2.51           case createReq:    //create request has to come as a VMS request,
    2.52                              // to allow MasterLoop to do stuff before gets
    2.53                              // here, and maybe also stuff after all requests
    2.54                              // done -- however, can still attach semantic
    2.55                              // req data to req.
    2.56 -                            semReq = VMS__take_sem_reqst_from( req );
    2.57 -                            handleSpawn( semReq, requestingPr, semEnv );
    2.58 +                            handleSpawn(          req, requestingPr, semEnv);
    2.59              break;
    2.60 -         case dissipate:    handleDissipate( requestingPr, semEnv );
    2.61 +         case dissipate:    handleDissipate(           requestingPr, semEnv);
    2.62              break;
    2.63           case VMSSemantic:  VMS__handle_VMSSemReq(req, requestingPr, semEnv,
    2.64 -                                                  &resumePr );
    2.65 +                                                              &resume_procr);
    2.66              break;
    2.67           default:
    2.68              break;
    2.69 @@ -115,17 +123,27 @@
    2.70   }
    2.71  
    2.72  void inline
    2.73 -dispatchSemReq( VCilkSemReq *semReq, VirtProcr *requestingPr,
    2.74 -                VCilkSemEnv *semEnv )
    2.75 - {
    2.76 +dispatchSemReq( VMSReqst *req, VirtProcr *reqPr, VCilkSemEnv *semEnv )
    2.77 + { VCilkSemReq *semReq;
    2.78 +
    2.79 +   semReq = VMS__take_sem_reqst_from(req);
    2.80 +
    2.81     if( semReq == NULL ) return;
    2.82     switch( semReq->reqType )
    2.83      {
    2.84 -      case syncReq:       handleSync(           requestingPr, semEnv );
    2.85 +      case syncReq:         handleSync(                 reqPr, semEnv );
    2.86           break;
    2.87 -      case mallocReq:     handleMalloc( semReq, requestingPr, semEnv );
    2.88 +      case mallocReq:       handleMalloc(       semReq, reqPr, semEnv );
    2.89           break;
    2.90 -      case freeReq:       handleFree(   semReq, requestingPr, semEnv );
    2.91 +      case freeReq:         handleFree(         semReq, reqPr, semEnv );
    2.92 +         break;
    2.93 +      case singleton:       handleSingleton(    semReq, reqPr, semEnv );
    2.94 +         break;
    2.95 +      case atomic:          handleAtomic(       semReq, reqPr, semEnv );
    2.96 +         break;
    2.97 +      case trans_start:     handleTransStart(   semReq, reqPr, semEnv );
    2.98 +         break;
    2.99 +      case trans_end:       handleTransEnd(     semReq, reqPr, semEnv );
   2.100           break;
   2.101      }
   2.102     //NOTE: semantic request data strucs allocated on stack in VCilk Lib calls
   2.103 @@ -135,7 +153,7 @@
   2.104  
   2.105  //=========================== Request Handlers ==============================
   2.106  void inline
   2.107 -resumePr( VirtProcr *procr, VCilkSemEnv *semEnv )
   2.108 +resume_procr( VirtProcr *procr, VCilkSemEnv *semEnv )
   2.109   {
   2.110     writePrivQ( procr, semEnv->readyVPQs[ procr->coreAnimatedBy] );
   2.111   }
   2.112 @@ -152,7 +170,7 @@
   2.113   {
   2.114     if(((VCilkSemData *)(requestingPr->semanticData))->numLiveChildren  == 0 )
   2.115      { //no live children to wait for
   2.116 -      resumePr( requestingPr, semEnv );
   2.117 +      resume_procr( requestingPr, semEnv );
   2.118      }
   2.119     else
   2.120      {
   2.121 @@ -168,8 +186,8 @@
   2.122   { void *ptr;
   2.123     
   2.124     ptr = VMS__malloc( semReq->sizeToMalloc );
   2.125 -   requestingPr->dataReturnedFromReq = ptr;
   2.126 -   resumePr( requestingPr, semEnv );
   2.127 +   requestingPr->dataRetFromReq = ptr;
   2.128 +   resume_procr( requestingPr, semEnv );
   2.129   }
   2.130  
   2.131  /*
   2.132 @@ -179,21 +197,22 @@
   2.133              VCilkSemEnv *semEnv )
   2.134   {
   2.135     VMS__free( semReq->ptrToFree );
   2.136 -   resumePr( requestingPr, semEnv );
   2.137 +   resume_procr( requestingPr, semEnv );
   2.138   }
   2.139  
   2.140  
   2.141 -
   2.142 +//============================== VMS requests ===============================
   2.143  
   2.144  /* 
   2.145   */
   2.146  void inline
   2.147 -handleSpawn( VCilkSemReq *semReq, VirtProcr *requestingPr,
   2.148 -             VCilkSemEnv *semEnv  )
   2.149 - {
   2.150 +handleSpawn( VMSReqst *req, VirtProcr *requestingPr, VCilkSemEnv *semEnv )
   2.151 + { VCilkSemReq *semReq;
   2.152     VirtProcr    *newPr;
   2.153     VCilkSemData *semanticData;
   2.154  
   2.155 +   semReq = VMS__take_sem_reqst_from(req);
   2.156 +
   2.157        //This is running in master, so use internal version
   2.158     newPr = VMS__create_procr( semReq->fnPtr, semReq->initData );
   2.159  
   2.160 @@ -203,6 +222,9 @@
   2.161     semanticData->parentPr        = NULL;
   2.162     semanticData->syncPending     = FALSE;
   2.163  
   2.164 +   semanticData->highestTransEntered = -1;
   2.165 +   semanticData->lastTransEntered    = NULL;
   2.166 +
   2.167     newPr->semanticData = semanticData;
   2.168  
   2.169     /* add newly created to the list of live children of requester.
   2.170 @@ -234,8 +256,8 @@
   2.171      }
   2.172     #endif
   2.173  
   2.174 -   resumePr( newPr,        semEnv );
   2.175 -   resumePr( requestingPr, semEnv );
   2.176 +   resume_procr( newPr,        semEnv );
   2.177 +   resume_procr( requestingPr, semEnv );
   2.178   }
   2.179  
   2.180  
   2.181 @@ -266,7 +288,7 @@
   2.182            { //was waiting for last child to dissipate, so resume it
   2.183              ((VCilkSemData *)
   2.184               (parentPr->semanticData))->syncPending = FALSE;
   2.185 -            resumePr( parentPr, semEnv );
   2.186 +            resume_procr( parentPr, semEnv );
   2.187            }
   2.188         }
   2.189      }
   2.190 @@ -281,7 +303,137 @@
   2.191     semEnv->numVirtPr -= 1;
   2.192     if( semEnv->numVirtPr == 0 )
   2.193      {    //no more work, so shutdown
   2.194 -      VMS__handle_shutdown_reqst( requestingPr );
   2.195 +      VMS__shutdown();
   2.196      }
   2.197   }
   2.198  
   2.199 +
   2.200 +//=============================== Atomic ====================================
   2.201 +//
   2.202 +/*Uses ID as index into array of flags.  If flag already set, resumes from
   2.203 + * end-label.  Else, sets flag and resumes normally.
   2.204 + */
   2.205 +void inline
   2.206 +handleSingleton( VCilkSemReq *semReq, VirtProcr *requestingPr,
   2.207 +                 VCilkSemEnv *semEnv )
   2.208 + {
   2.209 +   if( semEnv->singletonHasBeenExecutedFlags[ semReq->singletonID ] )
   2.210 +      requestingPr->nextInstrPt = semReq->endJumpPt;
   2.211 +   else
   2.212 +      semEnv->singletonHasBeenExecutedFlags[ semReq->singletonID ] = TRUE;
   2.213 +
   2.214 +   resume_procr( requestingPr, semEnv );
   2.215 + }
   2.216 +
   2.217 +
   2.218 +/*This executes the function in the masterVP, take the function
   2.219 + * pointer out of the request and call it, then resume the VP.
   2.220 + */
   2.221 +void inline
   2.222 +handleAtomic( VCilkSemReq *semReq, VirtProcr *requestingPr,
   2.223 +              VCilkSemEnv *semEnv )
   2.224 + {
   2.225 +   semReq->fnToExecInMaster( semReq->dataForFn );
   2.226 +   resume_procr( requestingPr, semEnv );
   2.227 + }
   2.228 +
   2.229 +/*First, it looks at the VP's semantic data, to see the highest transactionID
   2.230 + * that VP
   2.231 + * already has entered.  If the current ID is not larger, it throws an
   2.232 + * exception stating a bug in the code.
   2.233 + *Otherwise it puts the current ID
   2.234 + * there, and adds the ID to a linked list of IDs entered -- the list is
   2.235 + * used to check that exits are properly ordered.
   2.236 + *Next it is uses transactionID as index into an array of transaction
   2.237 + * structures.
   2.238 + *If the "VP_currently_executing" field is non-null, then put requesting VP
   2.239 + * into queue in the struct.  (At some point a holder will request
   2.240 + * end-transaction, which will take this VP from the queue and resume it.)
   2.241 + *If NULL, then write requesting into the field and resume.
   2.242 + */
   2.243 +void inline
   2.244 +handleTransStart( VCilkSemReq *semReq, VirtProcr *requestingPr,
   2.245 +                  VCilkSemEnv *semEnv )
   2.246 + { VCilkSemData *semData;
   2.247 +   TransListElem *nextTransElem;
   2.248 +
   2.249 +      //check ordering of entering transactions is correct
   2.250 +   semData = requestingPr->semanticData;
   2.251 +   if( semData->highestTransEntered > semReq->transID )
   2.252 +    {    //throw VMS exception, which shuts down VMS.
   2.253 +      VMS__throw_exception( "transID smaller than prev", requestingPr, NULL);
   2.254 +    }
   2.255 +      //add this trans ID to the list of transactions entered -- check when
   2.256 +      // end a transaction
   2.257 +   semData->highestTransEntered = semReq->transID;
   2.258 +   nextTransElem = VMS__malloc( sizeof(TransListElem) );
   2.259 +   nextTransElem->transID = semReq->transID;
   2.260 +   nextTransElem->nextTrans = semData->lastTransEntered;
   2.261 +   semData->lastTransEntered = nextTransElem;
   2.262 +
   2.263 +      //get the structure for this transaction ID
   2.264 +   VCilkTrans *
   2.265 +   transStruc = &(semEnv->transactionStrucs[ semReq->transID ]);
   2.266 +
   2.267 +   if( transStruc->VPCurrentlyExecuting == NULL )
   2.268 +    {
   2.269 +      transStruc->VPCurrentlyExecuting = requestingPr;
   2.270 +      resume_procr( requestingPr, semEnv );
   2.271 +    }
   2.272 +   else
   2.273 +    {    //note, might make future things cleaner if save request with VP and
   2.274 +         // add this trans ID to the linked list when gets out of queue.
   2.275 +         // but don't need for now, and lazy..
   2.276 +      writePrivQ( requestingPr, transStruc->waitingVPQ );
   2.277 +    }
   2.278 + }
   2.279 +
   2.280 +
   2.281 +/*Use the trans ID to get the transaction structure from the array.
   2.282 + *Look at VP_currently_executing to be sure it's same as requesting VP.
   2.283 + * If different, throw an exception, stating there's a bug in the code.
   2.284 + *Next, take the first element off the list of entered transactions.
   2.285 + * Check to be sure the ending transaction is the same ID as the next on
   2.286 + * the list.  If not, incorrectly nested so throw an exception.
   2.287 + *
   2.288 + *Next, get from the queue in the structure.
   2.289 + *If it's empty, set VP_currently_executing field to NULL and resume
   2.290 + * requesting VP.
   2.291 + *If get somethine, set VP_currently_executing to the VP from the queue, then
   2.292 + * resume both.
   2.293 + */
   2.294 +void inline
   2.295 +handleTransEnd( VCilkSemReq *semReq, VirtProcr *requestingPr,
   2.296 +                VCilkSemEnv *semEnv )
   2.297 + { VCilkSemData    *semData;
   2.298 +   VirtProcr     *waitingPr;
   2.299 +   VCilkTrans      *transStruc;
   2.300 +   TransListElem *lastTrans;
   2.301 +
   2.302 +   transStruc = &(semEnv->transactionStrucs[ semReq->transID ]);
   2.303 +
   2.304 +      //make sure transaction ended in same VP as started it.
   2.305 +   if( transStruc->VPCurrentlyExecuting != requestingPr )
   2.306 +    {
   2.307 +      VMS__throw_exception( "trans ended in diff VP", requestingPr, NULL );
   2.308 +    }
   2.309 +
   2.310 +      //make sure nesting is correct -- last ID entered should == this ID
   2.311 +   semData = requestingPr->semanticData;
   2.312 +   lastTrans = semData->lastTransEntered;
   2.313 +   if( lastTrans->transID != semReq->transID )
   2.314 +    {
   2.315 +      VMS__throw_exception( "trans incorrectly nested", requestingPr, NULL );
   2.316 +    }
   2.317 +
   2.318 +   semData->lastTransEntered = semData->lastTransEntered->nextTrans;
   2.319 +
   2.320 +
   2.321 +   waitingPr = readPrivQ( transStruc->waitingVPQ );
   2.322 +   transStruc->VPCurrentlyExecuting = waitingPr;
   2.323 +
   2.324 +   if( waitingPr != NULL )
   2.325 +      resume_procr( waitingPr, semEnv );
   2.326 +
   2.327 +   resume_procr( requestingPr, semEnv );
   2.328 + }
     3.1 --- a/VCilk_lib.c	Sun Nov 07 06:53:21 2010 -0800
     3.2 +++ b/VCilk_lib.c	Mon Nov 08 03:58:41 2010 -0800
     3.3 @@ -6,7 +6,6 @@
     3.4  
     3.5  #include <stdio.h>
     3.6  #include <stdlib.h>
     3.7 -#include <malloc.h>
     3.8  
     3.9  #include "VMS/VMS.h"
    3.10  #include "VCilk.h"
    3.11 @@ -106,14 +105,17 @@
    3.12        // and which then calls create() to create more, thereby expanding work
    3.13        //Note, have to use external version of VMS__create_procr because
    3.14        // internal version uses VMS__malloc, which hasn't been set up by here
    3.15 -   seedPr = VMS_ext__create_procr( fnPtr, initData );
    3.16 +   seedPr = VMS__create_procr( fnPtr, initData );
    3.17     VCilkSemData *
    3.18 -   semanticData = malloc( sizeof(VCilkSemData) );
    3.19 +   semanticData = VMS__malloc( sizeof(VCilkSemData) );
    3.20  
    3.21     semanticData->numLiveChildren = 0;
    3.22     semanticData->parentPr        = NULL;
    3.23     semanticData->syncPending     = FALSE;
    3.24  
    3.25 +   semanticData->highestTransEntered = -1;
    3.26 +   semanticData->lastTransEntered    = NULL;
    3.27 +   
    3.28     seedPr->semanticData = semanticData;
    3.29     seedPr->coreAnimatedBy = semEnv->nextCoreToGetNewPr++;
    3.30  
    3.31 @@ -126,7 +128,7 @@
    3.32     VMS__start_the_work_then_wait_until_done();      //normal multi-thd
    3.33     #endif
    3.34  
    3.35 -   VCilk__cleanup_after_shutdown();
    3.36 +   VCilk__cleanup_at_end_of_shutdown();
    3.37   }
    3.38  
    3.39  
    3.40 @@ -165,7 +167,8 @@
    3.41   { int32 endTime, startTime;
    3.42     //TODO: fix by repeating time-measurement
    3.43     saveLowTimeStampCountInto( endTime );
    3.44 -   startTime = ((VCilkSemEnv *)(_VMSMasterEnv->semanticEnv))->primitiveStartTime;
    3.45 +   startTime = ( (VCilkSemEnv *)
    3.46 +                 (_VMSMasterEnv->semanticEnv))->primitiveStartTime;
    3.47     return (endTime - startTime);
    3.48   }
    3.49  
    3.50 @@ -213,14 +216,14 @@
    3.51  
    3.52        //create the semantic layer's environment (all its data) and add to
    3.53        // the master environment
    3.54 -   semanticEnv = malloc( sizeof( VCilkSemEnv ) );
    3.55 +   semanticEnv = VMS__malloc( sizeof( VCilkSemEnv ) );
    3.56     _VMSMasterEnv->semanticEnv = semanticEnv;
    3.57  
    3.58        //create the ready queue, hash tables used for pairing send to receive
    3.59        // and so forth
    3.60        //TODO: add hash tables for pairing sends with receives, and
    3.61        // initialize the data ownership system
    3.62 -   readyVPQs = malloc( NUM_CORES * sizeof(PrivQueueStruc *) );
    3.63 +   readyVPQs = VMS__malloc( NUM_CORES * sizeof(PrivQueueStruc *) );
    3.64  
    3.65     for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
    3.66      {
    3.67 @@ -230,6 +233,18 @@
    3.68     semanticEnv->readyVPQs = readyVPQs;
    3.69     
    3.70     semanticEnv->nextCoreToGetNewPr = 0;
    3.71 +
    3.72 +   //TODO: bug -- turn these arrays into dyn arrays to eliminate limit
    3.73 +   //semanticEnv->singletonHasBeenExecutedFlags = makeDynArrayInfo( );
    3.74 +   //semanticEnv->transactionStrucs = makeDynArrayInfo( );
    3.75 +   //something like: setHighestIdx( dynArrayInfo, NUM_STRUCS_IN_SEM_ENV )
    3.76 +   int32 i;
    3.77 +   for( i = 0; i < NUM_STRUCS_IN_SEM_ENV; i++ )
    3.78 +    {
    3.79 +      semanticEnv->singletonHasBeenExecutedFlags[i] = FALSE;
    3.80 +      semanticEnv->transactionStrucs[i].waitingVPQ  = makePrivQ();
    3.81 +    }
    3.82 +
    3.83   }
    3.84  
    3.85  
    3.86 @@ -237,23 +252,23 @@
    3.87   *Frees any memory allocated by VCilk__init() then calls VMS's cleanup
    3.88   */
    3.89  void
    3.90 -VCilk__cleanup_after_shutdown()
    3.91 +VCilk__cleanup_at_end_of_shutdown()
    3.92   { VCilkSemEnv *semanticEnv;
    3.93 -   int coreIdx;
    3.94   
    3.95     semanticEnv = _VMSMasterEnv->semanticEnv;
    3.96  
    3.97 -//TODO: double check all sem env locations freed
    3.98 -
    3.99 +   /*
   3.100 +   int32 coreIdx;
   3.101     for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
   3.102      {
   3.103 -      free( semanticEnv->readyVPQs[coreIdx]->startOfData );
   3.104 -      free( semanticEnv->readyVPQs[coreIdx] );
   3.105 +      VMS__free( semanticEnv->readyVPQs[coreIdx]->startOfData );
   3.106 +      VMS__free( semanticEnv->readyVPQs[coreIdx] );
   3.107      }
   3.108 -   free( semanticEnv->readyVPQs );
   3.109 +   VMS__free( semanticEnv->readyVPQs );
   3.110     
   3.111 -   free( _VMSMasterEnv->semanticEnv );
   3.112 -   VMS__cleanup_after_shutdown();
   3.113 +   VMS__free( _VMSMasterEnv->semanticEnv );
   3.114 +    */
   3.115 +   VMS__cleanup_at_end_of_shutdown();
   3.116   }
   3.117  
   3.118  
   3.119 @@ -322,7 +337,7 @@
   3.120  
   3.121     VMS__send_sem_request( &reqData, animPr );
   3.122  
   3.123 -   return animPr->dataReturnedFromReq;
   3.124 +   return animPr->dataRetFromReq;
   3.125   }
   3.126  
   3.127  
   3.128 @@ -339,3 +354,92 @@
   3.129     VMS__send_sem_request( &reqData, animPr );
   3.130   }
   3.131  
   3.132 +//===========================================================================
   3.133 +
   3.134 +/*Uses ID as index into array of flags.  If flag already set, resumes from
   3.135 + * end-label.  Else, sets flag and resumes normally.
   3.136 + */
   3.137 +void
   3.138 +VCilk__start_singleton( int32 singletonID, void *endSingletonLabelAddr,
   3.139 +                      VirtProcr *animPr )
   3.140 + {
   3.141 +   VCilkSemReq  reqData;
   3.142 +
   3.143 +      //
   3.144 +   reqData.reqType     = singleton;
   3.145 +   reqData.singletonID = singletonID;
   3.146 +   reqData.endJumpPt   = endSingletonLabelAddr;
   3.147 +
   3.148 +   VMS__send_sem_request( &reqData, animPr );
   3.149 + }
   3.150 +
   3.151 +/*This executes the function in the masterVP, so it executes in isolation
   3.152 + * from any other copies -- only one copy of the function can ever execute
   3.153 + * at a time.
   3.154 + *
   3.155 + *It suspends to the master, and the request handler takes the function
   3.156 + * pointer out of the request and calls it, then resumes the VP.
   3.157 + *Only very short functions should be called this way -- for longer-running
   3.158 + * isolation, use transaction-start and transaction-end, which run the code
   3.159 + * between as work-code.
   3.160 + */
   3.161 +void
   3.162 +VCilk__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
   3.163 +                                    void *data, VirtProcr *animPr )
   3.164 + {
   3.165 +   VCilkSemReq  reqData;
   3.166 +
   3.167 +      //
   3.168 +   reqData.reqType          = atomic;
   3.169 +   reqData.fnToExecInMaster = ptrToFnToExecInMaster;
   3.170 +   reqData.dataForFn        = data;
   3.171 +
   3.172 +   VMS__send_sem_request( &reqData, animPr );
   3.173 + }
   3.174 +
   3.175 +
   3.176 +/*This suspends to the master.
   3.177 + *First, it looks at the VP's data, to see the highest transactionID that VP
   3.178 + * already has entered.  If the current ID is not larger, it throws an
   3.179 + * exception stating a bug in the code.  Otherwise it puts the current ID
   3.180 + * there, and adds the ID to a linked list of IDs entered -- the list is
   3.181 + * used to check that exits are properly ordered.
   3.182 + *Next it is uses transactionID as index into an array of transaction
   3.183 + * structures.
   3.184 + *If the "VP_currently_executing" field is non-null, then put requesting VP
   3.185 + * into queue in the struct.  (At some point a holder will request
   3.186 + * end-transaction, which will take this VP from the queue and resume it.)
   3.187 + *If NULL, then write requesting into the field and resume.
   3.188 + */
   3.189 +void
   3.190 +VCilk__start_transaction( int32 transactionID, VirtProcr *animPr )
   3.191 + {
   3.192 +   VCilkSemReq  reqData;
   3.193 +
   3.194 +      //
   3.195 +   reqData.reqType     = trans_start;
   3.196 +   reqData.transID     = transactionID;
   3.197 +
   3.198 +   VMS__send_sem_request( &reqData, animPr );
   3.199 + }
   3.200 +
   3.201 +/*This suspends to the master, then uses transactionID as index into an
   3.202 + * array of transaction structures.
   3.203 + *It looks at VP_currently_executing to be sure it's same as requesting VP.
   3.204 + * If different, throws an exception, stating there's a bug in the code.
   3.205 + *Next it looks at the queue in the structure.
   3.206 + *If it's empty, it sets VP_currently_executing field to NULL and resumes.
   3.207 + *If something in, gets it, sets VP_currently_executing to that VP, then
   3.208 + * resumes both.
   3.209 + */
   3.210 +void
   3.211 +VCilk__end_transaction( int32 transactionID, VirtProcr *animPr )
   3.212 + {
   3.213 +   VCilkSemReq  reqData;
   3.214 +
   3.215 +      //
   3.216 +   reqData.reqType     = trans_end;
   3.217 +   reqData.transID     = transactionID;
   3.218 +
   3.219 +   VMS__send_sem_request( &reqData, animPr );
   3.220 + }
   3.221 \ No newline at end of file