changeset 2:e960a8d18f7c

Added singleton, atomic, transactions -- don't think it's working singletons yet
author Me
date Tue, 16 Nov 2010 16:04:29 +0100
parents 1d3157ac56c4
children 505d3c674ce8
files VPThread.h VPThread_Request_Handlers.c VPThread_Request_Handlers.h VPThread_lib.c
diffstat 4 files changed, 229 insertions(+), 31 deletions(-) [+]
line diff
     1.1 --- a/VPThread.h	Thu Nov 11 04:29:10 2010 -0800
     1.2 +++ b/VPThread.h	Tue Nov 16 16:04:29 2010 +0100
     1.3 @@ -45,7 +45,8 @@
     1.4     make_procr,
     1.5     malloc_req,
     1.6     free_req,
     1.7 -   singleton,
     1.8 +   singleton_start,
     1.9 +   singleton_end,
    1.10     atomic,
    1.11     trans_start,
    1.12     trans_end
    1.13 @@ -82,30 +83,14 @@
    1.14   }
    1.15  VPThdTrans;
    1.16  
    1.17 -
    1.18  typedef struct
    1.19   {
    1.20 -      //Standard stuff will be in most every semantic env
    1.21 -   PrivQueueStruc  **readyVPQs;
    1.22 -   int32             numVirtPr;
    1.23 -   int32             nextCoreToGetNewPr;
    1.24 -   int32             primitiveStartTime;
    1.25 -
    1.26 -      //Specific to this semantic layer
    1.27 -   VPThdMutex      **mutexDynArray;
    1.28 -   PrivDynArrayInfo *mutexDynArrayInfo;
    1.29 -
    1.30 -   VPThdCond       **condDynArray;
    1.31 -   PrivDynArrayInfo *condDynArrayInfo;
    1.32 -
    1.33 -   void             *applicationGlobals;
    1.34 -
    1.35 -                       //fix limit on num with dynArray
    1.36 -   int32             singletonHasBeenExecutedFlags[NUM_STRUCS_IN_SEM_ENV];
    1.37 -   VPThdTrans        transactionStrucs[NUM_STRUCS_IN_SEM_ENV];
    1.38 +   int32           hasBeenStarted;
    1.39 +   int32           hasFinished;
    1.40 +   void           *endInstrAddr;
    1.41 +   PrivQueueStruc *waitQ;
    1.42   }
    1.43 -VPThdSemEnv;
    1.44 -
    1.45 +VPThdSingleton;
    1.46  
    1.47  typedef struct
    1.48   {
    1.49 @@ -140,6 +125,32 @@
    1.50  VPThdSemData;
    1.51  
    1.52  
    1.53 +typedef struct
    1.54 + {
    1.55 +      //Standard stuff will be in most every semantic env
    1.56 +   PrivQueueStruc  **readyVPQs;
    1.57 +   int32             numVirtPr;
    1.58 +   int32             nextCoreToGetNewPr;
    1.59 +   int32             primitiveStartTime;
    1.60 +
    1.61 +      //Specific to this semantic layer
    1.62 +   VPThdMutex      **mutexDynArray;
    1.63 +   PrivDynArrayInfo *mutexDynArrayInfo;
    1.64 +
    1.65 +   VPThdCond       **condDynArray;
    1.66 +   PrivDynArrayInfo *condDynArrayInfo;
    1.67 +
    1.68 +   void             *applicationGlobals;
    1.69 +
    1.70 +                       //fix limit on num with dynArray
    1.71 +   VPThdSingleton    singletons[NUM_STRUCS_IN_SEM_ENV];
    1.72 +   void             *singletonEndInstrAddr;
    1.73 +
    1.74 +   VPThdTrans        transactionStrucs[NUM_STRUCS_IN_SEM_ENV];
    1.75 + }
    1.76 +VPThdSemEnv;
    1.77 +
    1.78 +
    1.79  //===========================================================================
    1.80  
    1.81  inline void
    1.82 @@ -187,6 +198,24 @@
    1.83  VPThread__cond_signal( int32 condIdx, VirtProcr *signallingPr );
    1.84  
    1.85  
    1.86 +//=======================
    1.87 +
    1.88 +void
    1.89 +VPThread__end_singleton( int32 singletonID, VirtProcr *animPr );
    1.90 +
    1.91 +inline void
    1.92 +VPThread__start_singleton( int32 singletonID, VirtProcr *animPr );
    1.93 +
    1.94 +void
    1.95 +VPThread__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
    1.96 +                                         void *data, VirtProcr *animPr );
    1.97 +
    1.98 +void
    1.99 +VPThread__start_transaction( int32 transactionID, VirtProcr *animPr );
   1.100 +
   1.101 +void
   1.102 +VPThread__end_transaction( int32 transactionID, VirtProcr *animPr );
   1.103 +
   1.104  
   1.105  
   1.106  //=========================  Internal use only  =============================
     2.1 --- a/VPThread_Request_Handlers.c	Thu Nov 11 04:29:10 2010 -0800
     2.2 +++ b/VPThread_Request_Handlers.c	Tue Nov 16 16:04:29 2010 +0100
     2.3 @@ -203,19 +203,54 @@
     2.4  //
     2.5  /*Uses ID as index into array of flags.  If flag already set, resumes from
     2.6   * end-label.  Else, sets flag and resumes normally.
     2.7 + *Note, because of one-master-at-a-time, if flag is set,
     2.8   */
     2.9  void inline
    2.10 -handleSingleton( VPThdSemReq *semReq, VirtProcr *requestingPr,
    2.11 -                 VPThdSemEnv *semEnv )
    2.12 +handleStartSingleton( VPThdSemReq *semReq, VirtProcr *reqstingPr,
    2.13 +                      VPThdSemEnv *semEnv )
    2.14   {
    2.15 -   if( semEnv->singletonHasBeenExecutedFlags[ semReq->singletonID ] )
    2.16 -      requestingPr->nextInstrPt = semReq->endJumpPt;
    2.17 +   if( semEnv->singletons[ semReq->singletonID ].hasFinished )
    2.18 +    {    //the code that sets the flag to true first sets the end instr addr
    2.19 +      reqstingPr->nextInstrPt = semEnv->singletonEndInstrAddr;
    2.20 +      resume_procr( reqstingPr, semEnv );
    2.21 +      return;
    2.22 +    }
    2.23 +   else if( semEnv->singletons[ semReq->singletonID ].hasBeenStarted )
    2.24 +    {    //singleton is in-progress in a diff slave, so wait for it to finish
    2.25 +      writePrivQ(reqstingPr, semEnv->singletons[semReq->singletonID].waitQ );
    2.26 +      return;
    2.27 +    }
    2.28     else
    2.29 -      semEnv->singletonHasBeenExecutedFlags[ semReq->singletonID ] = TRUE;
    2.30 -
    2.31 -   resume_procr( requestingPr, semEnv );
    2.32 +    {    //hasn't been started, so this is the first attempt at the singleton
    2.33 +      semEnv->singletons[ semReq->singletonID ].hasBeenStarted = TRUE;
    2.34 +      resume_procr( reqstingPr, semEnv );
    2.35 +      return;
    2.36 +    }
    2.37   }
    2.38  
    2.39 +void inline
    2.40 +handleEndSingleton( VPThdSemReq *semReq, VirtProcr *requestingPr,
    2.41 +                    VPThdSemEnv *semEnv )
    2.42 + {
    2.43 +   PrivQueueStruc waitQ;
    2.44 +   int32          numWaiting, i;
    2.45 +   
    2.46 +   if( semEnv->singletons[ semReq->singletonID ].hasFinished )
    2.47 +    { //by definition, only one slave should ever be able to run end singleton
    2.48 +      // so if this is true, is an error
    2.49 +      VMS__throw_exception( "singleton code ran twice");
    2.50 +    }
    2.51 +
    2.52 +   semEnv->singletons[ semReq->singletonID ].hasFinished = TRUE;
    2.53 +   waitQ = semEnv->singletons[ semReq->singletonID ].waitQ;
    2.54 +   numWaiting = numInPrivQ( waitQ );
    2.55 +   for( i = 0; i < numWaiting; i++ )
    2.56 +    {
    2.57 +      resume_procr( readPrivQ( waitQ ) );
    2.58 +    }
    2.59 +   
    2.60 +   resume_procr( requestingPr );
    2.61 +  }
    2.62  
    2.63  /*This executes the function in the masterVP, take the function
    2.64   * pointer out of the request and call it, then resume the VP.
     3.1 --- a/VPThread_Request_Handlers.h	Thu Nov 11 04:29:10 2010 -0800
     3.2 +++ b/VPThread_Request_Handlers.h	Tue Nov 16 16:04:29 2010 +0100
     3.3 @@ -26,6 +26,26 @@
     3.4  handleCondWait(   VPThdSemReq *semReq, VPThdSemEnv *semEnv);
     3.5  void
     3.6  handleCondSignal( VPThdSemReq *semReq, VPThdSemEnv *semEnv);
     3.7 +void inline
     3.8 +handleMalloc(VPThdSemReq *semReq, VirtProcr *requestingPr,VPThdSemEnv *semEnv);
     3.9 +void inline
    3.10 +handleFree( VPThdSemReq *semReq, VirtProcr *requestingPr, VPThdSemEnv *semEnv);
    3.11 +void inline
    3.12 +handleStartSingleton( VPThdSemReq *semReq, VirtProcr *reqstingPr,
    3.13 +                      VPThdSemEnv *semEnv );
    3.14 +void inline
    3.15 +handleEndSingleton( VPThdSemReq *semReq, VirtProcr *requestingPr,
    3.16 +                    VPThdSemEnv *semEnv );
    3.17 +void inline
    3.18 +handleAtomic( VPThdSemReq *semReq, VirtProcr *requestingPr,
    3.19 +              VPThdSemEnv *semEnv);
    3.20 +void inline
    3.21 +handleTransStart( VPThdSemReq *semReq, VirtProcr *requestingPr,
    3.22 +                  VPThdSemEnv *semEnv );
    3.23 +void inline
    3.24 +handleTransEnd( VPThdSemReq *semReq, VirtProcr *requestingPr,
    3.25 +                VPThdSemEnv *semEnv);
    3.26 +
    3.27  
    3.28  #endif	/* _VPThread_REQ_H */
    3.29  
     4.1 --- a/VPThread_lib.c	Thu Nov 11 04:29:10 2010 -0800
     4.2 +++ b/VPThread_lib.c	Tue Nov 16 16:04:29 2010 +0100
     4.3 @@ -209,9 +209,11 @@
     4.4     //semanticEnv->transactionStrucs = makeDynArrayInfo( );
     4.5     for( i = 0; i < NUM_STRUCS_IN_SEM_ENV; i++ )
     4.6      {
     4.7 -      semanticEnv->singletonHasBeenExecutedFlags[i] = FALSE;
     4.8 +      semanticEnv->singletons[i].hasBeenStarted    = FALSE;
     4.9 +      semanticEnv->singletons[i].hasFinished       = FALSE;
    4.10 +      semanticEnv->singletons[i].waitQ             = makePrivQ;
    4.11        semanticEnv->transactionStrucs[i].waitingVPQ = makePrivQ();
    4.12 -    }
    4.13 +    }   
    4.14   }
    4.15  
    4.16  
    4.17 @@ -436,4 +438,116 @@
    4.18  
    4.19     VMS__send_sem_request( &reqData, signallingPr );
    4.20   }
    4.21 +//============================================================================
    4.22 +
    4.23 +/*Uses ID as index into array of flags.  If flag already set, resumes from
    4.24 + * end-label.  Else, sets flag and resumes normally.
    4.25 + */
    4.26 +inline void
    4.27 +VPThread__start_singleton( int32 singletonID, VirtProcr *animPr )
    4.28 + {
    4.29 +   VPThdSemReq  reqData;
    4.30 +
    4.31 +   reqData.reqType     = singleton_start;
    4.32 +   reqData.singletonID = singletonID;
    4.33 +
    4.34 +   VMS__send_sem_request( &reqData, animPr );
    4.35 + }
    4.36 +
    4.37 +
    4.38 +/*Uses ID as index into array of flags.  If flag already set, resumes from
    4.39 + * end-label.  Else, sets flag and resumes normally.
    4.40 + *
    4.41 + *Note, this call cannot be inlined because the instr addr at the label
    4.42 + * inside is shared by all invocations of singleton.
    4.43 + */
    4.44 +void
    4.45 +VPThread__end_singleton( int32 singletonID, VirtProcr *animPr )
    4.46 + {
    4.47 +   VPThdSemReq  reqData;
    4.48 +
    4.49 +      //don't need this addr until after at least one singleton has reached
    4.50 +      // this function
    4.51 +   VPThdSemEnv *semEnv = VMS__give_sem_env_for( animPr );
    4.52 +   semEnv->singletons[ singletonID ].endInstrAddr = &&EndSingletonInstrAddr;
    4.53 +      
    4.54 +   reqData.reqType     = singleton_end;
    4.55 +   reqData.singletonID = singletonID;
    4.56 +
    4.57 +   VMS__send_sem_request( &reqData, animPr );
    4.58 +
    4.59 +EndSingletonInstrAddr:
    4.60 +   return;
    4.61 + }
    4.62 +
    4.63 +/*This executes the function in the masterVP, so it executes in isolation
    4.64 + * from any other copies -- only one copy of the function can ever execute
    4.65 + * at a time.
    4.66 + *
    4.67 + *It suspends to the master, and the request handler takes the function
    4.68 + * pointer out of the request and calls it, then resumes the VP.
    4.69 + *Only very short functions should be called this way -- for longer-running
    4.70 + * isolation, use transaction-start and transaction-end, which run the code
    4.71 + * between as work-code.
    4.72 + */
    4.73 +void
    4.74 +VPThread__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
    4.75 +                                    void *data, VirtProcr *animPr )
    4.76 + {
    4.77 +   VPThdSemReq  reqData;
    4.78 +
    4.79 +      //
    4.80 +   reqData.reqType          = atomic;
    4.81 +   reqData.fnToExecInMaster = ptrToFnToExecInMaster;
    4.82 +   reqData.dataForFn        = data;
    4.83 +
    4.84 +   VMS__send_sem_request( &reqData, animPr );
    4.85 + }
    4.86 +
    4.87 +
    4.88 +/*This suspends to the master.
    4.89 + *First, it looks at the VP's data, to see the highest transactionID that VP
    4.90 + * already has entered.  If the current ID is not larger, it throws an
    4.91 + * exception stating a bug in the code.  Otherwise it puts the current ID
    4.92 + * there, and adds the ID to a linked list of IDs entered -- the list is
    4.93 + * used to check that exits are properly ordered.
    4.94 + *Next it is uses transactionID as index into an array of transaction
    4.95 + * structures.
    4.96 + *If the "VP_currently_executing" field is non-null, then put requesting VP
    4.97 + * into queue in the struct.  (At some point a holder will request
    4.98 + * end-transaction, which will take this VP from the queue and resume it.)
    4.99 + *If NULL, then write requesting into the field and resume.
   4.100 + */
   4.101 +void
   4.102 +VPThread__start_transaction( int32 transactionID, VirtProcr *animPr )
   4.103 + {
   4.104 +   VPThdSemReq  reqData;
   4.105 +
   4.106 +      //
   4.107 +   reqData.reqType     = trans_start;
   4.108 +   reqData.transID     = transactionID;
   4.109 +
   4.110 +   VMS__send_sem_request( &reqData, animPr );
   4.111 + }
   4.112 +
   4.113 +/*This suspends to the master, then uses transactionID as index into an
   4.114 + * array of transaction structures.
   4.115 + *It looks at VP_currently_executing to be sure it's same as requesting VP.
   4.116 + * If different, throws an exception, stating there's a bug in the code.
   4.117 + *Next it looks at the queue in the structure.
   4.118 + *If it's empty, it sets VP_currently_executing field to NULL and resumes.
   4.119 + *If something in, gets it, sets VP_currently_executing to that VP, then
   4.120 + * resumes both.
   4.121 + */
   4.122 +void
   4.123 +VPThread__end_transaction( int32 transactionID, VirtProcr *animPr )
   4.124 + {
   4.125 +   VPThdSemReq  reqData;
   4.126 +
   4.127 +      //
   4.128 +   reqData.reqType     = trans_end;
   4.129 +   reqData.transID     = transactionID;
   4.130 +
   4.131 +   VMS__send_sem_request( &reqData, animPr );
   4.132 + }
   4.133  //===========================================================================