Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > Vthread_impls > Vthread_MC_shared_impl
changeset 3:505d3c674ce8
Nov 20 PLDI final version -- working data singletons, meas hist macros in plugin
| author | Me |
|---|---|
| date | Sat, 20 Nov 2010 08:39:58 +0100 |
| parents | e960a8d18f7c |
| children | cfd2f7e54129 |
| files | VPThread.h VPThread_PluginFns.c VPThread_Request_Handlers.c VPThread_Request_Handlers.h VPThread_lib.c |
| diffstat | 5 files changed, 303 insertions(+), 88 deletions(-) [+] |
line diff
1.1 --- a/VPThread.h Tue Nov 16 16:04:29 2010 +0100 1.2 +++ b/VPThread.h Sat Nov 20 08:39:58 2010 +0100 1.3 @@ -31,6 +31,17 @@ 1.4 //=========================================================================== 1.5 1.6 1.7 +/*WARNING: assembly hard-codes position of endInstrAddr as first field 1.8 + */ 1.9 +typedef struct 1.10 + { 1.11 + void *endInstrAddr; 1.12 + int32 hasBeenStarted; 1.13 + int32 hasFinished; 1.14 + PrivQueueStruc *waitQ; 1.15 + } 1.16 +VPThdSingleton; 1.17 + 1.18 /*Semantic layer-specific data sent inside a request from lib called in app 1.19 * to request handler called in MasterLoop 1.20 */ 1.21 @@ -45,8 +56,10 @@ 1.22 make_procr, 1.23 malloc_req, 1.24 free_req, 1.25 - singleton_start, 1.26 - singleton_end, 1.27 + singleton_fn_start, 1.28 + singleton_fn_end, 1.29 + singleton_data_start, 1.30 + singleton_data_end, 1.31 atomic, 1.32 trans_start, 1.33 trans_end 1.34 @@ -66,7 +79,7 @@ 1.35 void *ptrToFree; 1.36 1.37 int32 singletonID; 1.38 - void *endJumpPt; 1.39 + VPThdSingleton **singletonPtrAddr; 1.40 1.41 PtrToAtomicFn fnToExecInMaster; 1.42 void *dataForFn; 1.43 @@ -83,14 +96,6 @@ 1.44 } 1.45 VPThdTrans; 1.46 1.47 -typedef struct 1.48 - { 1.49 - int32 hasBeenStarted; 1.50 - int32 hasFinished; 1.51 - void *endInstrAddr; 1.52 - PrivQueueStruc *waitQ; 1.53 - } 1.54 -VPThdSingleton; 1.55 1.56 typedef struct 1.57 { 1.58 @@ -143,8 +148,7 @@ 1.59 void *applicationGlobals; 1.60 1.61 //fix limit on num with dynArray 1.62 - VPThdSingleton singletons[NUM_STRUCS_IN_SEM_ENV]; 1.63 - void *singletonEndInstrAddr; 1.64 + VPThdSingleton fnSingletons[NUM_STRUCS_IN_SEM_ENV]; 1.65 1.66 VPThdTrans transactionStrucs[NUM_STRUCS_IN_SEM_ENV]; 1.67 } 1.68 @@ -199,12 +203,17 @@ 1.69 1.70 1.71 //======================= 1.72 +void 1.73 +VPThread__start_fn_singleton( int32 singletonID, VirtProcr *animPr ); 1.74 1.75 void 1.76 -VPThread__end_singleton( int32 singletonID, VirtProcr *animPr ); 1.77 +VPThread__end_fn_singleton( int32 singletonID, VirtProcr *animPr ); 1.78 1.79 -inline void 1.80 -VPThread__start_singleton( int32 singletonID, VirtProcr *animPr ); 1.81 +void 1.82 +VPThread__start_data_singleton( VPThdSingleton **singeltonAddr, VirtProcr *animPr ); 1.83 + 1.84 +void 1.85 +VPThread__end_data_singleton( VPThdSingleton **singletonAddr, VirtProcr *animPr ); 1.86 1.87 void 1.88 VPThread__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster, 1.89 @@ -237,5 +246,8 @@ 1.90 void 1.91 VPThread__cleanup_after_shutdown(); 1.92 1.93 +void inline 1.94 +resume_procr( VirtProcr *procr, VPThdSemEnv *semEnv ); 1.95 + 1.96 #endif /* _VPThread_H */ 1.97
2.1 --- a/VPThread_PluginFns.c Tue Nov 16 16:04:29 2010 +0100 2.2 +++ b/VPThread_PluginFns.c Sat Nov 20 08:39:58 2010 +0100 2.3 @@ -13,16 +13,14 @@ 2.4 #include "VPThread_Request_Handlers.h" 2.5 2.6 //=========================== Local Fn Prototypes =========================== 2.7 -void inline 2.8 -resume_procr( VirtProcr *procr, VPThdSemEnv *semEnv ); 2.9 2.10 void inline 2.11 handleSemReq( VMSReqst *req, VirtProcr *requestingPr, VPThdSemEnv *semEnv ); 2.12 2.13 -void 2.14 +inline void 2.15 handleDissipate( VirtProcr *requestingPr, VPThdSemEnv *semEnv ); 2.16 2.17 -void 2.18 +inline void 2.19 handleCreate( VMSReqst *req, VirtProcr *requestingPr, VPThdSemEnv *semEnv ); 2.20 2.21 2.22 @@ -111,12 +109,30 @@ 2.23 break; 2.24 case cond_signal: handleCondSignal( semReq, semEnv); 2.25 break; 2.26 + case malloc_req: handleMalloc( semReq, reqPr, semEnv); 2.27 + break; 2.28 + case free_req: handleFree( semReq, reqPr, semEnv); 2.29 + break; 2.30 + case singleton_fn_start: handleStartFnSingleton(semReq, reqPr, semEnv); 2.31 + break; 2.32 + case singleton_fn_end: handleEndFnSingleton( semReq, reqPr, semEnv); 2.33 + break; 2.34 + case singleton_data_start:handleStartDataSingleton(semReq,reqPr,semEnv); 2.35 + break; 2.36 + case singleton_data_end: handleEndDataSingleton(semReq, reqPr, semEnv); 2.37 + break; 2.38 + case atomic: handleAtomic( semReq, reqPr, semEnv); 2.39 + break; 2.40 + case trans_start: handleTransStart( semReq, reqPr, semEnv); 2.41 + break; 2.42 + case trans_end: handleTransEnd( semReq, reqPr, semEnv); 2.43 + break; 2.44 } 2.45 } 2.46 2.47 //=========================== VMS Request Handlers =========================== 2.48 // 2.49 -void 2.50 +inline void 2.51 handleDissipate( VirtProcr *requestingPr, VPThdSemEnv *semEnv ) 2.52 { 2.53 //free any semantic data allocated to the virt procr 2.54 @@ -137,8 +153,8 @@ 2.55 inline VirtProcr * 2.56 VPThread__create_procr_helper( VirtProcrFnPtr fnPtr, void *initData, 2.57 VPThdSemEnv *semEnv, int32 coreToScheduleOnto ) 2.58 - { VirtProcr *newPr; 2.59 - VPThdSemData semData; 2.60 + { VirtProcr *newPr; 2.61 + VPThdSemData *semData; 2.62 2.63 //This is running in master, so use internal version 2.64 newPr = VMS__create_procr( fnPtr, initData ); 2.65 @@ -175,11 +191,13 @@ 2.66 return newPr; 2.67 } 2.68 2.69 -void 2.70 +inline void 2.71 handleCreate( VMSReqst *req, VirtProcr *requestingPr, VPThdSemEnv *semEnv ) 2.72 { VPThdSemReq *semReq; 2.73 VirtProcr *newPr; 2.74 2.75 + Meas_startCreate 2.76 + 2.77 semReq = VMS__take_sem_reqst_from( req ); 2.78 2.79 newPr = VPThread__create_procr_helper( semReq->fnPtr, semReq->initData, 2.80 @@ -190,6 +208,16 @@ 2.81 2.82 resume_procr( newPr, semEnv ); 2.83 resume_procr( requestingPr, semEnv ); 2.84 + 2.85 + //========================= MEASUREMENT STUFF ====================== 2.86 + Meas_endCreate 2.87 + #ifdef MEAS__TIME_PLUGIN 2.88 + #ifdef MEAS__SUB_CREATE 2.89 + subIntervalFromHist( startStamp, endStamp, 2.90 + _VMSMasterEnv->reqHdlrHighTimeHist ); 2.91 + #endif 2.92 + #endif 2.93 + //================================================================== 2.94 } 2.95 2.96
3.1 --- a/VPThread_Request_Handlers.c Tue Nov 16 16:04:29 2010 +0100 3.2 +++ b/VPThread_Request_Handlers.c Sat Nov 20 08:39:58 2010 +0100 3.3 @@ -24,8 +24,8 @@ 3.4 VirtProcr *requestingPr; 3.5 3.6 requestingPr = semReq->requestingPr; 3.7 - newMutex = VMS__malloc( sizeof(VPThdMutex), requestingPr ); 3.8 - newMutex->waitingQueue = makePrivQ( requestingPr ); 3.9 + newMutex = VMS__malloc( sizeof(VPThdMutex) ); 3.10 + newMutex->waitingQueue = makeVMSPrivQ( requestingPr ); 3.11 newMutex->holderOfLock = NULL; 3.12 3.13 //The mutex struc contains an int that identifies it -- use that as 3.14 @@ -36,7 +36,7 @@ 3.15 semReq->requestingPr->dataRetFromReq = newMutex->mutexIdx; 3.16 3.17 //re-animate the requester 3.18 - resume_procr( requestingPr ); 3.19 + resume_procr( requestingPr, semEnv ); 3.20 } 3.21 3.22 3.23 @@ -49,6 +49,7 @@ 3.24 3.25 #endif 3.26 //================================================================= 3.27 + Meas_startMutexLock 3.28 //lookup mutex struc, using mutexIdx as index 3.29 mutex = semEnv->mutexDynArray[ semReq->mutexIdx ]; 3.30 3.31 @@ -58,12 +59,13 @@ 3.32 mutex->holderOfLock = semReq->requestingPr; 3.33 3.34 //re-animate requester, now that it has the lock 3.35 - resume_procr( semReq->requestingPr ); 3.36 + resume_procr( semReq->requestingPr, semEnv ); 3.37 } 3.38 else //queue up requester to wait for release of lock 3.39 { 3.40 writePrivQ( semReq->requestingPr, mutex->waitingQueue ); 3.41 } 3.42 + Meas_endMutexLock 3.43 } 3.44 3.45 /* 3.46 @@ -72,6 +74,7 @@ 3.47 handleMutexUnlock( VPThdSemReq *semReq, VPThdSemEnv *semEnv) 3.48 { VPThdMutex *mutex; 3.49 3.50 + Meas_startMutexUnlock 3.51 //lookup mutex struc, using mutexIdx as index 3.52 mutex = semEnv->mutexDynArray[ semReq->mutexIdx ]; 3.53 3.54 @@ -81,11 +84,12 @@ 3.55 //if have new non-NULL holder, re-animate it 3.56 if( mutex->holderOfLock != NULL ) 3.57 { 3.58 - resume_procr( mutex->holderOfLock ); 3.59 + resume_procr( mutex->holderOfLock, semEnv ); 3.60 } 3.61 3.62 //re-animate the releaser of the lock 3.63 - resume_procr( semReq->requestingPr ); 3.64 + resume_procr( semReq->requestingPr, semEnv ); 3.65 + Meas_endMutexUnlock 3.66 } 3.67 3.68 //=========================== Condition Vars ============================== 3.69 @@ -106,10 +110,10 @@ 3.70 VirtProcr *requestingPr; 3.71 3.72 requestingPr = semReq->requestingPr; 3.73 - newCond = VMS__malloc( sizeof(VPThdCond), requestingPr ); 3.74 + newCond = VMS__malloc( sizeof(VPThdCond) ); 3.75 newCond->partnerMutex = semEnv->mutexDynArray[ semReq->mutexIdx ]; 3.76 3.77 - newCond->waitingQueue = makePrivQ(); 3.78 + newCond->waitingQueue = makeVMSPrivQ(); 3.79 3.80 //The cond struc contains an int that identifies it -- use that as 3.81 // its index within the array of conds. Add the new cond to array. 3.82 @@ -119,7 +123,7 @@ 3.83 semReq->requestingPr->dataRetFromReq = newCond->condIdx; 3.84 3.85 //re-animate the requester 3.86 - resume_procr( requestingPr ); 3.87 + resume_procr( requestingPr, semEnv ); 3.88 } 3.89 3.90 3.91 @@ -131,8 +135,8 @@ 3.92 handleCondWait( VPThdSemReq *semReq, VPThdSemEnv *semEnv) 3.93 { VPThdCond *cond; 3.94 VPThdMutex *mutex; 3.95 - VirtProcr *pr; 3.96 3.97 + Meas_startCondWait 3.98 //get cond struc out of array of them that's in the sem env 3.99 cond = semEnv->condDynArray[ semReq->condIdx ]; 3.100 3.101 @@ -145,8 +149,9 @@ 3.102 3.103 if( mutex->holderOfLock != NULL ) 3.104 { 3.105 - resume_procr( mutex->holderOfLock ); 3.106 + resume_procr( mutex->holderOfLock, semEnv ); 3.107 } 3.108 + Meas_endCondWait 3.109 } 3.110 3.111 3.112 @@ -159,6 +164,7 @@ 3.113 VPThdMutex *mutex; 3.114 VirtProcr *waitingPr, *pr; 3.115 3.116 + Meas_startCondSignal 3.117 //get cond struc out of array of them that's in the sem env 3.118 cond = semEnv->condDynArray[ semReq->condIdx ]; 3.119 3.120 @@ -171,7 +177,8 @@ 3.121 pushPrivQ( waitingPr, mutex->waitingQueue ); //is first out when read 3.122 3.123 //re-animate the signalling procr 3.124 - resume_procr( semReq->requestingPr ); 3.125 + resume_procr( semReq->requestingPr, semEnv ); 3.126 + Meas_endCondSignal 3.127 } 3.128 3.129 3.130 @@ -184,73 +191,147 @@ 3.131 handleMalloc(VPThdSemReq *semReq, VirtProcr *requestingPr,VPThdSemEnv *semEnv) 3.132 { void *ptr; 3.133 3.134 + //========================= MEASUREMENT STUFF ====================== 3.135 + #ifdef MEAS__TIME_PLUGIN 3.136 + int32 startStamp, endStamp; 3.137 + saveLowTimeStampCountInto( startStamp ); 3.138 + #endif 3.139 + //================================================================== 3.140 ptr = VMS__malloc( semReq->sizeToMalloc ); 3.141 requestingPr->dataRetFromReq = ptr; 3.142 resume_procr( requestingPr, semEnv ); 3.143 - } 3.144 + //========================= MEASUREMENT STUFF ====================== 3.145 + #ifdef MEAS__TIME_PLUGIN 3.146 + saveLowTimeStampCountInto( endStamp ); 3.147 + subIntervalFromHist( startStamp, endStamp, 3.148 + _VMSMasterEnv->reqHdlrHighTimeHist ); 3.149 + #endif 3.150 + //================================================================== 3.151 + } 3.152 3.153 /* 3.154 */ 3.155 void inline 3.156 handleFree( VPThdSemReq *semReq, VirtProcr *requestingPr, VPThdSemEnv *semEnv) 3.157 { 3.158 + //========================= MEASUREMENT STUFF ====================== 3.159 + #ifdef MEAS__TIME_PLUGIN 3.160 + int32 startStamp, endStamp; 3.161 + saveLowTimeStampCountInto( startStamp ); 3.162 + #endif 3.163 + //================================================================== 3.164 VMS__free( semReq->ptrToFree ); 3.165 resume_procr( requestingPr, semEnv ); 3.166 + //========================= MEASUREMENT STUFF ====================== 3.167 + #ifdef MEAS__TIME_PLUGIN 3.168 + saveLowTimeStampCountInto( endStamp ); 3.169 + subIntervalFromHist( startStamp, endStamp, 3.170 + _VMSMasterEnv->reqHdlrHighTimeHist ); 3.171 + #endif 3.172 + //================================================================== 3.173 } 3.174 3.175 3.176 -//============================================================================ 3.177 +//=========================================================================== 3.178 // 3.179 /*Uses ID as index into array of flags. If flag already set, resumes from 3.180 * end-label. Else, sets flag and resumes normally. 3.181 - *Note, because of one-master-at-a-time, if flag is set, 3.182 */ 3.183 void inline 3.184 -handleStartSingleton( VPThdSemReq *semReq, VirtProcr *reqstingPr, 3.185 - VPThdSemEnv *semEnv ) 3.186 +handleStartSingleton_helper( VPThdSingleton *singleton, VirtProcr *reqstingPr, 3.187 + VPThdSemEnv *semEnv ) 3.188 { 3.189 - if( semEnv->singletons[ semReq->singletonID ].hasFinished ) 3.190 + if( singleton->hasFinished ) 3.191 { //the code that sets the flag to true first sets the end instr addr 3.192 - reqstingPr->nextInstrPt = semEnv->singletonEndInstrAddr; 3.193 + reqstingPr->dataRetFromReq = singleton->endInstrAddr; 3.194 resume_procr( reqstingPr, semEnv ); 3.195 return; 3.196 } 3.197 - else if( semEnv->singletons[ semReq->singletonID ].hasBeenStarted ) 3.198 + else if( singleton->hasBeenStarted ) 3.199 { //singleton is in-progress in a diff slave, so wait for it to finish 3.200 - writePrivQ(reqstingPr, semEnv->singletons[semReq->singletonID].waitQ ); 3.201 + writePrivQ(reqstingPr, singleton->waitQ ); 3.202 return; 3.203 } 3.204 else 3.205 { //hasn't been started, so this is the first attempt at the singleton 3.206 - semEnv->singletons[ semReq->singletonID ].hasBeenStarted = TRUE; 3.207 + singleton->hasBeenStarted = TRUE; 3.208 + reqstingPr->dataRetFromReq = 0x0; 3.209 resume_procr( reqstingPr, semEnv ); 3.210 return; 3.211 } 3.212 } 3.213 +void inline 3.214 +handleStartFnSingleton( VPThdSemReq *semReq, VirtProcr *requestingPr, 3.215 + VPThdSemEnv *semEnv ) 3.216 + { VPThdSingleton *singleton; 3.217 + 3.218 + singleton = &(semEnv->fnSingletons[ semReq->singletonID ]); 3.219 + handleStartSingleton_helper( singleton, requestingPr, semEnv ); 3.220 + } 3.221 +void inline 3.222 +handleStartDataSingleton( VPThdSemReq *semReq, VirtProcr *requestingPr, 3.223 + VPThdSemEnv *semEnv ) 3.224 + { VPThdSingleton *singleton; 3.225 + 3.226 + if( *(semReq->singletonPtrAddr) == NULL ) 3.227 + { singleton = VMS__malloc( sizeof(VPThdSingleton) ); 3.228 + singleton->waitQ = makeVMSPrivQ(); 3.229 + singleton->endInstrAddr = 0x0; 3.230 + singleton->hasBeenStarted = FALSE; 3.231 + singleton->hasFinished = FALSE; 3.232 + *(semReq->singletonPtrAddr) = singleton; 3.233 + } 3.234 + else 3.235 + singleton = *(semReq->singletonPtrAddr); 3.236 + handleStartSingleton_helper( singleton, requestingPr, semEnv ); 3.237 + } 3.238 + 3.239 3.240 void inline 3.241 -handleEndSingleton( VPThdSemReq *semReq, VirtProcr *requestingPr, 3.242 - VPThdSemEnv *semEnv ) 3.243 - { 3.244 - PrivQueueStruc waitQ; 3.245 - int32 numWaiting, i; 3.246 - 3.247 - if( semEnv->singletons[ semReq->singletonID ].hasFinished ) 3.248 +handleEndSingleton_helper( VPThdSingleton *singleton, VirtProcr *requestingPr, 3.249 + VPThdSemEnv *semEnv ) 3.250 + { PrivQueueStruc *waitQ; 3.251 + int32 numWaiting, i; 3.252 + VirtProcr *resumingPr; 3.253 + 3.254 + if( singleton->hasFinished ) 3.255 { //by definition, only one slave should ever be able to run end singleton 3.256 // so if this is true, is an error 3.257 - VMS__throw_exception( "singleton code ran twice"); 3.258 + //VMS__throw_exception( "singleton code ran twice", requestingPr, NULL); 3.259 } 3.260 3.261 - semEnv->singletons[ semReq->singletonID ].hasFinished = TRUE; 3.262 - waitQ = semEnv->singletons[ semReq->singletonID ].waitQ; 3.263 + singleton->hasFinished = TRUE; 3.264 + waitQ = singleton->waitQ; 3.265 numWaiting = numInPrivQ( waitQ ); 3.266 for( i = 0; i < numWaiting; i++ ) 3.267 - { 3.268 - resume_procr( readPrivQ( waitQ ) ); 3.269 + { //they will resume inside start singleton, then jmp to end singleton 3.270 + resumingPr = readPrivQ( waitQ ); 3.271 + resumingPr->dataRetFromReq = singleton->endInstrAddr; 3.272 + resume_procr( resumingPr, semEnv ); 3.273 } 3.274 - 3.275 - resume_procr( requestingPr ); 3.276 - } 3.277 + 3.278 + resume_procr( requestingPr, semEnv ); 3.279 + 3.280 + } 3.281 +void inline 3.282 +handleEndFnSingleton( VPThdSemReq *semReq, VirtProcr *requestingPr, 3.283 + VPThdSemEnv *semEnv ) 3.284 + { 3.285 + VPThdSingleton *singleton; 3.286 + 3.287 + singleton = &(semEnv->fnSingletons[ semReq->singletonID ]); 3.288 + handleEndSingleton_helper( singleton, requestingPr, semEnv ); 3.289 + } 3.290 +void inline 3.291 +handleEndDataSingleton( VPThdSemReq *semReq, VirtProcr *requestingPr, 3.292 + VPThdSemEnv *semEnv ) 3.293 + { 3.294 + VPThdSingleton *singleton; 3.295 + 3.296 + singleton = *(semReq->singletonPtrAddr); 3.297 + handleEndSingleton_helper( singleton, requestingPr, semEnv ); 3.298 + } 3.299 + 3.300 3.301 /*This executes the function in the masterVP, take the function 3.302 * pointer out of the request and call it, then resume the VP.
4.1 --- a/VPThread_Request_Handlers.h Tue Nov 16 16:04:29 2010 +0100 4.2 +++ b/VPThread_Request_Handlers.h Sat Nov 20 08:39:58 2010 +0100 4.3 @@ -14,27 +14,33 @@ 4.4 /*This header defines everything specific to the VPThread semantic plug-in 4.5 */ 4.6 4.7 -void 4.8 +inline void 4.9 handleMakeMutex( VPThdSemReq *semReq, VPThdSemEnv *semEnv); 4.10 -void 4.11 +inline void 4.12 handleMutexLock( VPThdSemReq *semReq, VPThdSemEnv *semEnv); 4.13 -void 4.14 +inline void 4.15 handleMutexUnlock(VPThdSemReq *semReq, VPThdSemEnv *semEnv); 4.16 -void 4.17 +inline void 4.18 handleMakeCond( VPThdSemReq *semReq, VPThdSemEnv *semEnv); 4.19 -void 4.20 +inline void 4.21 handleCondWait( VPThdSemReq *semReq, VPThdSemEnv *semEnv); 4.22 -void 4.23 +inline void 4.24 handleCondSignal( VPThdSemReq *semReq, VPThdSemEnv *semEnv); 4.25 void inline 4.26 handleMalloc(VPThdSemReq *semReq, VirtProcr *requestingPr,VPThdSemEnv *semEnv); 4.27 void inline 4.28 handleFree( VPThdSemReq *semReq, VirtProcr *requestingPr, VPThdSemEnv *semEnv); 4.29 -void inline 4.30 -handleStartSingleton( VPThdSemReq *semReq, VirtProcr *reqstingPr, 4.31 +inline void 4.32 +handleStartFnSingleton( VPThdSemReq *semReq, VirtProcr *reqstingPr, 4.33 VPThdSemEnv *semEnv ); 4.34 -void inline 4.35 -handleEndSingleton( VPThdSemReq *semReq, VirtProcr *requestingPr, 4.36 +inline void 4.37 +handleEndFnSingleton( VPThdSemReq *semReq, VirtProcr *requestingPr, 4.38 + VPThdSemEnv *semEnv ); 4.39 +inline void 4.40 +handleStartDataSingleton( VPThdSemReq *semReq, VirtProcr *reqstingPr, 4.41 + VPThdSemEnv *semEnv ); 4.42 +inline void 4.43 +handleEndDataSingleton( VPThdSemReq *semReq, VirtProcr *requestingPr, 4.44 VPThdSemEnv *semEnv ); 4.45 void inline 4.46 handleAtomic( VPThdSemReq *semReq, VirtProcr *requestingPr,
5.1 --- a/VPThread_lib.c Tue Nov 16 16:04:29 2010 +0100 5.2 +++ b/VPThread_lib.c Sat Nov 20 08:39:58 2010 +0100 5.3 @@ -123,7 +123,7 @@ 5.4 */ 5.5 inline void 5.6 VPThread__start_primitive() 5.7 - { saveLowTimeStampCountInto( ((VPThreadSemEnv *)(_VMSMasterEnv->semanticEnv))-> 5.8 + { saveLowTimeStampCountInto( ((VPThdSemEnv *)(_VMSMasterEnv->semanticEnv))-> 5.9 primitiveStartTime ); 5.10 } 5.11 5.12 @@ -190,7 +190,7 @@ 5.13 5.14 for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 5.15 { 5.16 - readyVPQs[ coreIdx ] = makePrivQ(); 5.17 + readyVPQs[ coreIdx ] = makeVMSPrivQ(); 5.18 } 5.19 5.20 semanticEnv->readyVPQs = readyVPQs; 5.21 @@ -209,10 +209,11 @@ 5.22 //semanticEnv->transactionStrucs = makeDynArrayInfo( ); 5.23 for( i = 0; i < NUM_STRUCS_IN_SEM_ENV; i++ ) 5.24 { 5.25 - semanticEnv->singletons[i].hasBeenStarted = FALSE; 5.26 - semanticEnv->singletons[i].hasFinished = FALSE; 5.27 - semanticEnv->singletons[i].waitQ = makePrivQ; 5.28 - semanticEnv->transactionStrucs[i].waitingVPQ = makePrivQ(); 5.29 + semanticEnv->fnSingletons[i].endInstrAddr = NULL; 5.30 + semanticEnv->fnSingletons[i].hasBeenStarted = FALSE; 5.31 + semanticEnv->fnSingletons[i].hasFinished = FALSE; 5.32 + semanticEnv->fnSingletons[i].waitQ = makeVMSPrivQ(); 5.33 + semanticEnv->transactionStrucs[i].waitingVPQ = makeVMSPrivQ(); 5.34 } 5.35 } 5.36 5.37 @@ -438,40 +439,95 @@ 5.38 5.39 VMS__send_sem_request( &reqData, signallingPr ); 5.40 } 5.41 -//============================================================================ 5.42 5.43 -/*Uses ID as index into array of flags. If flag already set, resumes from 5.44 - * end-label. Else, sets flag and resumes normally. 5.45 + 5.46 +//=========================================================================== 5.47 +// 5.48 +/*A function singleton is a function whose body executes exactly once, on a 5.49 + * single core, no matter how many times the fuction is called and no 5.50 + * matter how many cores or the timing of cores calling it. 5.51 + * 5.52 + *A data singleton is a ticket attached to data. That ticket can be used 5.53 + * to get the data through the function exactly once, no matter how many 5.54 + * times the data is given to the function, and no matter the timing of 5.55 + * trying to get the data through from different cores. 5.56 */ 5.57 -inline void 5.58 -VPThread__start_singleton( int32 singletonID, VirtProcr *animPr ) 5.59 + 5.60 +/*Fn singleton uses ID as index into array of singleton structs held in the 5.61 + * semantic environment. 5.62 + */ 5.63 +void 5.64 +VPThread__start_fn_singleton( int32 singletonID, VirtProcr *animPr ) 5.65 { 5.66 VPThdSemReq reqData; 5.67 5.68 - reqData.reqType = singleton_start; 5.69 + // 5.70 + reqData.reqType = singleton_fn_start; 5.71 reqData.singletonID = singletonID; 5.72 5.73 VMS__send_sem_request( &reqData, animPr ); 5.74 + if( animPr->dataRetFromReq ) //will be 0 or addr of label in end singleton 5.75 + { 5.76 + asm volatile("movl %0, %%eax; \ 5.77 + jmp *%%eax" \ 5.78 + /* outputs */ : \ 5.79 + /* inputs */ : "g"(animPr->dataRetFromReq) \ 5.80 + /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx","%edi","%esi"\ 5.81 + ); 5.82 + } 5.83 } 5.84 5.85 +/*Data singleton hands addr of loc holding a pointer to a singleton struct. 5.86 + * The start_data_singleton makes the structure and puts its addr into the 5.87 + * location. 5.88 + */ 5.89 +void 5.90 +VPThread__start_data_singleton( VPThdSingleton **singletonAddr, VirtProcr *animPr ) 5.91 + { 5.92 + VPThdSemReq reqData; 5.93 + 5.94 + if( *singletonAddr && (*singletonAddr)->hasFinished ) 5.95 + goto JmpToEndSingleton; 5.96 + // 5.97 + reqData.reqType = singleton_data_start; 5.98 + reqData.singletonPtrAddr = singletonAddr; 5.99 + 5.100 + VMS__send_sem_request( &reqData, animPr ); 5.101 + if( animPr->dataRetFromReq ) //either 0 or end singleton's return addr 5.102 + { //Assembly code changes the return addr on the stack to the one 5.103 + // saved into the singleton by the end-singleton-fn 5.104 + //The stack's return addr is at 0x4(%%ebp) 5.105 + JmpToEndSingleton: 5.106 + asm volatile("movl %0, %%eax; \ 5.107 + movl (%%eax), %%ebx; \ 5.108 + movl (%%ebx), %%eax; \ 5.109 + movl %%eax, 0x4(%%ebp);" \ 5.110 + /* outputs */ : \ 5.111 + /* inputs */ : "m"(singletonAddr) \ 5.112 + /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx","%edi","%esi"\ 5.113 + ); 5.114 + } 5.115 + //now, simply return 5.116 + //will exit either from the start singleton call or the end-singleton call 5.117 + } 5.118 5.119 /*Uses ID as index into array of flags. If flag already set, resumes from 5.120 * end-label. Else, sets flag and resumes normally. 5.121 * 5.122 *Note, this call cannot be inlined because the instr addr at the label 5.123 - * inside is shared by all invocations of singleton. 5.124 + * inside is shared by all invocations of a given singleton ID. 5.125 */ 5.126 void 5.127 -VPThread__end_singleton( int32 singletonID, VirtProcr *animPr ) 5.128 +VPThread__end_fn_singleton( int32 singletonID, VirtProcr *animPr ) 5.129 { 5.130 VPThdSemReq reqData; 5.131 5.132 //don't need this addr until after at least one singleton has reached 5.133 // this function 5.134 VPThdSemEnv *semEnv = VMS__give_sem_env_for( animPr ); 5.135 - semEnv->singletons[ singletonID ].endInstrAddr = &&EndSingletonInstrAddr; 5.136 - 5.137 - reqData.reqType = singleton_end; 5.138 + semEnv->fnSingletons[ singletonID].endInstrAddr = &&EndSingletonInstrAddr; 5.139 + 5.140 + reqData.reqType = singleton_fn_end; 5.141 reqData.singletonID = singletonID; 5.142 5.143 VMS__send_sem_request( &reqData, animPr ); 5.144 @@ -480,6 +536,38 @@ 5.145 return; 5.146 } 5.147 5.148 +void 5.149 +VPThread__end_data_singleton( VPThdSingleton **singletonPtrAddr, VirtProcr *animPr ) 5.150 + { 5.151 + VPThdSemReq reqData; 5.152 + 5.153 + //don't need this addr until after singleton struct has reached 5.154 + // this function for first time 5.155 + //do assembly that saves the return addr of this fn call into the 5.156 + // data singleton -- that data-singleton can only be given to exactly 5.157 + // one instance in the code of this function. However, can use this 5.158 + // function in different places for different data-singletons. 5.159 +// (*(singletonAddr))->endInstrAddr = &&EndDataSingletonInstrAddr; 5.160 + 5.161 + //Assembly code takes the return addr off the stack and saves 5.162 + // into the singleton. The first field in the singleton is the 5.163 + // "endInstrAddr" field, and the return addr is at 0x4(%%ebp) 5.164 + asm volatile("movl 0x4(%%ebp), %%eax; \ 5.165 + movl %0, %%ebx; \ 5.166 + movl (%%ebx), %%ecx; \ 5.167 + movl %%eax, (%%ecx);" \ 5.168 + /* outputs */ : \ 5.169 + /* inputs */ : "m"(singletonPtrAddr) \ 5.170 + /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx","%edi","%esi"\ 5.171 + ); 5.172 + 5.173 + reqData.reqType = singleton_data_end; 5.174 + reqData.singletonPtrAddr = singletonPtrAddr; 5.175 + 5.176 + VMS__send_sem_request( &reqData, animPr ); 5.177 + } 5.178 + 5.179 + 5.180 /*This executes the function in the masterVP, so it executes in isolation 5.181 * from any other copies -- only one copy of the function can ever execute 5.182 * at a time.
