Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > Vthread_impls > Vthread_MC_shared_impl
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 //===========================================================================
