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