changeset 17:bf57b83019e5

Added atomic fn exec, singleton, trans start and end and fixed bus (contd) Fixed double-free of waiting requests bug Fixed place didn't clone in request handling Changed malloc and free handler prototypes
author Me
date Tue, 02 Nov 2010 16:57:45 -0700
parents 6c6d7fbd7e25
children cee3eecc5c22
files SSR.h SSR_PluginFns.c SSR_Request_Handlers.c SSR_Request_Handlers.h SSR_lib.c
diffstat 5 files changed, 687 insertions(+), 248 deletions(-) [+]
line diff
     1.1 --- a/SSR.h	Thu Oct 14 17:06:28 2010 -0700
     1.2 +++ b/SSR.h	Tue Nov 02 16:57:45 2010 -0700
     1.3 @@ -13,10 +13,17 @@
     1.4  #include "VMS/Hash_impl/PrivateHash.h"
     1.5  #include "VMS/VMS.h"
     1.6  
     1.7 +
     1.8 +//===========================================================================
     1.9 +
    1.10 +#define NUM_STRUCS_IN_SEM_ENV 1000
    1.11 +
    1.12 +//===========================================================================
    1.13  /*This header defines everything specific to the SSR semantic plug-in
    1.14   */
    1.15  typedef struct _SSRSemReq   SSRSemReq;
    1.16 -
    1.17 +typedef void  (*PtrToAtomicFn )   ( void * ); //executed atomically in master
    1.18 +//===========================================================================
    1.19  
    1.20  /*Semantic layer-specific data sent inside a request from lib called in app
    1.21   * to request handler called in MasterLoop
    1.22 @@ -29,19 +36,48 @@
    1.23     receive_type,   // and receive_any first of the receives -- Handlers
    1.24     receive_from_to,// rely upon this ordering of enum
    1.25     transfer_to,
    1.26 -   transfer_out
    1.27 +   transfer_out,
    1.28 +   malloc_req,
    1.29 +   free_req,
    1.30 +   singleton,
    1.31 +   atomic,
    1.32 +   trans_start,
    1.33 +   trans_end
    1.34   };
    1.35  
    1.36  struct _SSRSemReq
    1.37   { enum SSRReqType    reqType;
    1.38 -   VirtProcr           *sendPr;
    1.39 -   VirtProcr           *receivePr;
    1.40 -   int32                msgType;
    1.41 -   void                *msg;
    1.42 +   VirtProcr         *sendPr;
    1.43 +   VirtProcr         *receivePr;
    1.44 +   int32              msgType;
    1.45 +   void              *msg;
    1.46     SSRSemReq         *nextReqInHashEntry;
    1.47 +
    1.48 +   void              *initData;
    1.49 +   VirtProcrFnPtr     fnPtr;
    1.50 +   int32              coreToScheduleOnto;
    1.51 +
    1.52 +   int32              sizeToMalloc;
    1.53 +   void              *ptrToFree;
    1.54 +
    1.55 +   int32              singletonID;
    1.56 +   void              *endJumpPt;
    1.57 +
    1.58 +   PtrToAtomicFn      fnToExecInMaster;
    1.59 +   void              *dataForFn;
    1.60 +
    1.61 +   int32              transID;
    1.62   }
    1.63  /* SSRSemReq */;
    1.64  
    1.65 +
    1.66 +typedef struct
    1.67 + {
    1.68 +   VirtProcr      *VPCurrentlyExecuting;
    1.69 +   PrivQueueStruc *waitingVPQ;
    1.70 + }
    1.71 +SSRTrans;
    1.72 +
    1.73  typedef struct
    1.74   {
    1.75     PrivQueueStruc **readyVPQs;
    1.76 @@ -49,10 +85,28 @@
    1.77     int32            numVirtPr;
    1.78     int32            nextCoreToGetNewPr;
    1.79     int32            primitiveStartTime;
    1.80 +
    1.81 +                       //fix limit on num with dynArray
    1.82 +   int32            singletonHasBeenExecutedFlags[NUM_STRUCS_IN_SEM_ENV];
    1.83 +   SSRTrans         transactionStrucs[NUM_STRUCS_IN_SEM_ENV];
    1.84   }
    1.85  SSRSemEnv;
    1.86  
    1.87  
    1.88 +typedef struct _TransListElem TransListElem;
    1.89 +struct _TransListElem
    1.90 + {
    1.91 +   int32          transID;
    1.92 +   TransListElem *nextTrans;
    1.93 + };
    1.94 +
    1.95 +typedef struct
    1.96 + {
    1.97 +   int32          highestTransEntered;
    1.98 +   TransListElem *lastTransEntered;
    1.99 + }
   1.100 +SSRSemData;
   1.101 + 
   1.102  //===========================================================================
   1.103  
   1.104  void
   1.105 @@ -70,6 +124,9 @@
   1.106  int32
   1.107  SSR__giveIdealNumWorkUnits();
   1.108  
   1.109 +int32
   1.110 +SSR__give_number_of_cores_to_schedule_onto();
   1.111 +
   1.112  //=======================
   1.113  
   1.114  void
   1.115 @@ -84,12 +141,19 @@
   1.116  SSR__create_procr_with( VirtProcrFnPtr fnPtr, void *initData,
   1.117                            VirtProcr *creatingPr );
   1.118  
   1.119 +inline VirtProcr *
   1.120 +SSR__create_procr_with_affinity( VirtProcrFnPtr fnPtr,    void *initData,
   1.121 +                            VirtProcr *creatingPr, int32 coreToScheduleOnto);
   1.122 +
   1.123  void
   1.124  SSR__dissipate_procr( VirtProcr *procrToDissipate );
   1.125  
   1.126  //=======================
   1.127  void *
   1.128 -SSR__malloc_size_to( int numBytes, VirtProcr *ownerPr );
   1.129 +SSR__malloc_to( int numBytes, VirtProcr *ownerPr );
   1.130 +
   1.131 +void
   1.132 +SSR__free( void *ptrToFree, VirtProcr *owningPr );
   1.133  
   1.134  void
   1.135  SSR__transfer_ownership_of_from_to( void *data, VirtProcr *oldOwnerPr,
   1.136 @@ -121,10 +185,20 @@
   1.137  SSR__receive_from_to( VirtProcr *sendPr, VirtProcr *receivePr );
   1.138  
   1.139  
   1.140 -//=======================
   1.141 +//======================= Concurrency Stuff ======================
   1.142 +void
   1.143 +SSR__start_singleton( int32 singletonID, void *endSingletonLabelAddr,
   1.144 +                      VirtProcr *animPr );
   1.145  
   1.146  void
   1.147 -SSR__free_semantic_request( SSRSemReq *semReq );
   1.148 +SSR__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
   1.149 +                                    void *data, VirtProcr *animPr );
   1.150 +
   1.151 +void
   1.152 +SSR__start_transaction( int32 transactionID, VirtProcr *animPr );
   1.153 +
   1.154 +void
   1.155 +SSR__end_transaction( int32 transactionID, VirtProcr *animPr );
   1.156  
   1.157  
   1.158  //=========================  Internal use only  =============================
     2.1 --- a/SSR_PluginFns.c	Thu Oct 14 17:06:28 2010 -0700
     2.2 +++ b/SSR_PluginFns.c	Tue Nov 02 16:57:45 2010 -0700
     2.3 @@ -6,13 +6,49 @@
     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 "SSR.h"
    2.11  #include "SSR_Request_Handlers.h"
    2.12  
    2.13 +//=========================== Local Fn Prototypes ===========================
    2.14 +void inline
    2.15 +resumePr( VirtProcr *procr, SSRSemEnv *semEnv );
    2.16  
    2.17 +void inline
    2.18 +handleSemReq( VMSReqst *req, VirtProcr *requestingPr, SSRSemEnv *semEnv );
    2.19 +
    2.20 +void
    2.21 +handleDissipate(             VirtProcr *requestingPr, SSRSemEnv *semEnv );
    2.22 +
    2.23 +void
    2.24 +handleCreate( VMSReqst *req, VirtProcr *requestingPr, SSRSemEnv *semEnv  );
    2.25 +
    2.26 +
    2.27 +//============================== Scheduler ==================================
    2.28 +//
    2.29 +/*For SSR, scheduling a slave simply takes the next work-unit off the
    2.30 + * ready-to-go work-unit queue and assigns it to the slaveToSched.
    2.31 + *If the ready-to-go work-unit queue is empty, then nothing to schedule
    2.32 + * to the slave -- return FALSE to let Master loop know scheduling that
    2.33 + * slave failed.
    2.34 + */
    2.35 +VirtProcr *
    2.36 +SSR__schedule_virt_procr( void *_semEnv, int coreNum )
    2.37 + { VirtProcr   *schedPr;
    2.38 +   SSRSemEnv *semEnv;
    2.39 +
    2.40 +   semEnv  = (SSRSemEnv *)_semEnv;
    2.41 +
    2.42 +   schedPr = readPrivQ( semEnv->readyVPQs[coreNum] );
    2.43 +      //Note, using a non-blocking queue -- it returns NULL if queue empty
    2.44 +
    2.45 +   return( schedPr );
    2.46 + }
    2.47 +
    2.48 +
    2.49 +//===========================  Request Handler  =============================
    2.50 +//
    2.51  /*Will get requests to send, to receive, and to create new processors.
    2.52   * Upon send, check the hash to see if a receive is waiting.
    2.53   * Upon receive, check hash to see if a send has already happened.
    2.54 @@ -27,99 +63,132 @@
    2.55  SSR__Request_Handler( VirtProcr *requestingPr, void *_semEnv )
    2.56   { SSRSemEnv *semEnv;
    2.57     VMSReqst    *req;
    2.58 -   SSRSemReq *semReq;
    2.59   
    2.60     semEnv = (SSRSemEnv *)_semEnv;
    2.61  
    2.62 -   req = VMS__take_top_request_from( requestingPr );
    2.63 -   
    2.64 +   req    = VMS__take_next_request_out_of( requestingPr );
    2.65 +
    2.66     while( req != NULL )
    2.67      {
    2.68 -      if( VMS__isSemanticReqst( req ) )
    2.69 -       {
    2.70 -         semReq = VMS__take_sem_reqst_from( req );
    2.71 -         if( semReq == NULL ) goto DoneHandlingReqst;
    2.72 -         switch( semReq->reqType )
    2.73 -          {
    2.74 -            case send_type:       handleSendType(     semReq, semEnv);
    2.75 -               break;
    2.76 -            case send_from_to:    handleSendFromTo(   semReq, semEnv);
    2.77 -               break;
    2.78 -            case receive_type:    handleReceiveType(  semReq, semEnv);
    2.79 -               break;
    2.80 -            case receive_from_to: handleReceiveFromTo(semReq, semEnv);
    2.81 -               break;
    2.82 -            case transfer_to:     handleTransferTo(   semReq, semEnv);
    2.83 -               SSR__free_semantic_request( semReq );
    2.84 -               break;
    2.85 -            case transfer_out:    handleTransferOut(  semReq, semEnv);
    2.86 -               SSR__free_semantic_request( semReq );
    2.87 -               break;
    2.88 -          }
    2.89 -         //NOTE: freeing semantic request data strucs handled inside these
    2.90 +      switch( req->reqType )
    2.91 +       { case semantic:     handleSemReq(         req, requestingPr, semEnv);
    2.92 +            break;
    2.93 +         case createReq:    handleCreate(         req, requestingPr, semEnv);
    2.94 +            break;
    2.95 +         case dissipate:    handleDissipate(           requestingPr, semEnv);
    2.96 +            break;
    2.97 +         case VMSSemantic:  VMS__handle_VMSSemReq(req, requestingPr, semEnv,
    2.98 +                                                                  &resumePr);
    2.99 +            break;
   2.100 +         default:
   2.101 +            break;
   2.102         }
   2.103 -      else if( VMS__isCreateReqst( req ) ) //only plugin can add to ready Q
   2.104 -       { VirtProcr *
   2.105 -         newPr = (VirtProcr *)req->semReqData;
   2.106 -         semEnv->numVirtPr += 1;
   2.107 +      
   2.108 +      req = VMS__take_next_request_out_of( requestingPr );
   2.109 +    } //while( req != NULL )
   2.110  
   2.111 -            //Assign new processor to next core in line & queue it up
   2.112 -         #ifdef DEBUG
   2.113 -         newPr->coreAnimatedBy = 0;
   2.114 -         #else
   2.115 -         newPr->coreAnimatedBy = semEnv->nextCoreToGetNewPr;
   2.116 -         if( semEnv->nextCoreToGetNewPr >= NUM_CORES - 1 )
   2.117 -             semEnv->nextCoreToGetNewPr  = 0;
   2.118 -         else
   2.119 -             semEnv->nextCoreToGetNewPr += 1;
   2.120 -         #endif
   2.121 -         writePrivQ( newPr, semEnv->readyVPQs[requestingPr->coreAnimatedBy]);
   2.122 -
   2.123 -            //resume procr that asked for registration
   2.124 -         writePrivQ( requestingPr, 
   2.125 -                            semEnv->readyVPQs[requestingPr->coreAnimatedBy]);
   2.126 -       }
   2.127 -      else if( VMS__isDissipateReqst( req ) )
   2.128 -       {
   2.129 -            //free any semantic data allocated to the virt procr
   2.130 -
   2.131 -            //Now, call VMS to free_all AppVP state -- stack and so on
   2.132 -         VMS__handle_dissipate_reqst( requestingPr );
   2.133 -
   2.134 -         semEnv->numVirtPr -= 1;
   2.135 -         if( semEnv->numVirtPr == 0 )
   2.136 -          {    //no more work, so shutdown
   2.137 -            VMS__handle_shutdown_reqst( requestingPr );
   2.138 -          }
   2.139 -       }
   2.140 -
   2.141 -      DoneHandlingReqst:
   2.142 -         //Free VMS portion of request, no matter what -- sem request data
   2.143 -         // struc instances may still be around..  VMS__free_request doesn't
   2.144 -         // affect the semantic request that was carried by it
   2.145 -      req = VMS__free_top_and_give_next_request_from( requestingPr );
   2.146 -    } //while( req != NULL )
   2.147   }
   2.148  
   2.149 -//===========================================================================
   2.150  
   2.151 +void inline
   2.152 +handleSemReq( VMSReqst *req, VirtProcr *reqPr, SSRSemEnv *semEnv )
   2.153 + { SSRSemReq *semReq;
   2.154  
   2.155 -/*For SSR, scheduling a slave simply takes the next work-unit off the
   2.156 - * ready-to-go work-unit queue and assigns it to the slaveToSched.
   2.157 - *If the ready-to-go work-unit queue is empty, then nothing to schedule
   2.158 - * to the slave -- return FALSE to let Master loop know scheduling that
   2.159 - * slave failed.
   2.160 - */
   2.161 -VirtProcr *
   2.162 -SSR__schedule_virt_procr( void *_semEnv, int coreNum )
   2.163 - { VirtProcr   *schedPr;
   2.164 -   SSRSemEnv *semEnv;
   2.165 -
   2.166 -   semEnv = (SSRSemEnv *)_semEnv;
   2.167 -
   2.168 -   schedPr = readPrivQ( semEnv->readyVPQs[coreNum] );
   2.169 -      //Note, using a non-blocking queue -- it returns NULL if queue empty
   2.170 -
   2.171 -   return( schedPr );
   2.172 +   semReq = VMS__take_sem_reqst_from(req);
   2.173 +   if( semReq == NULL ) return;
   2.174 +   switch( semReq->reqType )  //sem handlers are all in other file
   2.175 +    {
   2.176 +      case send_type:       handleSendType(     semReq,        semEnv);
   2.177 +         break;
   2.178 +      case send_from_to:    handleSendFromTo(   semReq,        semEnv);
   2.179 +         break;
   2.180 +      case receive_type:    handleReceiveType(  semReq,        semEnv);
   2.181 +         break;
   2.182 +      case receive_from_to: handleReceiveFromTo(semReq,        semEnv);
   2.183 +         break;
   2.184 +      case transfer_to:     handleTransferTo(   semReq,        semEnv);
   2.185 +         break;
   2.186 +      case transfer_out:    handleTransferOut(  semReq,        semEnv);
   2.187 +         break;
   2.188 +      case malloc_req:      handleMalloc(       semReq, reqPr, semEnv);
   2.189 +         break;
   2.190 +      case free_req:        handleFree(         semReq, reqPr, semEnv);
   2.191 +         break;
   2.192 +      case singleton:       handleSingleton(    semReq, reqPr, semEnv);
   2.193 +         break;
   2.194 +      case atomic:          handleAtomic(       semReq, reqPr, semEnv);
   2.195 +         break;
   2.196 +      case trans_start:     handleTransStart(   semReq, reqPr, semEnv);
   2.197 +         break;
   2.198 +      case trans_end:       handleTransEnd(     semReq, reqPr, semEnv);
   2.199 +         break;
   2.200 +    }
   2.201   }
   2.202  
   2.203 +
   2.204 +
   2.205 +//=========================== VMS Request Handlers ==============================
   2.206 +//
   2.207 +void
   2.208 +handleDissipate( VirtProcr *requestingPr, SSRSemEnv *semEnv )
   2.209 + {
   2.210 +      //free any semantic data allocated to the virt procr
   2.211 +
   2.212 +      //Now, call VMS to free_all AppVP state -- stack and so on
   2.213 +   VMS__dissipate_procr( requestingPr );
   2.214 +
   2.215 +   semEnv->numVirtPr -= 1;
   2.216 +   if( semEnv->numVirtPr == 0 )
   2.217 +    {    //no more work, so shutdown
   2.218 +      VMS__shutdown();
   2.219 +    }
   2.220 + }
   2.221 +
   2.222 +void
   2.223 +handleCreate( VMSReqst *req, VirtProcr *requestingPr, SSRSemEnv *semEnv  )
   2.224 + { SSRSemReq *semReq;
   2.225 +   VirtProcr    *newPr;
   2.226 +
   2.227 +   semReq = VMS__take_sem_reqst_from( req );
   2.228 +
   2.229 +      //This is running in master, so use internal version
   2.230 +   newPr = VMS__create_procr( semReq->fnPtr, semReq->initData );
   2.231 +
   2.232 +   semEnv->numVirtPr += 1;
   2.233 +
   2.234 +      //Assign new processor to a core & transition it to ready
   2.235 +   #ifdef SEQUENTIAL
   2.236 +   newPr->coreAnimatedBy = 0;
   2.237 +
   2.238 +   #else
   2.239 +   int32
   2.240 +   coreToScheduleOnto = semReq->coreToScheduleOnto;
   2.241 +
   2.242 +   if(coreToScheduleOnto < 0 || coreToScheduleOnto >= NUM_CORES )
   2.243 +    {    //out-of-range, so round-robin assignment
   2.244 +      newPr->coreAnimatedBy = semEnv->nextCoreToGetNewPr;
   2.245 +
   2.246 +      if( semEnv->nextCoreToGetNewPr >= NUM_CORES - 1 )
   2.247 +          semEnv->nextCoreToGetNewPr  = 0;
   2.248 +      else
   2.249 +          semEnv->nextCoreToGetNewPr += 1;
   2.250 +    }
   2.251 +   else //core num in-range, so use it
   2.252 +    { newPr->coreAnimatedBy = coreToScheduleOnto;
   2.253 +    }
   2.254 +   #endif
   2.255 +
   2.256 +      //For SSR, caller needs ptr to created processor returned to it
   2.257 +   requestingPr->dataRetFromReq = newPr;
   2.258 +
   2.259 +   resumePr( newPr,        semEnv );
   2.260 +   resumePr( requestingPr, semEnv );
   2.261 + }
   2.262 +
   2.263 +
   2.264 +//=========================== Helper ==============================
   2.265 +void inline
   2.266 +resumePr( VirtProcr *procr, SSRSemEnv *semEnv )
   2.267 + {
   2.268 +   writePrivQ( procr, semEnv->readyVPQs[ procr->coreAnimatedBy] );
   2.269 + }
     3.1 --- a/SSR_Request_Handlers.c	Thu Oct 14 17:06:28 2010 -0700
     3.2 +++ b/SSR_Request_Handlers.c	Tue Nov 02 16:57:45 2010 -0700
     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 "VMS/Queue_impl/PrivateQueue.h"
    3.11 @@ -15,19 +14,41 @@
    3.12  
    3.13  
    3.14  
    3.15 +//=========================== Local Fn Prototypes ===========================
    3.16 +void inline
    3.17 +resumePr( VirtProcr *procr, SSRSemEnv *semEnv );
    3.18 +
    3.19 +
    3.20 +
    3.21  //===========================================================================
    3.22  //                           Helpers
    3.23  
    3.24 +/*Only clone the elements of req used in these reqst handlers
    3.25 + */
    3.26 +inline SSRSemReq *
    3.27 +cloneReq( SSRSemReq *semReq )
    3.28 + { SSRSemReq *clonedReq;
    3.29 +
    3.30 +   clonedReq             = VMS__malloc( sizeof(SSRSemReq) );
    3.31 +   clonedReq->reqType    = semReq->reqType;
    3.32 +   clonedReq->sendPr     = semReq->sendPr;
    3.33 +   clonedReq->msg        = semReq->msg;
    3.34 +   clonedReq->nextReqInHashEntry = NULL;
    3.35 +   
    3.36 +   return clonedReq;
    3.37 + }
    3.38 +
    3.39  HashEntry *
    3.40  giveEntryElseInsertReqst( char *key, SSRSemReq *semReq,
    3.41      HashTable   *commHashTbl )
    3.42   { HashEntry    *entry;
    3.43 -   SSRSemReq  *waitingReq;
    3.44 +   SSRSemReq    *waitingReq;
    3.45  
    3.46     entry = getEntryFromTable( (char *)key, commHashTbl );
    3.47     if( entry == NULL )
    3.48      {    //no waiting sends or receives, so add this request and exit
    3.49 -      addValueIntoTable( key, semReq, commHashTbl );
    3.50 +         // note: have to clone the request because it's on stack of sender
    3.51 +      addValueIntoTable( key, cloneReq( semReq ), commHashTbl );
    3.52        return NULL;
    3.53      }
    3.54     waitingReq = (SSRSemReq *)entry->content;
    3.55 @@ -60,7 +81,7 @@
    3.56   * separate processors can send to the same receiver, and hashing on the
    3.57   * receive processor, so they will stack up.
    3.58   */
    3.59 -void
    3.60 +void inline
    3.61  handleSendType( SSRSemReq *semReq, SSRSemEnv *semEnv )
    3.62   { VirtProcr   *sendPr, *receivePr;
    3.63     int          key[] = {0,0,0};
    3.64 @@ -82,7 +103,7 @@
    3.65     key[1] = (int)(semReq->msgType);
    3.66   //key[2] acts as the 0 that terminates the string
    3.67  
    3.68 -   entry = giveEntryElseInsertReqst( key, semReq, commHashTbl);
    3.69 +   entry = giveEntryElseInsertReqst( (char *)key, semReq, commHashTbl);
    3.70     if( entry == NULL ) return;  //was just inserted
    3.71  
    3.72     waitingReq = (SSRSemReq *)entry->content;
    3.73 @@ -90,36 +111,36 @@
    3.74        //At this point, know have waiting request(s) -- either sends or recv
    3.75        //Note, can only have max of one receive waiting, and cannot have both
    3.76        // sends and receives waiting (they would have paired off)
    3.77 -      // but can have multiple send_type requests waiting (from diff senders)
    3.78 +      // but can have multiple sends from diff sending VPs, all same msg-type
    3.79     if( waitingReq->reqType == send_type )
    3.80      {    //waiting request is another send, so stack this up on list
    3.81 -      semReq->    nextReqInHashEntry = waitingReq->nextReqInHashEntry;
    3.82 -      waitingReq->nextReqInHashEntry = semReq;
    3.83 -         PRINT2_DEBUG("linked requests: %d, %d  |  ", semReq, waitingReq )
    3.84 -         PRINT2_DEBUG("type: %d, %d\n", semReq->reqType, waitingReq->reqType)
    3.85 +         // but first clone the sending request so it persists.
    3.86 +      SSRSemReq *clonedReq = cloneReq( semReq );
    3.87 +      clonedReq-> nextReqInHashEntry = waitingReq->nextReqInHashEntry;
    3.88 +      waitingReq->nextReqInHashEntry = clonedReq;
    3.89 +         PRINT2_DEBUG("linked requests: %d, %d  |  ", clonedReq, waitingReq )
    3.90        return;
    3.91      }
    3.92     else
    3.93 -    {    //waiting request is a receive, so pair it to this send
    3.94 -         //first, remove the waiting receive request from the list in entry
    3.95 +    {    //waiting request is a receive, so it pairs to this send
    3.96 +         //First, remove the waiting receive request from the entry
    3.97        entry->content = waitingReq->nextReqInHashEntry;
    3.98 +      VMS__free( waitingReq ); //Don't use contents -- so free it
    3.99 +      
   3.100        if( entry->content == NULL )
   3.101         {    //TODO: mod hash table to double-link, so can delete entry from
   3.102              // table without hashing the key and looking it up again
   3.103 -         deleteEntryFromTable( entry->key, commHashTbl );  //frees entry too
   3.104 +         deleteEntryFromTable( entry->key, commHashTbl );  //frees hashEntry
   3.105         }
   3.106        
   3.107           //attach msg that's in this send request to receiving procr
   3.108 -         // when comes back from suspend, will have msg in semanticData
   3.109 -      receivePr->semanticData = semReq->msg;
   3.110 +         // when comes back from suspend will have msg in dataRetFromReq
   3.111 +      receivePr->dataRetFromReq = semReq->msg;
   3.112  
   3.113           //bring both processors back from suspend
   3.114 -      writePrivQ( sendPr,    semEnv->readyVPQs[sendPr->coreAnimatedBy] );
   3.115 -      writePrivQ( receivePr, semEnv->readyVPQs[receivePr->coreAnimatedBy] );
   3.116 +      resumePr( sendPr,    semEnv );
   3.117 +      resumePr( receivePr, semEnv );
   3.118  
   3.119 -         //don't need semReq anymore -- free it
   3.120 -      SSR__free_semantic_request( waitingReq );
   3.121 -      SSR__free_semantic_request( semReq );
   3.122        return;
   3.123      }
   3.124   }
   3.125 @@ -128,7 +149,7 @@
   3.126  /*Looks like can make single handler for both sends..
   3.127   */
   3.128  //TODO: combine both send handlers into single handler
   3.129 -void
   3.130 +void inline
   3.131  handleSendFromTo( SSRSemReq *semReq, SSRSemEnv *semEnv)
   3.132   { VirtProcr   *sendPr, *receivePr;
   3.133     int          key[] = {0,0,0};
   3.134 @@ -143,47 +164,44 @@
   3.135     key[1] = (int)sendPr;
   3.136   //key[2] acts at the 0 that terminates the string
   3.137  
   3.138 -   entry = giveEntryElseInsertReqst( key, semReq, commHashTbl);
   3.139 +   entry = giveEntryElseInsertReqst( (char *)key, semReq, commHashTbl);
   3.140     if( entry == NULL ) return;  //was just inserted
   3.141  
   3.142     waitingReq = (SSRSemReq *)entry->content;
   3.143  
   3.144        //At this point, know have waiting request(s) -- either sends or recv
   3.145     if( waitingReq->reqType == send_from_to )
   3.146 -    { printf("\n ERROR: shouldn't be two send from-tos waiting \n");
   3.147 +    { printf("\n ERROR: shouldn't be two send-from-tos waiting \n");
   3.148      }
   3.149     else
   3.150      {    //waiting request is a receive, so it completes pair with this send
   3.151 -
   3.152 -         //remove the waiting receive request from the entry
   3.153 +         //First, remove the waiting receive request from the entry
   3.154        entry->content = waitingReq->nextReqInHashEntry;
   3.155 +      VMS__free( waitingReq ); //Don't use contents -- so free it
   3.156 +      
   3.157           //can only be one waiting req for "from-to" semantics
   3.158        if( entry->content != NULL )
   3.159         {
   3.160           printf("\nERROR in handleSendFromTo\n");
   3.161 -         printf("waitReq: %d | next req: %d\n", waitingReq, entry->content);
   3.162         }
   3.163 -      deleteEntryFromTable( entry->key, commHashTbl );  //frees entry too
   3.164 +      deleteEntryFromTable( entry->key, commHashTbl );  //frees HashEntry
   3.165  
   3.166           //attach msg that's in this send request to receiving procr
   3.167 -         // when comes back from suspend, will have msg in semanticData
   3.168 -      receivePr->semanticData = semReq->msg;
   3.169 +         // when comes back from suspend, will have msg in dataRetFromReq
   3.170 +      receivePr->dataRetFromReq = semReq->msg;
   3.171  
   3.172           //bring both processors back from suspend
   3.173        writePrivQ( sendPr,    semEnv->readyVPQs[sendPr->coreAnimatedBy] );
   3.174        writePrivQ( receivePr, semEnv->readyVPQs[receivePr->coreAnimatedBy] );
   3.175        
   3.176 -         //done with requests, so free them
   3.177 -      SSR__free_semantic_request( waitingReq );
   3.178 -      SSR__free_semantic_request( semReq );
   3.179        return;
   3.180      }
   3.181   }
   3.182  
   3.183  
   3.184  
   3.185 -//=======================================================
   3.186 -
   3.187 +//==============================  Receives  ===========================
   3.188 +//
   3.189  /*Removed this one for now, because forces either a search or going to a
   3.190   * two-level hash table, where one level the key is the receivePr, in the
   3.191   * other level, the key is the type.
   3.192 @@ -210,14 +228,14 @@
   3.193   * If ever add receive_any, looking like this second option easier and even
   3.194   * less costly.
   3.195   */
   3.196 -void
   3.197 +void inline
   3.198  handleReceiveAny( SSRSemReq *semReq, SSRSemEnv *semEnv)
   3.199   {
   3.200   
   3.201   }
   3.202  
   3.203  
   3.204 -void
   3.205 +void inline
   3.206  handleReceiveType( SSRSemReq *semReq, SSRSemEnv *semEnv)
   3.207   { VirtProcr   *sendPr, *receivePr;
   3.208     int          key[] = {0,0,0};
   3.209 @@ -229,13 +247,13 @@
   3.210  
   3.211     key[0] = (int)receivePr;
   3.212     key[1] = (int)(semReq->msgType);
   3.213 - //key[2] acts at the 0 that terminates the string
   3.214 + //key[2] acts as the 0 that terminates the string
   3.215  
   3.216  
   3.217 -   entry = giveEntryElseInsertReqst( key, semReq, commHashTbl);
   3.218 +   entry = giveEntryElseInsertReqst((char*)key, semReq, commHashTbl);//clones
   3.219     if( entry == NULL ) return;  //was just inserted
   3.220  
   3.221 -   waitingReq = (SSRSemReq *)entry->content;
   3.222 +   waitingReq = (SSRSemReq *)entry->content;  //previously cloned by insert
   3.223  
   3.224        //At this point, know have waiting request(s) -- should be send(s)
   3.225     if( waitingReq->reqType == send_type )
   3.226 @@ -243,21 +261,20 @@
   3.227           //first, remove the waiting send request from the list in entry
   3.228        entry->content = waitingReq->nextReqInHashEntry;
   3.229        if( entry->content == NULL )
   3.230 -       { deleteEntryFromTable( entry->key, commHashTbl );  //frees entry too
   3.231 +       { deleteEntryFromTable( entry->key, commHashTbl );  //frees HashEntry
   3.232         }
   3.233        
   3.234           //attach msg that's in the send request to receiving procr
   3.235 -         // when comes back from suspend, will have msg in semanticData
   3.236 -      receivePr->semanticData = waitingReq->msg;
   3.237 +         // when comes back from suspend, will have msg in dataReturnedFromReq
   3.238 +      receivePr->dataRetFromReq = waitingReq->msg;
   3.239  
   3.240           //bring both processors back from suspend
   3.241        sendPr = waitingReq->sendPr;
   3.242 +      VMS__free( waitingReq );
   3.243 +
   3.244        writePrivQ( sendPr,    semEnv->readyVPQs[sendPr->coreAnimatedBy] );
   3.245        writePrivQ( receivePr, semEnv->readyVPQs[receivePr->coreAnimatedBy] );
   3.246  
   3.247 -         //done with requests, so free them
   3.248 -      SSR__free_semantic_request( waitingReq );
   3.249 -      SSR__free_semantic_request( semReq );
   3.250        return;
   3.251      }
   3.252     printf("\nLang Impl Error: Should never be two waiting receives!\n");
   3.253 @@ -266,7 +283,7 @@
   3.254  
   3.255  /*
   3.256   */
   3.257 -void
   3.258 +void inline
   3.259  handleReceiveFromTo( SSRSemReq *semReq, SSRSemEnv *semEnv)
   3.260   { VirtProcr   *sendPr, *receivePr;
   3.261     int          key[] = {0,0,0};
   3.262 @@ -281,7 +298,7 @@
   3.263     key[1] = (int)sendPr;
   3.264   //key[2] acts at the 0 that terminates the string
   3.265  
   3.266 -   entry = giveEntryElseInsertReqst( key, semReq, commHashTbl);
   3.267 +   entry = giveEntryElseInsertReqst( (char *)key, semReq, commHashTbl);
   3.268     if( entry == NULL ) return;  //was just inserted
   3.269  
   3.270     waitingReq = (SSRSemReq *)entry->content;
   3.271 @@ -296,17 +313,16 @@
   3.272        deleteEntryFromTable( entry->key, commHashTbl );  //frees entry too
   3.273  
   3.274           //attach msg that's in the send request to receiving procr
   3.275 -         // when comes back from suspend, will have msg in semanticData
   3.276 -      receivePr->semanticData = waitingReq->msg;
   3.277 +         // when comes back from suspend, will have msg in dataRetFromReq
   3.278 +      receivePr->dataRetFromReq = waitingReq->msg;
   3.279  
   3.280           //bring both processors back from suspend
   3.281        sendPr = waitingReq->sendPr;
   3.282 +      VMS__free( waitingReq );
   3.283 +
   3.284        writePrivQ( sendPr,    semEnv->readyVPQs[sendPr->coreAnimatedBy] );
   3.285        writePrivQ( receivePr, semEnv->readyVPQs[receivePr->coreAnimatedBy] );
   3.286  
   3.287 -         //done with requests, so free them
   3.288 -      SSR__free_semantic_request( waitingReq );
   3.289 -      SSR__free_semantic_request( semReq );
   3.290        return;
   3.291      }
   3.292     printf("\nLang Impl Error: Should never be two waiting receives!\n");
   3.293 @@ -315,16 +331,164 @@
   3.294  
   3.295  
   3.296  //===============================================
   3.297 -void
   3.298 +void inline
   3.299  handleTransferTo( SSRSemReq *semReq, SSRSemEnv *semEnv)
   3.300   {
   3.301  
   3.302   }
   3.303  
   3.304 -void
   3.305 +void inline
   3.306  handleTransferOut( SSRSemReq *semReq, SSRSemEnv *semEnv)
   3.307   {
   3.308  
   3.309   }
   3.310  
   3.311  
   3.312 +/*
   3.313 + */
   3.314 +void inline
   3.315 +handleMalloc( SSRSemReq *semReq, VirtProcr *requestingPr, SSRSemEnv *semEnv )
   3.316 + { void *ptr;
   3.317 +
   3.318 +   ptr = VMS__malloc( semReq->sizeToMalloc );
   3.319 +   requestingPr->dataRetFromReq = ptr;
   3.320 +   resumePr( requestingPr, semEnv );
   3.321 + }
   3.322 +
   3.323 +/*
   3.324 + */
   3.325 +void inline
   3.326 +handleFree( SSRSemReq *semReq, VirtProcr *requestingPr, SSRSemEnv *semEnv )
   3.327 + {
   3.328 +   VMS__free( semReq->ptrToFree );
   3.329 +   resumePr( requestingPr, semEnv );
   3.330 + }
   3.331 +
   3.332 +
   3.333 +//===========================================================================
   3.334 +//
   3.335 +/*Uses ID as index into array of flags.  If flag already set, resumes from
   3.336 + * end-label.  Else, sets flag and resumes normally.
   3.337 + */
   3.338 +void inline
   3.339 +handleSingleton( SSRSemReq *semReq, VirtProcr *requestingPr,
   3.340 +                 SSRSemEnv *semEnv )
   3.341 + {
   3.342 +   if( semEnv->singletonHasBeenExecutedFlags[ semReq->singletonID ] )
   3.343 +      requestingPr->nextInstrPt = semReq->endJumpPt;
   3.344 +   else
   3.345 +      semEnv->singletonHasBeenExecutedFlags[ semReq->singletonID ] = TRUE;
   3.346 +
   3.347 +   resumePr( requestingPr, semEnv );
   3.348 + }
   3.349 +
   3.350 +
   3.351 +/*This executes the function in the masterVP, take the function
   3.352 + * pointer out of the request and call it, then resume the VP.
   3.353 + */
   3.354 +void inline
   3.355 +handleAtomic( SSRSemReq *semReq, VirtProcr *requestingPr, SSRSemEnv *semEnv )
   3.356 + {
   3.357 +   semReq->fnToExecInMaster( semReq->dataForFn );
   3.358 +   resumePr( requestingPr, semEnv );
   3.359 + }
   3.360 +
   3.361 +/*First, it looks at the VP's semantic data, to see the highest transactionID
   3.362 + * that VP
   3.363 + * already has entered.  If the current ID is not larger, it throws an
   3.364 + * exception stating a bug in the code.
   3.365 + *Otherwise it puts the current ID
   3.366 + * there, and adds the ID to a linked list of IDs entered -- the list is
   3.367 + * used to check that exits are properly ordered.
   3.368 + *Next it is uses transactionID as index into an array of transaction
   3.369 + * structures.
   3.370 + *If the "VP_currently_executing" field is non-null, then put requesting VP
   3.371 + * into queue in the struct.  (At some point a holder will request
   3.372 + * end-transaction, which will take this VP from the queue and resume it.)
   3.373 + *If NULL, then write requesting into the field and resume.
   3.374 + */
   3.375 +void inline
   3.376 +handleTransStart( SSRSemReq *semReq, VirtProcr *requestingPr,
   3.377 +                  SSRSemEnv *semEnv )
   3.378 + { SSRSemData *semData;
   3.379 +   TransListElem *nextTransElem;
   3.380 +
   3.381 +      //check ordering of entering transactions is correct
   3.382 +   semData = requestingPr->semanticData;
   3.383 +   if( semData->highestTransEntered > semReq->transID )
   3.384 +    {    //throw VMS exception, which shuts down VMS.
   3.385 +      VMS__throw_exception( "transID smaller than prev", requestingPr, NULL);
   3.386 +    }
   3.387 +      //add this trans ID to the list of transactions entered -- check when
   3.388 +      // end a transaction
   3.389 +   semData->highestTransEntered = semReq->transID;
   3.390 +   nextTransElem = VMS__malloc( sizeof(TransListElem) );
   3.391 +   nextTransElem->transID = semReq->transID;
   3.392 +   nextTransElem->nextTrans = semData->lastTransEntered;
   3.393 +   semData->lastTransEntered = nextTransElem;
   3.394 +
   3.395 +      //get the structure for this transaction ID
   3.396 +   SSRTrans *
   3.397 +   transStruc = &(semEnv->transactionStrucs[ semReq->transID ]);
   3.398 +
   3.399 +   if( transStruc->VPCurrentlyExecuting == NULL )
   3.400 +    {
   3.401 +      transStruc->VPCurrentlyExecuting = requestingPr;
   3.402 +      resumePr( requestingPr, semEnv );
   3.403 +    }
   3.404 +   else
   3.405 +    {    //note, might make future things cleaner if save request with VP and
   3.406 +         // add this trans ID to the linked list when gets out of queue.
   3.407 +         // but don't need for now, and lazy..
   3.408 +      writePrivQ( requestingPr, transStruc->waitingVPQ );
   3.409 +    }
   3.410 + }
   3.411 +
   3.412 +
   3.413 +/*Use the trans ID to get the transaction structure from the array.
   3.414 + *Look at VP_currently_executing to be sure it's same as requesting VP.
   3.415 + * If different, throw an exception, stating there's a bug in the code.
   3.416 + *Next, take the first element off the list of entered transactions.
   3.417 + * Check to be sure the ending transaction is the same ID as the next on
   3.418 + * the list.  If not, incorrectly nested so throw an exception.
   3.419 + *
   3.420 + *Next, get from the queue in the structure.
   3.421 + *If it's empty, set VP_currently_executing field to NULL and resume
   3.422 + * requesting VP.
   3.423 + *If get somethine, set VP_currently_executing to the VP from the queue, then
   3.424 + * resume both.
   3.425 + */
   3.426 +void inline
   3.427 +handleTransEnd(SSRSemReq *semReq, VirtProcr *requestingPr, SSRSemEnv *semEnv)
   3.428 + { SSRSemData    *semData;
   3.429 +   VirtProcr     *waitingPr;
   3.430 +   SSRTrans      *transStruc;
   3.431 +   TransListElem *lastTrans;
   3.432 +   
   3.433 +   transStruc = &(semEnv->transactionStrucs[ semReq->transID ]);
   3.434 +
   3.435 +      //make sure transaction ended in same VP as started it.
   3.436 +   if( transStruc->VPCurrentlyExecuting != requestingPr )
   3.437 +    {
   3.438 +      VMS__throw_exception( "trans ended in diff VP", requestingPr, NULL );
   3.439 +    }
   3.440 +
   3.441 +      //make sure nesting is correct -- last ID entered should == this ID
   3.442 +   semData = requestingPr->semanticData;
   3.443 +   lastTrans = semData->lastTransEntered;
   3.444 +   if( lastTrans->transID != semReq->transID )
   3.445 +    {
   3.446 +      VMS__throw_exception( "trans incorrectly nested", requestingPr, NULL );
   3.447 +    }
   3.448 +
   3.449 +   semData->lastTransEntered = semData->lastTransEntered->nextTrans;
   3.450 +
   3.451 +
   3.452 +   waitingPr = readPrivQ( transStruc->waitingVPQ );
   3.453 +   transStruc->VPCurrentlyExecuting = waitingPr;
   3.454 +
   3.455 +   if( waitingPr != NULL )
   3.456 +      resumePr( waitingPr, semEnv );
   3.457 +
   3.458 +   resumePr( requestingPr, semEnv );
   3.459 + }
     4.1 --- a/SSR_Request_Handlers.h	Thu Oct 14 17:06:28 2010 -0700
     4.2 +++ b/SSR_Request_Handlers.h	Tue Nov 02 16:57:45 2010 -0700
     4.3 @@ -14,20 +14,34 @@
     4.4  /*This header defines everything specific to the SSR semantic plug-in
     4.5   */
     4.6  
     4.7 -void
     4.8 +void inline
     4.9  handleSendType( SSRSemReq *semReq, SSRSemEnv *semEnv);
    4.10 -void
    4.11 +void inline
    4.12  handleSendFromTo( SSRSemReq *semReq, SSRSemEnv *semEnv);
    4.13 -void
    4.14 +void inline
    4.15  handleReceiveAny( SSRSemReq *semReq, SSRSemEnv *semEnv);
    4.16 -void
    4.17 +void inline
    4.18  handleReceiveType( SSRSemReq *semReq, SSRSemEnv *semEnv);
    4.19 -void
    4.20 +void inline
    4.21  handleReceiveFromTo( SSRSemReq *semReq, SSRSemEnv *semEnv);
    4.22 -void
    4.23 +void inline
    4.24  handleTransferTo( SSRSemReq *semReq, SSRSemEnv *semEnv);
    4.25 -void
    4.26 +void inline
    4.27  handleTransferOut( SSRSemReq *semReq, SSRSemEnv *semEnv);
    4.28 +void inline
    4.29 +handleMalloc( SSRSemReq *semReq, VirtProcr *requestingPr, SSRSemEnv *semEnv);
    4.30 +void inline
    4.31 +handleFree( SSRSemReq *semReq, VirtProcr *requestingPr, SSRSemEnv *semEnv );
    4.32 +void inline
    4.33 +handleTransEnd(SSRSemReq *semReq, VirtProcr *requestingPr, SSRSemEnv*semEnv);
    4.34 +void inline
    4.35 +handleTransStart( SSRSemReq *semReq, VirtProcr *requestingPr,
    4.36 +                  SSRSemEnv *semEnv );
    4.37 +void inline
    4.38 +handleAtomic( SSRSemReq *semReq, VirtProcr *requestingPr, SSRSemEnv *semEnv);
    4.39 +void inline
    4.40 +handleSingleton( SSRSemReq *semReq, VirtProcr *requestingPr,
    4.41 +                 SSRSemEnv *semEnv );
    4.42  
    4.43  #endif	/* _SSR_REQ_H */
    4.44  
     5.1 --- a/SSR_lib.c	Thu Oct 14 17:06:28 2010 -0700
     5.2 +++ b/SSR_lib.c	Tue Nov 02 16:57:45 2010 -0700
     5.3 @@ -94,7 +94,7 @@
     5.4   { SSRSemEnv *semEnv;
     5.5     VirtProcr *seedPr;
     5.6  
     5.7 -   #ifdef DEBUG
     5.8 +   #ifdef SEQUENTIAL
     5.9     SSR__init_Seq();  //debug sequential exe
    5.10     #else
    5.11     SSR__init();      //normal multi-thd
    5.12 @@ -110,7 +110,7 @@
    5.13     writePrivQ( seedPr, semEnv->readyVPQs[seedPr->coreAnimatedBy] );
    5.14     semEnv->numVirtPr = 1;
    5.15  
    5.16 -   #ifdef DEBUG
    5.17 +   #ifdef SEQUENTIAL
    5.18     VMS__start_the_work_then_wait_until_done_Seq();  //debug sequential exe
    5.19     #else
    5.20     VMS__start_the_work_then_wait_until_done();      //normal multi-thd
    5.21 @@ -132,14 +132,19 @@
    5.22     return NUM_SCHED_SLOTS * NUM_CORES;
    5.23   }
    5.24  
    5.25 +int32
    5.26 +SSR__give_number_of_cores_to_schedule_onto()
    5.27 + {
    5.28 +   return NUM_CORES;
    5.29 + }
    5.30 +
    5.31  /*For now, use TSC -- later, make these two macros with assembly that first
    5.32   * saves jump point, and second jumps back several times to get reliable time
    5.33   */
    5.34  void inline
    5.35  SSR__start_primitive()
    5.36 - { int32 *saveAddr;
    5.37 -   saveAddr = &(((SSRSemEnv *)(_VMSMasterEnv->semanticEnv))->primitiveStartTime);
    5.38 -   saveLowTimeStampCountInto( (((SSRSemEnv *)(_VMSMasterEnv->semanticEnv))->primitiveStartTime) );
    5.39 + { saveLowTimeStampCountInto( ((SSRSemEnv *)(_VMSMasterEnv->semanticEnv))->
    5.40 +                              primitiveStartTime );
    5.41   }
    5.42  
    5.43  /*Just quick and dirty for now -- make reliable later
    5.44 @@ -152,7 +157,7 @@
    5.45   { int32 endTime, startTime;
    5.46     //TODO: fix by repeating time-measurement
    5.47     saveLowTimeStampCountInto( endTime );
    5.48 -   startTime = ((SSRSemEnv *)(_VMSMasterEnv->semanticEnv))->primitiveStartTime;
    5.49 +   startTime =((SSRSemEnv*)(_VMSMasterEnv->semanticEnv))->primitiveStartTime;
    5.50     return (endTime - startTime);
    5.51   }
    5.52  
    5.53 @@ -161,6 +166,7 @@
    5.54  /*Initializes all the data-structures for a SSR system -- but doesn't
    5.55   * start it running yet!
    5.56   *
    5.57 + *This runs in the main thread -- before VMS starts up
    5.58   * 
    5.59   *This sets up the semantic layer over the VMS system
    5.60   *
    5.61 @@ -172,6 +178,7 @@
    5.62   {
    5.63     VMS__init();
    5.64        //masterEnv, a global var, now is partially set up by init_VMS
    5.65 +      // after this, have VMS__malloc and VMS__free available
    5.66  
    5.67     SSR__init_Helper();
    5.68   }
    5.69 @@ -189,7 +196,7 @@
    5.70  SSR__init_Helper()
    5.71   { SSRSemEnv       *semanticEnv;
    5.72     PrivQueueStruc **readyVPQs;
    5.73 -   int              coreIdx;
    5.74 +   int              coreIdx, i;
    5.75   
    5.76        //Hook up the semantic layer's plug-ins to the Master virt procr
    5.77     _VMSMasterEnv->requestHandler = &SSR__Request_Handler;
    5.78 @@ -197,14 +204,14 @@
    5.79  
    5.80        //create the semantic layer's environment (all its data) and add to
    5.81        // the master environment
    5.82 -   semanticEnv = malloc( sizeof( SSRSemEnv ) );
    5.83 +   semanticEnv = VMS__malloc( sizeof( SSRSemEnv ) );
    5.84     _VMSMasterEnv->semanticEnv = semanticEnv;
    5.85  
    5.86        //create the ready queue, hash tables used for pairing send to receive
    5.87        // and so forth
    5.88        //TODO: add hash tables for pairing sends with receives, and
    5.89        // initialize the data ownership system
    5.90 -   readyVPQs = malloc( NUM_CORES * sizeof(PrivQueueStruc *) );
    5.91 +   readyVPQs = VMS__malloc( NUM_CORES * sizeof(PrivQueueStruc *) );
    5.92  
    5.93     for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
    5.94      {
    5.95 @@ -215,7 +222,19 @@
    5.96     
    5.97     semanticEnv->nextCoreToGetNewPr = 0;
    5.98     
    5.99 -   semanticEnv->commHashTbl     = makeHashTable( 1<<16, NULL ); //start big
   5.100 +   semanticEnv->commHashTbl  = makeHashTable( 1<<16, &VMS__free );//start big
   5.101 +
   5.102 +   //TODO: bug -- turn these arrays into dyn arrays to eliminate limit
   5.103 +   //semanticEnv->singletonHasBeenExecutedFlags = makeDynArrayInfo( );
   5.104 +   //semanticEnv->transactionStrucs = makeDynArrayInfo( );
   5.105 +   for( i = 0; i < NUM_STRUCS_IN_SEM_ENV; i++ )
   5.106 +    {
   5.107 +      semanticEnv->singletonHasBeenExecutedFlags[i] = FALSE;
   5.108 +      semanticEnv->transactionStrucs[i].waitingVPQ = makePrivQ();
   5.109 +    }
   5.110 +
   5.111 +
   5.112 +   
   5.113   }
   5.114  
   5.115  
   5.116 @@ -225,21 +244,22 @@
   5.117  SSR__cleanup_after_shutdown()
   5.118   { SSRSemEnv *semanticEnv;
   5.119     int coreIdx;
   5.120 - 
   5.121 +
   5.122 +/* It's all allocated inside VMS's big chunk -- that's about to be freed, so
   5.123 + *  nothing to do here
   5.124     semanticEnv = _VMSMasterEnv->semanticEnv;
   5.125  
   5.126 -//TODO: double check all sem env locations freed
   5.127 -
   5.128     for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
   5.129      {
   5.130 -      free( semanticEnv->readyVPQs[coreIdx]->startOfData );
   5.131 -      free( semanticEnv->readyVPQs[coreIdx] );
   5.132 +      VMS__free( semanticEnv->readyVPQs[coreIdx]->startOfData );
   5.133 +      VMS__free( semanticEnv->readyVPQs[coreIdx] );
   5.134      }
   5.135 -   free( semanticEnv->readyVPQs );
   5.136 +   VMS__free( semanticEnv->readyVPQs );
   5.137     
   5.138     freeHashTable( semanticEnv->commHashTbl );
   5.139 -   free( _VMSMasterEnv->semanticEnv );
   5.140 -   VMS__cleanup_after_shutdown();
   5.141 +   VMS__free( _VMSMasterEnv->semanticEnv );
   5.142 + */
   5.143 +   VMS__cleanup_at_end_of_shutdown();
   5.144   }
   5.145  
   5.146  
   5.147 @@ -248,38 +268,76 @@
   5.148  /*
   5.149   */
   5.150  inline VirtProcr *
   5.151 -SSR__create_procr_with( VirtProcrFnPtr fnPtr, void *initData,
   5.152 -                          VirtProcr *creatingPr )
   5.153 - { VirtProcr *newPr;
   5.154 +SSR__create_procr_with( VirtProcrFnPtr fnPtr,   void *initData,
   5.155 +                        VirtProcr *creatingPr )
   5.156 + { SSRSemReq reqData;
   5.157  
   5.158 -   newPr = VMS__create_procr( fnPtr, initData );
   5.159 +      //the semantic request data is on the stack and disappears when this
   5.160 +      // call returns -- it's guaranteed to remain in the VP's stack for as
   5.161 +      // long as the VP is suspended.
   5.162 +   reqData.reqType            = 0; //know type because in a VMS create req
   5.163 +   reqData.coreToScheduleOnto = -1; //means round-robin schedule
   5.164 +   reqData.fnPtr              = fnPtr;
   5.165 +   reqData.initData           = initData;
   5.166 +   reqData.sendPr             = creatingPr;
   5.167  
   5.168 -      //After create, have to send request to plugin for any sem env
   5.169 -      // modifications -- such as putting the new procr into the ready Q
   5.170 -      //Need a processor to "animate" the creation -- it's one the register
   5.171 -      // request is attached to, and one suspended in order to send req
   5.172 -      // to plugin
   5.173 -   VMS__send_req_to_register_new_procr( newPr, creatingPr );
   5.174 +   VMS__send_create_procr_req( &reqData, creatingPr );
   5.175  
   5.176 -   return newPr;
   5.177 +   return creatingPr->dataRetFromReq;
   5.178 + }
   5.179 +
   5.180 +inline VirtProcr *
   5.181 +SSR__create_procr_with_affinity( VirtProcrFnPtr fnPtr, void *initData,
   5.182 +                        VirtProcr *creatingPr,  int32  coreToScheduleOnto )
   5.183 + { SSRSemReq reqData;
   5.184 +
   5.185 +      //the semantic request data is on the stack and disappears when this
   5.186 +      // call returns -- it's guaranteed to remain in the VP's stack for as
   5.187 +      // long as the VP is suspended.
   5.188 +   reqData.reqType            = 0; //know type because in a VMS create req
   5.189 +   reqData.coreToScheduleOnto = coreToScheduleOnto;
   5.190 +   reqData.fnPtr              = fnPtr;
   5.191 +   reqData.initData           = initData;
   5.192 +   reqData.sendPr             = creatingPr;
   5.193 +
   5.194 +   VMS__send_create_procr_req( &reqData, creatingPr );
   5.195   }
   5.196  
   5.197  
   5.198  inline void
   5.199  SSR__dissipate_procr( VirtProcr *procrToDissipate )
   5.200   {
   5.201 -   VMS__dissipate_procr( procrToDissipate );
   5.202 +   VMS__send_dissipate_req( procrToDissipate );
   5.203   }
   5.204  
   5.205  
   5.206  //===========================================================================
   5.207  
   5.208  void *
   5.209 -SSR__malloc_size_to( int numBytes, VirtProcr *ownerPr )
   5.210 - {
   5.211 -//TODO: Put in the ownership system from DKU -- have it working, just adapt
   5.212 -//  it to here
   5.213 -   return malloc( numBytes );
   5.214 +SSR__malloc_to( int32 sizeToMalloc, VirtProcr *owningPr )
   5.215 + { SSRSemReq reqData;
   5.216 +
   5.217 +   reqData.reqType      = malloc_req;
   5.218 +   reqData.sendPr       = owningPr;
   5.219 +   reqData.sizeToMalloc = sizeToMalloc;
   5.220 +
   5.221 +   VMS__send_sem_request( &reqData, owningPr );
   5.222 +
   5.223 +   return owningPr->dataRetFromReq;
   5.224 + }
   5.225 +
   5.226 +
   5.227 +/*Sends request to Master, which does the work of freeing
   5.228 + */
   5.229 +void
   5.230 +SSR__free( void *ptrToFree, VirtProcr *owningPr )
   5.231 + { SSRSemReq reqData;
   5.232 +
   5.233 +   reqData.reqType      = free_req;
   5.234 +   reqData.sendPr       = owningPr;
   5.235 +   reqData.ptrToFree    = ptrToFree;
   5.236 +
   5.237 +   VMS__send_sem_request( &reqData, owningPr );
   5.238   }
   5.239  
   5.240  
   5.241 @@ -287,7 +345,9 @@
   5.242  SSR__transfer_ownership_of_from_to( void *data, VirtProcr *oldOwnerPr,
   5.243                                                    VirtProcr *newOwnerPr )
   5.244   {
   5.245 -
   5.246 +   //TODO: put in the ownership system that automatically frees when no
   5.247 +   // owners of data left -- will need keeper for keeping data around when
   5.248 +   // future created processors might need it but don't exist yet
   5.249   }
   5.250  
   5.251  
   5.252 @@ -333,22 +393,20 @@
   5.253  void
   5.254  SSR__send_of_type_to( VirtProcr *sendPr, void *msg, const int type,
   5.255                          VirtProcr *receivePr)
   5.256 - { SSRSemReq *reqData;
   5.257 + { SSRSemReq  reqData;
   5.258  
   5.259 -   reqData = malloc( sizeof(SSRSemReq) );
   5.260 -   reqData->receivePr = receivePr;
   5.261 -   reqData->sendPr    = sendPr;
   5.262 -   reqData->reqType   = send_type;
   5.263 -   reqData->msgType   = type;
   5.264 -   reqData->msg       = msg;
   5.265 -   reqData->nextReqInHashEntry = NULL;
   5.266 +   reqData.receivePr = receivePr;
   5.267 +   reqData.sendPr    = sendPr;
   5.268 +   reqData.reqType   = send_type;
   5.269 +   reqData.msgType   = type;
   5.270 +   reqData.msg       = msg;
   5.271 +   reqData.nextReqInHashEntry = NULL;
   5.272  
   5.273        //On ownership -- remove inside the send and let ownership sit in limbo
   5.274        // as a potential in an entry in the hash table, when this receive msg
   5.275        // gets paired to a send, the ownership gets added to the receivePr --
   5.276        // the next work-unit in the receivePr's trace will have ownership.
   5.277 -   VMS__add_sem_request( reqData, sendPr );
   5.278 -   VMS__suspend_procr( sendPr ); //will suspend then resume and continue
   5.279 +   VMS__send_sem_request( &reqData, sendPr );
   5.280  
   5.281        //When come back from suspend, no longer own data reachable from msg
   5.282        //TODO: release ownership here
   5.283 @@ -356,27 +414,18 @@
   5.284  
   5.285  void
   5.286  SSR__send_from_to( void *msg, VirtProcr *sendPr, VirtProcr *receivePr )
   5.287 - { SSRSemReq *reqData;
   5.288 + { SSRSemReq  reqData;
   5.289  
   5.290        //hash on the receiver, 'cause always know it, but sometimes want to
   5.291        // receive from anonymous sender
   5.292  
   5.293 -   reqData = malloc( sizeof(SSRSemReq) );
   5.294 -   reqData->receivePr = receivePr;
   5.295 -   reqData->sendPr    = sendPr;
   5.296 -   reqData->reqType   = send_from_to;
   5.297 -   reqData->msg       = msg;
   5.298 -   reqData->nextReqInHashEntry = NULL;
   5.299 +   reqData.receivePr = receivePr;
   5.300 +   reqData.sendPr    = sendPr;
   5.301 +   reqData.reqType   = send_from_to;
   5.302 +   reqData.msg       = msg;
   5.303 +   reqData.nextReqInHashEntry = NULL;
   5.304  
   5.305 -      //On ownership -- remove inside the send and let ownership sit in limbo
   5.306 -      // as a potential in an entry in the hash table, when this receive msg
   5.307 -      // gets paired to a send, the ownership gets added to the receivePr --
   5.308 -      // the next work-unit in the receivePr's trace will have ownership.
   5.309 -   VMS__add_sem_request( reqData, sendPr );
   5.310 -   VMS__suspend_procr( sendPr ); //will suspend then resume and continue
   5.311 -
   5.312 -      //When come back from suspend, no longer own data reachable from msg
   5.313 -      //TODO: release ownership here
   5.314 +   VMS__send_sem_request( &reqData, sendPr );
   5.315   }
   5.316  
   5.317  
   5.318 @@ -390,19 +439,17 @@
   5.319  
   5.320  void *
   5.321  SSR__receive_type_to( const int type, VirtProcr *receivePr )
   5.322 - { void *msg;
   5.323 -   SSRSemReq *reqData;
   5.324 + { 
   5.325 +   SSRSemReq  reqData;
   5.326  
   5.327 -   reqData = malloc( sizeof(SSRSemReq) );
   5.328 -   reqData->receivePr = receivePr;
   5.329 -   reqData->reqType   = receive_type;
   5.330 -   reqData->msgType   = type;
   5.331 -   reqData->nextReqInHashEntry = NULL;
   5.332 +   reqData.receivePr = receivePr;
   5.333 +   reqData.reqType   = receive_type;
   5.334 +   reqData.msgType   = type;
   5.335 +   reqData.nextReqInHashEntry = NULL;
   5.336  
   5.337 -   VMS__add_sem_request( reqData, receivePr );
   5.338 -   VMS__suspend_procr( receivePr );
   5.339 -   msg = receivePr->semanticData;
   5.340 -   return msg;
   5.341 +   VMS__send_sem_request( &reqData, receivePr );
   5.342 +   
   5.343 +   return receivePr->dataRetFromReq;
   5.344   }
   5.345  
   5.346  
   5.347 @@ -415,39 +462,110 @@
   5.348   */
   5.349  void *
   5.350  SSR__receive_from_to( VirtProcr *sendPr, VirtProcr *receivePr )
   5.351 - { SSRSemReq *reqData;
   5.352 + { SSRSemReq  reqData;
   5.353  
   5.354        //hash on the receiver, 'cause always know it, but sometimes want to
   5.355        // receive from anonymous sender
   5.356  
   5.357 -   reqData = malloc( sizeof(SSRSemReq) );
   5.358 -   reqData->receivePr = receivePr;
   5.359 -   reqData->sendPr    = sendPr;
   5.360 -   reqData->reqType   = receive_from_to;
   5.361 -   reqData->nextReqInHashEntry = NULL;
   5.362 +   reqData.receivePr = receivePr;
   5.363 +   reqData.sendPr    = sendPr;
   5.364 +   reqData.reqType   = receive_from_to;
   5.365 +   reqData.nextReqInHashEntry = NULL;
   5.366  
   5.367 -      //On ownership -- remove inside the send after receive successful.
   5.368 -      // Below, add ownership when come back from suspend
   5.369 -      //Reason: Thinking of impl ownership mech such that it automatically
   5.370 -      // frees any data has no owners -- so have to add receiver before
   5.371 -      // remove sender
   5.372 -   VMS__add_sem_request( reqData, receivePr );
   5.373 -      //TODO: add ownership of locs reachable from msg inside reqst handler
   5.374 -   VMS__suspend_procr( receivePr ); //will suspend then resume and continue
   5.375 +   VMS__send_sem_request( &reqData, receivePr );
   5.376  
   5.377 -      //When come back from suspend, the msg data is in receivePr->semData
   5.378 -   return receivePr->semanticData;
   5.379 +   return receivePr->dataRetFromReq;
   5.380   }
   5.381  
   5.382  
   5.383  //===========================================================================
   5.384  
   5.385 -/*Just thin wrapper for now -- semantic request is still a simple thing
   5.386 - * (July 3, 2010)
   5.387 +/*Uses ID as index into array of flags.  If flag already set, resumes from
   5.388 + * end-label.  Else, sets flag and resumes normally.
   5.389   */
   5.390 -inline void
   5.391 -SSR__free_semantic_request( SSRSemReq *semReq )
   5.392 +void
   5.393 +SSR__start_singleton( int32 singletonID, void *endSingletonLabelAddr,
   5.394 +                      VirtProcr *animPr )
   5.395   {
   5.396 -   free( semReq );
   5.397 +   SSRSemReq  reqData;
   5.398 +
   5.399 +      //
   5.400 +   reqData.reqType     = singleton;
   5.401 +   reqData.singletonID = singletonID;
   5.402 +   reqData.endJumpPt   = endSingletonLabelAddr;
   5.403 +
   5.404 +   VMS__send_sem_request( &reqData, animPr );
   5.405   }
   5.406  
   5.407 +/*This executes the function in the masterVP, so it executes in isolation
   5.408 + * from any other copies -- only one copy of the function can ever execute
   5.409 + * at a time.
   5.410 + *
   5.411 + *It suspends to the master, and the request handler takes the function
   5.412 + * pointer out of the request and calls it, then resumes the VP.
   5.413 + *Only very short functions should be called this way -- for longer-running
   5.414 + * isolation, use transaction-start and transaction-end, which run the code
   5.415 + * between as work-code.
   5.416 + */
   5.417 +void
   5.418 +SSR__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
   5.419 +                                    void *data, VirtProcr *animPr )
   5.420 + {
   5.421 +   SSRSemReq  reqData;
   5.422 +
   5.423 +      //
   5.424 +   reqData.reqType          = atomic;
   5.425 +   reqData.fnToExecInMaster = ptrToFnToExecInMaster;
   5.426 +   reqData.dataForFn        = data;
   5.427 +
   5.428 +   VMS__send_sem_request( &reqData, animPr );
   5.429 + }
   5.430 +
   5.431 +
   5.432 +/*This suspends to the master.
   5.433 + *First, it looks at the VP's data, to see the highest transactionID that VP
   5.434 + * already has entered.  If the current ID is not larger, it throws an
   5.435 + * exception stating a bug in the code.  Otherwise it puts the current ID
   5.436 + * there, and adds the ID to a linked list of IDs entered -- the list is
   5.437 + * used to check that exits are properly ordered.
   5.438 + *Next it is uses transactionID as index into an array of transaction
   5.439 + * structures.
   5.440 + *If the "VP_currently_executing" field is non-null, then put requesting VP
   5.441 + * into queue in the struct.  (At some point a holder will request
   5.442 + * end-transaction, which will take this VP from the queue and resume it.)
   5.443 + *If NULL, then write requesting into the field and resume.
   5.444 + */
   5.445 +void
   5.446 +SSR__start_transaction( int32 transactionID, VirtProcr *animPr )
   5.447 + {
   5.448 +   SSRSemReq  reqData;
   5.449 +
   5.450 +      //
   5.451 +   reqData.sendPr      = animPr;
   5.452 +   reqData.reqType     = trans_start;
   5.453 +   reqData.transID     = transactionID;
   5.454 +
   5.455 +   VMS__send_sem_request( &reqData, animPr );
   5.456 + }
   5.457 +
   5.458 +/*This suspends to the master, then uses transactionID as index into an
   5.459 + * array of transaction structures.
   5.460 + *It looks at VP_currently_executing to be sure it's same as requesting VP.
   5.461 + * If different, throws an exception, stating there's a bug in the code.
   5.462 + *Next it looks at the queue in the structure.
   5.463 + *If it's empty, it sets VP_currently_executing field to NULL and resumes.
   5.464 + *If something in, gets it, sets VP_currently_executing to that VP, then
   5.465 + * resumes both.
   5.466 + */
   5.467 +void
   5.468 +SSR__end_transaction( int32 transactionID, VirtProcr *animPr )
   5.469 + {
   5.470 +   SSRSemReq  reqData;
   5.471 +
   5.472 +      //
   5.473 +   reqData.sendPr      = animPr;
   5.474 +   reqData.reqType     = trans_end;
   5.475 +   reqData.transID     = transactionID;
   5.476 +
   5.477 +   VMS__send_sem_request( &reqData, animPr );
   5.478 + }
   5.479 \ No newline at end of file