Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
diff VMS.c @ 61:984f7d78bfdf
Merge See what happens -- merged test stuff into Nov 8 VMS version
| author | SeanHalle |
|---|---|
| date | Thu, 11 Nov 2010 06:19:51 -0800 |
| parents | 054006c26b92 26d53313a8f2 |
| children |
line diff
1.1 --- a/VMS.c Tue Oct 26 18:31:34 2010 -0700 1.2 +++ b/VMS.c Thu Nov 11 06:19:51 2010 -0800 1.3 @@ -6,7 +6,9 @@ 1.4 1.5 #include <stdio.h> 1.6 #include <stdlib.h> 1.7 +#include <string.h> 1.8 #include <malloc.h> 1.9 +#include <sys/time.h> 1.10 1.11 #include "VMS.h" 1.12 #include "Queue_impl/BlockingQueue.h" 1.13 @@ -28,6 +30,12 @@ 1.14 void 1.15 create_the_coreLoop_OS_threads(); 1.16 1.17 +MallocProlog * 1.18 +create_free_list(); 1.19 + 1.20 +void 1.21 +endOSThreadFn( void *initData, VirtProcr *animatingPr ); 1.22 + 1.23 pthread_mutex_t suspendLock = PTHREAD_MUTEX_INITIALIZER; 1.24 pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER; 1.25 1.26 @@ -83,34 +91,43 @@ 1.27 int coreIdx; 1.28 VirtProcr **masterVPs; 1.29 SchedSlot ***allSchedSlots; //ptr to array of ptrs 1.30 - 1.31 + 1.32 + 1.33 //Make the master env, which holds everything else 1.34 _VMSMasterEnv = malloc( sizeof(MasterEnv) ); 1.35 + 1.36 + //Very first thing put into the master env is the free-list, seeded 1.37 + // with a massive initial chunk of memory. 1.38 + //After this, all other mallocs are VMS__malloc. 1.39 + _VMSMasterEnv->freeListHead = VMS_ext__create_free_list(); 1.40 + 1.41 + //===================== Only VMS__malloc after this ==================== 1.42 masterEnv = _VMSMasterEnv; 1.43 - //Need to set start pt here 'cause used by seed procr, which is created 1.44 - // before the first core loop starts up. -- not sure how yet.. 1.45 -// masterEnv->coreLoopStartPt = ; 1.46 -// masterEnv->coreLoopEndPt = ; 1.47 1.48 //Make a readyToAnimateQ for each core loop 1.49 - readyToAnimateQs = malloc( NUM_CORES * sizeof(VMSQueueStruc *) ); 1.50 - masterVPs = malloc( NUM_CORES * sizeof(VirtProcr *) ); 1.51 + readyToAnimateQs = VMS__malloc( NUM_CORES * sizeof(VMSQueueStruc *) ); 1.52 + masterVPs = VMS__malloc( NUM_CORES * sizeof(VirtProcr *) ); 1.53 1.54 //One array for each core, 3 in array, core's masterVP scheds all 1.55 - allSchedSlots = malloc( NUM_CORES * sizeof(SchedSlot *) ); 1.56 + allSchedSlots = VMS__malloc( NUM_CORES * sizeof(SchedSlot *) ); 1.57 1.58 + _VMSMasterEnv->numProcrsCreated = 0; //used by create procr 1.59 for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 1.60 - { 1.61 - readyToAnimateQs[ coreIdx ] = makeSRSWQ(); 1.62 + { 1.63 + readyToAnimateQs[ coreIdx ] = makeVMSQ(); 1.64 1.65 - //Q: should give masterVP core-specific into as its init data? 1.66 + //Q: should give masterVP core-specific info as its init data? 1.67 masterVPs[ coreIdx ] = VMS__create_procr( &masterLoop, masterEnv ); 1.68 masterVPs[ coreIdx ]->coreAnimatedBy = coreIdx; 1.69 allSchedSlots[ coreIdx ] = create_sched_slots(); //makes for one core 1.70 + _VMSMasterEnv->numMasterInARow[ coreIdx ] = 0; 1.71 + _VMSMasterEnv->workStealingGates[ coreIdx ] = NULL; 1.72 } 1.73 _VMSMasterEnv->readyToAnimateQs = readyToAnimateQs; 1.74 _VMSMasterEnv->masterVPs = masterVPs; 1.75 + _VMSMasterEnv->masterLock = UNLOCKED; 1.76 _VMSMasterEnv->allSchedSlots = allSchedSlots; 1.77 + _VMSMasterEnv->workStealingLock = UNLOCKED; 1.78 1.79 //============================= MEASUREMENT STUFF ======================== 1.80 #ifdef MEAS__TIME_MASTER 1.81 @@ -125,59 +142,33 @@ 1.82 // because coreLoop now controls -- animates its masterVP when no work 1.83 1.84 1.85 - //==================== malloc substitute ======================== 1.86 - // 1.87 - //Testing whether malloc is using thread-local storage and therefore 1.88 - // causing unreliable behavior. 1.89 - //Just allocate a massive chunk of memory and roll own malloc/free and 1.90 - // make app use VMS__malloc_to, which will suspend and perform malloc 1.91 - // in the master, taking from this massive chunk. 1.92 + //============================= MEASUREMENT STUFF ======================== 1.93 + #ifdef STATS__TURN_ON_PROBES 1.94 + _VMSMasterEnv->dynIntervalProbesInfo = 1.95 + makePrivDynArrayOfSize( &(_VMSMasterEnv->intervalProbes), 200); 1.96 1.97 -// initFreeList(); 1.98 + _VMSMasterEnv->probeNameHashTbl = makeHashTable( 1000, &VMS__free ); 1.99 + 1.100 + //put creation time directly into master env, for fast retrieval 1.101 + struct timeval timeStamp; 1.102 + gettimeofday( &(timeStamp), NULL); 1.103 + _VMSMasterEnv->createPtInSecs = 1.104 + timeStamp.tv_sec +(timeStamp.tv_usec/1000000.0); 1.105 + #endif 1.106 + //======================================================================== 1.107 1.108 } 1.109 1.110 -/* 1.111 -void 1.112 -initMasterMalloc() 1.113 - { 1.114 - _VMSMasterEnv->mallocChunk = malloc( MASSIVE_MALLOC_SIZE ); 1.115 - 1.116 - //The free-list element is the first several locations of an 1.117 - // allocated chunk -- the address given to the application is pre- 1.118 - // pended with both the ownership structure and the free-list struc. 1.119 - //So, write the values of these into the first locations of 1.120 - // mallocChunk -- which marks it as free & puts in its size. 1.121 - listElem = (FreeListElem *)_VMSMasterEnv->mallocChunk; 1.122 - listElem->size = MASSIVE_MALLOC_SIZE - NUM_PREPEND_BYTES 1.123 - listElem->next = NULL; 1.124 - } 1.125 - 1.126 -void 1.127 -dissipateMasterMalloc() 1.128 - { 1.129 - //Just foo code -- to get going -- doing as if free list were link-list 1.130 - currElem = _VMSMasterEnv->freeList; 1.131 - while( currElem != NULL ) 1.132 - { 1.133 - nextElem = currElem->next; 1.134 - masterFree( currElem ); 1.135 - currElem = nextElem; 1.136 - } 1.137 - free( _VMSMasterEnv->freeList ); 1.138 - } 1.139 - */ 1.140 - 1.141 SchedSlot ** 1.142 create_sched_slots() 1.143 { SchedSlot **schedSlots; 1.144 int i; 1.145 1.146 - schedSlots = malloc( NUM_SCHED_SLOTS * sizeof(SchedSlot *) ); 1.147 + schedSlots = VMS__malloc( NUM_SCHED_SLOTS * sizeof(SchedSlot *) ); 1.148 1.149 for( i = 0; i < NUM_SCHED_SLOTS; i++ ) 1.150 { 1.151 - schedSlots[i] = malloc( sizeof(SchedSlot) ); 1.152 + schedSlots[i] = VMS__malloc( sizeof(SchedSlot) ); 1.153 1.154 //Set state to mean "handling requests done, slot needs filling" 1.155 schedSlots[i]->workIsDone = FALSE; 1.156 @@ -192,9 +183,9 @@ 1.157 { int i; 1.158 for( i = 0; i < NUM_SCHED_SLOTS; i++ ) 1.159 { 1.160 - free( schedSlots[i] ); 1.161 + VMS__free( schedSlots[i] ); 1.162 } 1.163 - free( schedSlots ); 1.164 + VMS__free( schedSlots ); 1.165 } 1.166 1.167 1.168 @@ -203,7 +194,7 @@ 1.169 { 1.170 //======================================================================== 1.171 // Create the Threads 1.172 - int coreIdx, retCode, i; 1.173 + int coreIdx, retCode; 1.174 1.175 //create the arrays used to measure TSC offsets between cores 1.176 pongNums = malloc( NUM_CORES * sizeof( int ) ); 1.177 @@ -227,7 +218,7 @@ 1.178 1.179 //Make the threads that animate the core loops 1.180 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) 1.181 - { coreLoopThdParams[coreIdx] = malloc( sizeof(ThdParams) ); 1.182 + { coreLoopThdParams[coreIdx] = VMS__malloc( sizeof(ThdParams) ); 1.183 coreLoopThdParams[coreIdx]->coreNum = coreIdx; 1.184 1.185 retCode = 1.186 @@ -235,7 +226,7 @@ 1.187 thdAttrs, 1.188 &coreLoop, 1.189 (void *)(coreLoopThdParams[coreIdx]) ); 1.190 - if(retCode){printf("ERROR creating thread: %d\n", retCode); exit(0);} 1.191 + if(retCode){printf("ERROR creating thread: %d\n", retCode); exit(1);} 1.192 } 1.193 } 1.194 1.195 @@ -307,10 +298,11 @@ 1.196 * animator state to return to -- 1.197 * 1.198 */ 1.199 -VirtProcr * 1.200 -VMS__create_procr( VirtProcrFnPtr fnPtr, void *initialData ) 1.201 - { VirtProcr *newPr; 1.202 - char *stackLocs, *stackPtr; 1.203 +inline VirtProcr * 1.204 +create_procr_helper( VirtProcr *newPr, VirtProcrFnPtr fnPtr, 1.205 + void *initialData, char *stackLocs ) 1.206 + { 1.207 + char *stackPtr; 1.208 1.209 //============================= MEASUREMENT STUFF ======================== 1.210 #ifdef MEAS__TIME_MASTER 1.211 @@ -318,23 +310,19 @@ 1.212 saveLowTimeStampCountInto( startStamp ); 1.213 #endif 1.214 //======================================================================== 1.215 - 1.216 - newPr = malloc( sizeof(VirtProcr) ); 1.217 - newPr->procrID = numProcrsCreated++; 1.218 - newPr->nextInstrPt = fnPtr; 1.219 - newPr->initialData = initialData; 1.220 - newPr->requests = NULL; 1.221 - newPr->schedSlot = NULL; 1.222 -// newPr->coreLoopStartPt = _VMSMasterEnv->coreLoopStartPt; 1.223 + newPr->startOfStack = stackLocs; 1.224 + newPr->procrID = _VMSMasterEnv->numProcrsCreated++; 1.225 + newPr->nextInstrPt = fnPtr; 1.226 + newPr->initialData = initialData; 1.227 + newPr->requests = NULL; 1.228 + newPr->schedSlot = NULL; 1.229 1.230 //fnPtr takes two params -- void *initData & void *animProcr 1.231 //alloc stack locations, make stackPtr be the highest addr minus room 1.232 // for 2 params + return addr. Return addr (NULL) is in loc pointed to 1.233 // by stackPtr, initData at stackPtr + 4 bytes, animatingPr just above 1.234 - stackLocs = malloc( VIRT_PROCR_STACK_SIZE ); 1.235 - if(stackLocs == 0) {perror("error: malloc stack"); exit(1);} 1.236 - newPr->startOfStack = stackLocs; 1.237 stackPtr = ( (char *)stackLocs + VIRT_PROCR_STACK_SIZE - 0x10 ); 1.238 + 1.239 //setup __cdecl on stack -- coreloop will switch to stackPtr before jmp 1.240 *( (int *)stackPtr + 2 ) = (int) newPr; //rightmost param -- 32bit pointer 1.241 *( (int *)stackPtr + 1 ) = (int) initialData; //next param to left 1.242 @@ -347,12 +335,48 @@ 1.243 saveLowTimeStampCountInto( endStamp ); 1.244 addIntervalToHist( startStamp, endStamp, 1.245 _VMSMasterEnv->stats->createHist ); 1.246 + //============================= MEASUREMENT STUFF ======================== 1.247 + #ifdef STATS__TURN_ON_PROBES 1.248 + struct timeval timeStamp; 1.249 + gettimeofday( &(timeStamp), NULL); 1.250 + newPr->createPtInSecs = timeStamp.tv_sec +(timeStamp.tv_usec/1000000.0) - 1.251 + _VMSMasterEnv->createPtInSecs; 1.252 #endif 1.253 //======================================================================== 1.254 - 1.255 + 1.256 return newPr; 1.257 } 1.258 1.259 +inline VirtProcr * 1.260 +VMS__create_procr( VirtProcrFnPtr fnPtr, void *initialData ) 1.261 + { VirtProcr *newPr; 1.262 + char *stackLocs; 1.263 + 1.264 + newPr = VMS__malloc( sizeof(VirtProcr) ); 1.265 + stackLocs = VMS__malloc( VIRT_PROCR_STACK_SIZE ); 1.266 + if( stackLocs == 0 ) 1.267 + { perror("VMS__malloc stack"); exit(1); } 1.268 + 1.269 + return create_procr_helper( newPr, fnPtr, initialData, stackLocs ); 1.270 + } 1.271 + 1.272 +/* "ext" designates that it's for use outside the VMS system -- should only 1.273 + * be called from main thread or other thread -- never from code animated by 1.274 + * a VMS virtual processor. 1.275 + */ 1.276 +inline VirtProcr * 1.277 +VMS_ext__create_procr( VirtProcrFnPtr fnPtr, void *initialData ) 1.278 + { VirtProcr *newPr; 1.279 + char *stackLocs; 1.280 + 1.281 + newPr = malloc( sizeof(VirtProcr) ); 1.282 + stackLocs = malloc( VIRT_PROCR_STACK_SIZE ); 1.283 + if( stackLocs == 0 ) 1.284 + { perror("malloc stack"); exit(1); } 1.285 + 1.286 + return create_procr_helper( newPr, fnPtr, initialData, stackLocs ); 1.287 + } 1.288 + 1.289 1.290 /*there is a label inside this function -- save the addr of this label in 1.291 * the callingPr struc, as the pick-up point from which to start the next 1.292 @@ -365,8 +389,7 @@ 1.293 */ 1.294 void 1.295 VMS__suspend_procr( VirtProcr *animatingPr ) 1.296 - { void *jmpPt, *stackPtrAddr, *framePtrAddr, *coreLoopStackPtr; 1.297 - void *coreLoopFramePtr; 1.298 + { 1.299 1.300 //The request to master will cause this suspended virt procr to get 1.301 // scheduled again at some future point -- to resume, core loop jumps 1.302 @@ -376,24 +399,6 @@ 1.303 1.304 //return ownership of the virt procr and sched slot to Master virt pr 1.305 animatingPr->schedSlot->workIsDone = TRUE; 1.306 -// coreIdx = callingPr->coreAnimatedBy; 1.307 - 1.308 - stackPtrAddr = &(animatingPr->stackPtr); 1.309 - framePtrAddr = &(animatingPr->framePtr); 1.310 - 1.311 - jmpPt = _VMSMasterEnv->coreLoopStartPt; 1.312 - coreLoopFramePtr = animatingPr->coreLoopFramePtr;//need this only 1.313 - coreLoopStackPtr = animatingPr->coreLoopStackPtr;//safety 1.314 - 1.315 - //Save the virt procr's stack and frame ptrs, 1.316 - asm volatile("movl %0, %%eax; \ 1.317 - movl %%esp, (%%eax); \ 1.318 - movl %1, %%eax; \ 1.319 - movl %%ebp, (%%eax) "\ 1.320 - /* outputs */ : "=g" (stackPtrAddr), "=g" (framePtrAddr) \ 1.321 - /* inputs */ : \ 1.322 - /* clobber */ : "%eax" \ 1.323 - ); 1.324 1.325 //=========================== Measurement stuff ======================== 1.326 #ifdef MEAS__TIME_STAMP_SUSP 1.327 @@ -402,20 +407,10 @@ 1.328 #endif 1.329 //======================================================================= 1.330 1.331 - //restore coreloop's frame ptr, then jump back to "start" of core loop 1.332 - //Note, GCC compiles to assembly that saves esp and ebp in the stack 1.333 - // frame -- so have to explicitly do assembly that saves to memory 1.334 - asm volatile("movl %0, %%eax; \ 1.335 - movl %1, %%esp; \ 1.336 - movl %2, %%ebp; \ 1.337 - jmp %%eax " \ 1.338 - /* outputs */ : \ 1.339 - /* inputs */ : "m" (jmpPt), "m"(coreLoopStackPtr), "m"(coreLoopFramePtr)\ 1.340 - /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi","%esi" \ 1.341 - ); //list everything as clobbered to force GCC to save all 1.342 - // live vars that are in regs on stack before this 1.343 - // assembly, so that stack pointer is correct, before jmp 1.344 1.345 + SwitchToCoreLoop( animatingPr ) 1.346 + 1.347 + //======================================================================= 1.348 ResumePt: 1.349 #ifdef MEAS__TIME_STAMP_SUSP 1.350 //NOTE: only take low part of count -- do sanity check when take diff 1.351 @@ -427,6 +422,31 @@ 1.352 1.353 1.354 1.355 +/*For this implementation of VMS, it may not make much sense to have the 1.356 + * system of requests for creating a new processor done this way.. but over 1.357 + * the scope of single-master, multi-master, mult-tasking, OS-implementing, 1.358 + * distributed-memory, and so on, this gives VMS implementation a chance to 1.359 + * do stuff before suspend, in the AppVP, and in the Master before the plugin 1.360 + * is called, as well as in the lang-lib before this is called, and in the 1.361 + * plugin. So, this gives both VMS and language implementations a chance to 1.362 + * intercept at various points and do order-dependent stuff. 1.363 + *Having a standard VMSNewPrReqData struc allows the language to create and 1.364 + * free the struc, while VMS knows how to get the newPr if it wants it, and 1.365 + * it lets the lang have lang-specific data related to creation transported 1.366 + * to the plugin. 1.367 + */ 1.368 +void 1.369 +VMS__send_create_procr_req( void *semReqData, VirtProcr *reqstingPr ) 1.370 + { VMSReqst req; 1.371 + 1.372 + req.reqType = createReq; 1.373 + req.semReqData = semReqData; 1.374 + req.nextReqst = reqstingPr->requests; 1.375 + reqstingPr->requests = &req; 1.376 + 1.377 + VMS__suspend_procr( reqstingPr ); 1.378 + } 1.379 + 1.380 1.381 /* 1.382 *This adds a request to dissipate, then suspends the processor so that the 1.383 @@ -450,81 +470,102 @@ 1.384 * pears -- making that suspend the last thing in the virt procr's trace. 1.385 */ 1.386 void 1.387 -VMS__dissipate_procr( VirtProcr *procrToDissipate ) 1.388 +VMS__send_dissipate_req( VirtProcr *procrToDissipate ) 1.389 + { VMSReqst req; 1.390 + 1.391 + req.reqType = dissipate; 1.392 + req.nextReqst = procrToDissipate->requests; 1.393 + procrToDissipate->requests = &req; 1.394 + 1.395 + VMS__suspend_procr( procrToDissipate ); 1.396 + } 1.397 + 1.398 + 1.399 +/* "ext" designates that it's for use outside the VMS system -- should only 1.400 + * be called from main thread or other thread -- never from code animated by 1.401 + * a VMS virtual processor. 1.402 + * 1.403 + *Use this version to dissipate VPs created outside the VMS system. 1.404 + */ 1.405 +void 1.406 +VMS_ext__dissipate_procr( VirtProcr *procrToDissipate ) 1.407 + { 1.408 + //NOTE: initialData was given to the processor, so should either have 1.409 + // been alloc'd with VMS__malloc, or freed by the level above animPr. 1.410 + //So, all that's left to free here is the stack and the VirtProcr struc 1.411 + // itself 1.412 + //Note, should not stack-allocate initial data -- no guarantee, in 1.413 + // general that creating processor will outlive ones it creates. 1.414 + free( procrToDissipate->startOfStack ); 1.415 + free( procrToDissipate ); 1.416 + } 1.417 + 1.418 + 1.419 + 1.420 +/*This call's name indicates that request is malloc'd -- so req handler 1.421 + * has to free any extra requests tacked on before a send, using this. 1.422 + * 1.423 + * This inserts the semantic-layer's request data into standard VMS carrier 1.424 + * request data-struct that is mallocd. The sem request doesn't need to 1.425 + * be malloc'd if this is called inside the same call chain before the 1.426 + * send of the last request is called. 1.427 + * 1.428 + *The request handler has to call VMS__free_VMSReq for any of these 1.429 + */ 1.430 +inline void 1.431 +VMS__add_sem_request_in_mallocd_VMSReqst( void *semReqData, 1.432 + VirtProcr *callingPr ) 1.433 { VMSReqst *req; 1.434 1.435 - req = malloc( sizeof(VMSReqst) ); 1.436 -// req->virtProcrFrom = callingPr; 1.437 - req->reqType = dissipate; 1.438 - req->nextReqst = procrToDissipate->requests; 1.439 - procrToDissipate->requests = req; 1.440 - 1.441 - VMS__suspend_procr( procrToDissipate ); 1.442 -} 1.443 - 1.444 - 1.445 -/*This inserts the semantic-layer's request data into standard VMS carrier 1.446 - */ 1.447 -inline void 1.448 -VMS__add_sem_request( void *semReqData, VirtProcr *callingPr ) 1.449 - { VMSReqst *req; 1.450 - 1.451 - req = malloc( sizeof(VMSReqst) ); 1.452 -// req->virtProcrFrom = callingPr; 1.453 - req->reqType = semantic; 1.454 - req->semReqData = semReqData; 1.455 - req->nextReqst = callingPr->requests; 1.456 + req = VMS__malloc( sizeof(VMSReqst) ); 1.457 + req->reqType = semantic; 1.458 + req->semReqData = semReqData; 1.459 + req->nextReqst = callingPr->requests; 1.460 callingPr->requests = req; 1.461 } 1.462 1.463 +/*This inserts the semantic-layer's request data into standard VMS carrier 1.464 + * request data-struct is allocated on stack of this call & ptr to it sent 1.465 + * to plugin 1.466 + *Then it does suspend, to cause request to be sent. 1.467 + */ 1.468 +inline void 1.469 +VMS__send_sem_request( void *semReqData, VirtProcr *callingPr ) 1.470 + { VMSReqst req; 1.471 1.472 -/*Use this to get first request before starting request handler's loop 1.473 + req.reqType = semantic; 1.474 + req.semReqData = semReqData; 1.475 + req.nextReqst = callingPr->requests; 1.476 + callingPr->requests = &req; 1.477 + 1.478 + VMS__suspend_procr( callingPr ); 1.479 + } 1.480 + 1.481 + 1.482 +inline void 1.483 +VMS__send_VMSSem_request( void *semReqData, VirtProcr *callingPr ) 1.484 + { VMSReqst req; 1.485 + 1.486 + req.reqType = VMSSemantic; 1.487 + req.semReqData = semReqData; 1.488 + req.nextReqst = callingPr->requests; //gab any other preceeding 1.489 + callingPr->requests = &req; 1.490 + 1.491 + VMS__suspend_procr( callingPr ); 1.492 + } 1.493 + 1.494 + 1.495 +/* 1.496 */ 1.497 VMSReqst * 1.498 -VMS__take_top_request_from( VirtProcr *procrWithReq ) 1.499 - { VMSReqst *req; 1.500 - 1.501 - req = procrWithReq->requests; 1.502 - if( req == NULL ) return req; 1.503 - 1.504 - procrWithReq->requests = procrWithReq->requests->nextReqst; 1.505 - return req; 1.506 - } 1.507 - 1.508 -/*A subtle bug due to freeing then accessing "next" after freed caused this 1.509 - * form of call to be put in -- so call this at end of request handler loop 1.510 - * that iterates through the requests. 1.511 - */ 1.512 -VMSReqst * 1.513 -VMS__free_top_and_give_next_request_from( VirtProcr *procrWithReq ) 1.514 +VMS__take_next_request_out_of( VirtProcr *procrWithReq ) 1.515 { VMSReqst *req; 1.516 1.517 req = procrWithReq->requests; 1.518 if( req == NULL ) return NULL; 1.519 1.520 procrWithReq->requests = procrWithReq->requests->nextReqst; 1.521 - VMS__free_request( req ); 1.522 - return procrWithReq->requests; 1.523 - } 1.524 - 1.525 - 1.526 -//TODO: add a semantic-layer supplied "freer" for the semantic-data portion 1.527 -// of a request -- IE call with both a virt procr and a fn-ptr to request 1.528 -// freer (also maybe put sem request freer as a field in virt procr?) 1.529 -//MeasVMS relies right now on this only freeing VMS layer of request -- the 1.530 -// semantic portion of request is alloc'd and freed by request handler 1.531 -void 1.532 -VMS__free_request( VMSReqst *req ) 1.533 - { 1.534 - free( req ); 1.535 - } 1.536 - 1.537 - 1.538 - 1.539 -inline int 1.540 -VMS__isSemanticReqst( VMSReqst *req ) 1.541 - { 1.542 - return ( req->reqType == semantic ); 1.543 + return req; 1.544 } 1.545 1.546 1.547 @@ -534,36 +575,52 @@ 1.548 return req->semReqData; 1.549 } 1.550 1.551 -inline int 1.552 -VMS__isDissipateReqst( VMSReqst *req ) 1.553 - { 1.554 - return ( req->reqType == dissipate ); 1.555 - } 1.556 1.557 -inline int 1.558 -VMS__isCreateReqst( VMSReqst *req ) 1.559 - { 1.560 - return ( req->reqType == regCreated ); 1.561 - } 1.562 1.563 -void 1.564 -VMS__send_req_to_register_new_procr(VirtProcr *newPr, VirtProcr *reqstingPr) 1.565 - { VMSReqst *req; 1.566 +/* This is for OS requests and VMS infrastructure requests, such as to create 1.567 + * a probe -- a probe is inside the heart of VMS-core, it's not part of any 1.568 + * language -- but it's also a semantic thing that's triggered from and used 1.569 + * in the application.. so it crosses abstractions.. so, need some special 1.570 + * pattern here for handling such requests. 1.571 + * Doing this just like it were a second language sharing VMS-core. 1.572 + * 1.573 + * This is called from the language's request handler when it sees a request 1.574 + * of type VMSSemReq 1.575 + * 1.576 + * TODO: Later change this, to give probes their own separate plugin & have 1.577 + * VMS-core steer the request to appropriate plugin 1.578 + * Do the same for OS calls -- look later at it.. 1.579 + */ 1.580 +void inline 1.581 +VMS__handle_VMSSemReq( VMSReqst *req, VirtProcr *requestingPr, void *semEnv, 1.582 + ResumePrFnPtr resumePrFnPtr ) 1.583 + { VMSSemReq *semReq; 1.584 + IntervalProbe *newProbe; 1.585 + int32 nameLen; 1.586 1.587 - req = malloc( sizeof(VMSReqst) ); 1.588 - req->reqType = regCreated; 1.589 - req->semReqData = newPr; 1.590 - req->nextReqst = reqstingPr->requests; 1.591 - reqstingPr->requests = req; 1.592 + semReq = req->semReqData; 1.593 1.594 - VMS__suspend_procr( reqstingPr ); 1.595 + newProbe = VMS__malloc( sizeof(IntervalProbe) ); 1.596 + nameLen = strlen( semReq->nameStr ); 1.597 + newProbe->nameStr = VMS__malloc( nameLen ); 1.598 + memcpy( newProbe->nameStr, semReq->nameStr, nameLen ); 1.599 + newProbe->hist = NULL; 1.600 + newProbe->schedChoiceWasRecorded = FALSE; 1.601 + 1.602 + //This runs in masterVP, so no race-condition worries 1.603 + newProbe->probeID = 1.604 + addToDynArray( newProbe, _VMSMasterEnv->dynIntervalProbesInfo ); 1.605 + 1.606 + requestingPr->dataRetFromReq = newProbe; 1.607 + 1.608 + (*resumePrFnPtr)( requestingPr, semEnv ); 1.609 } 1.610 1.611 1.612 1.613 /*This must be called by the request handler plugin -- it cannot be called 1.614 * from the semantic library "dissipate processor" function -- instead, the 1.615 - * semantic layer has to generate a request for the plug-in to call this 1.616 + * semantic layer has to generate a request, and the plug-in calls this 1.617 * function. 1.618 *The reason is that this frees the virtual processor's stack -- which is 1.619 * still in use inside semantic library calls! 1.620 @@ -579,33 +636,31 @@ 1.621 * of dis-owning it. 1.622 */ 1.623 void 1.624 -VMS__handle_dissipate_reqst( VirtProcr *animatingPr ) 1.625 +VMS__dissipate_procr( VirtProcr *animatingPr ) 1.626 { 1.627 //dis-own all locations owned by this processor, causing to be freed 1.628 // any locations that it is (was) sole owner of 1.629 //TODO: implement VMS__malloc system, including "give up ownership" 1.630 1.631 - //The dissipate request might still be attached, so remove and free it 1.632 - VMS__free_top_and_give_next_request_from( animatingPr ); 1.633 1.634 //NOTE: initialData was given to the processor, so should either have 1.635 // been alloc'd with VMS__malloc, or freed by the level above animPr. 1.636 //So, all that's left to free here is the stack and the VirtProcr struc 1.637 // itself 1.638 - free( animatingPr->startOfStack ); 1.639 - free( animatingPr ); 1.640 + //Note, should not stack-allocate initial data -- no guarantee, in 1.641 + // general that creating processor will outlive ones it creates. 1.642 + VMS__free( animatingPr->startOfStack ); 1.643 + VMS__free( animatingPr ); 1.644 } 1.645 1.646 1.647 -//TODO: re-architect so that have clean separation between request handler 1.648 +//TODO: look at architecting cleanest separation between request handler 1.649 // and master loop, for dissipate, create, shutdown, and other non-semantic 1.650 // requests. Issue is chain: one removes requests from AppVP, one dispatches 1.651 // on type of request, and one handles each type.. but some types require 1.652 // action from both request handler and master loop -- maybe just give the 1.653 // request handler calls like: VMS__handle_X_request_type 1.654 1.655 -void 1.656 -endOSThreadFn( void *initData, VirtProcr *animatingPr ); 1.657 1.658 /*This is called by the semantic layer's request handler when it decides its 1.659 * time to shut down the VMS system. Calling this causes the core loop OS 1.660 @@ -619,10 +674,9 @@ 1.661 * masterVP any AppVPs that might still be allocated and sitting in the 1.662 * semantic environment, or have been orphaned in the _VMSWorkQ. 1.663 * 1.664 - *NOTE: the semantic plug-in is expected to use VMS__malloc_to to get all the 1.665 + *NOTE: the semantic plug-in is expected to use VMS__malloc to get all the 1.666 * locations it needs, and give ownership to masterVP. Then, they will be 1.667 - * automatically freed when the masterVP is dissipated. (This happens after 1.668 - * the core loop threads have all exited) 1.669 + * automatically freed. 1.670 * 1.671 *In here,create one core-loop shut-down processor for each core loop and put 1.672 * them all directly into the readyToAnimateQ. 1.673 @@ -633,16 +687,16 @@ 1.674 * point is it sure that all results have completed. 1.675 */ 1.676 void 1.677 -VMS__handle_shutdown_reqst( void *dummy, VirtProcr *animatingPr ) 1.678 +VMS__shutdown() 1.679 { int coreIdx; 1.680 VirtProcr *shutDownPr; 1.681 1.682 //create the shutdown processors, one for each core loop -- put them 1.683 // directly into the Q -- each core will die when gets one 1.684 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) 1.685 - { 1.686 + { //Note, this is running in the master 1.687 shutDownPr = VMS__create_procr( &endOSThreadFn, NULL ); 1.688 - writeSRSWQ( shutDownPr, _VMSMasterEnv->readyToAnimateQs[coreIdx] ); 1.689 + writeVMSQ( shutDownPr, _VMSMasterEnv->readyToAnimateQs[coreIdx] ); 1.690 } 1.691 1.692 } 1.693 @@ -681,49 +735,60 @@ 1.694 } 1.695 1.696 1.697 -/*This is called after the threads have shut down and control has returned 1.698 - * to the semantic layer, in the entry point function in the main thread. 1.699 - * It has to free anything allocated during VMS_init, and any other alloc'd 1.700 - * locations that might be left over. 1.701 +/*This is called from the startup & shutdown 1.702 */ 1.703 void 1.704 -VMS__cleanup_after_shutdown() 1.705 +VMS__cleanup_at_end_of_shutdown() 1.706 { 1.707 VMSQueueStruc **readyToAnimateQs; 1.708 int coreIdx; 1.709 VirtProcr **masterVPs; 1.710 SchedSlot ***allSchedSlots; //ptr to array of ptrs 1.711 1.712 + //All the environment data has been allocated with VMS__malloc, so just 1.713 + // free its internal big-chunk and all inside it disappear. 1.714 +/* 1.715 readyToAnimateQs = _VMSMasterEnv->readyToAnimateQs; 1.716 masterVPs = _VMSMasterEnv->masterVPs; 1.717 allSchedSlots = _VMSMasterEnv->allSchedSlots; 1.718 1.719 for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 1.720 { 1.721 - freeSRSWQ( readyToAnimateQs[ coreIdx ] ); 1.722 - 1.723 - VMS__handle_dissipate_reqst( masterVPs[ coreIdx ] ); 1.724 + freeVMSQ( readyToAnimateQs[ coreIdx ] ); 1.725 + //master VPs were created external to VMS, so use external free 1.726 + VMS__dissipate_procr( masterVPs[ coreIdx ] ); 1.727 1.728 freeSchedSlots( allSchedSlots[ coreIdx ] ); 1.729 } 1.730 1.731 - free( _VMSMasterEnv->readyToAnimateQs ); 1.732 - free( _VMSMasterEnv->masterVPs ); 1.733 - free( _VMSMasterEnv->allSchedSlots ); 1.734 - 1.735 - free( _VMSMasterEnv ); 1.736 + VMS__free( _VMSMasterEnv->readyToAnimateQs ); 1.737 + VMS__free( _VMSMasterEnv->masterVPs ); 1.738 + VMS__free( _VMSMasterEnv->allSchedSlots ); 1.739 + 1.740 + //============================= MEASUREMENT STUFF ======================== 1.741 + #ifdef STATS__TURN_ON_PROBES 1.742 + freeDynArrayDeep( _VMSMasterEnv->dynIntervalProbesInfo, &VMS__free_probe); 1.743 + #endif 1.744 + //======================================================================== 1.745 +*/ 1.746 + //These are the only two that use system free 1.747 + VMS_ext__free_free_list( _VMSMasterEnv->freeListHead ); 1.748 + free( (void *)_VMSMasterEnv ); 1.749 } 1.750 1.751 1.752 -//=========================================================================== 1.753 +//================================ 1.754 1.755 -inline TSCount getTSC() 1.756 - { unsigned int low, high; 1.757 - TSCount out; 1.758 1.759 - saveTimeStampCountInto( low, high ); 1.760 - out = high; 1.761 - out = (out << 32) + low; 1.762 - return out; 1.763 +/*Later, improve this -- for now, just exits the application after printing 1.764 + * the error message. 1.765 + */ 1.766 +void 1.767 +VMS__throw_exception( char *msgStr, VirtProcr *reqstPr, VMSExcp *excpData ) 1.768 + { 1.769 + printf(msgStr); 1.770 + fflush(stdin); 1.771 + exit(1); 1.772 } 1.773 1.774 +
