comparison VMS.c @ 57:85b731b290f8

Merge between VCilk and SSR intermediate Nov 4
author Me
date Thu, 04 Nov 2010 18:27:27 -0700
parents 420a09d3f32a f8508572f3de
children 26d53313a8f2
comparison
equal deleted inserted replaced
26:f5d6e507b8f2 27:8e2ba82c520b
31 create_the_coreLoop_OS_threads(); 31 create_the_coreLoop_OS_threads();
32 32
33 MallocProlog * 33 MallocProlog *
34 create_free_list(); 34 create_free_list();
35 35
36 void
37 endOSThreadFn( void *initData, VirtProcr *animatingPr );
36 38
37 pthread_mutex_t suspendLock = PTHREAD_MUTEX_INITIALIZER; 39 pthread_mutex_t suspendLock = PTHREAD_MUTEX_INITIALIZER;
38 pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER; 40 pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
39 41
40 //=========================================================================== 42 //===========================================================================
87 { MasterEnv *masterEnv; 89 { MasterEnv *masterEnv;
88 SRSWQueueStruc **readyToAnimateQs; 90 SRSWQueueStruc **readyToAnimateQs;
89 int coreIdx; 91 int coreIdx;
90 VirtProcr **masterVPs; 92 VirtProcr **masterVPs;
91 SchedSlot ***allSchedSlots; //ptr to array of ptrs 93 SchedSlot ***allSchedSlots; //ptr to array of ptrs
92 94
95
93 //Make the master env, which holds everything else 96 //Make the master env, which holds everything else
94 _VMSMasterEnv = malloc( sizeof(MasterEnv) ); 97 _VMSMasterEnv = malloc( sizeof(MasterEnv) );
98
99 //Very first thing put into the master env is the free-list, seeded
100 // with a massive initial chunk of memory.
101 //After this, all other mallocs are VMS__malloc.
102 _VMSMasterEnv->freeListHead = VMS_ext__create_free_list();
103
104 //===================== Only VMS__malloc after this ====================
95 masterEnv = _VMSMasterEnv; 105 masterEnv = _VMSMasterEnv;
96 //Need to set start pt here 'cause used by seed procr, which is created
97 // before the first core loop starts up. -- not sure how yet..
98 // masterEnv->coreLoopStartPt = ;
99 // masterEnv->coreLoopEndPt = ;
100 106
101 //Make a readyToAnimateQ for each core loop 107 //Make a readyToAnimateQ for each core loop
102 readyToAnimateQs = malloc( NUM_CORES * sizeof(SRSWQueueStruc *) ); 108 readyToAnimateQs = VMS__malloc( NUM_CORES * sizeof(SRSWQueueStruc *) );
103 masterVPs = malloc( NUM_CORES * sizeof(VirtProcr *) ); 109 masterVPs = VMS__malloc( NUM_CORES * sizeof(VirtProcr *) );
104 110
105 //One array for each core, 3 in array, core's masterVP scheds all 111 //One array for each core, 3 in array, core's masterVP scheds all
106 allSchedSlots = malloc( NUM_CORES * sizeof(SchedSlot *) ); 112 allSchedSlots = VMS__malloc( NUM_CORES * sizeof(SchedSlot *) );
107 113
114 _VMSMasterEnv->numProcrsCreated = 0; //used by create procr
108 for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 115 for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
109 { //running in main thread -- normal malloc inside makeSRSWQ 116 {
110 readyToAnimateQs[ coreIdx ] = makeSRSWQ(); 117 readyToAnimateQs[ coreIdx ] = makeSRSWQ();
111 118
112 //Q: should give masterVP core-specific info as its init data? 119 //Q: should give masterVP core-specific info as its init data?
113 masterVPs[ coreIdx ] = VMS_ext__create_procr( &masterLoop, masterEnv ); 120 masterVPs[ coreIdx ] = VMS__create_procr( &masterLoop, masterEnv );
114 masterVPs[ coreIdx ]->coreAnimatedBy = coreIdx; 121 masterVPs[ coreIdx ]->coreAnimatedBy = coreIdx;
115 allSchedSlots[ coreIdx ] = create_sched_slots(); //makes for one core 122 allSchedSlots[ coreIdx ] = create_sched_slots(); //makes for one core
116 _VMSMasterEnv->numMasterInARow[ coreIdx ] = FALSE; 123 _VMSMasterEnv->numMasterInARow[ coreIdx ] = 0;
117 } 124 }
118 _VMSMasterEnv->readyToAnimateQs = readyToAnimateQs; 125 _VMSMasterEnv->readyToAnimateQs = readyToAnimateQs;
119 _VMSMasterEnv->masterVPs = masterVPs; 126 _VMSMasterEnv->masterVPs = masterVPs;
120 _VMSMasterEnv->masterLock = UNLOCKED; 127 _VMSMasterEnv->masterLock = UNLOCKED;
121 _VMSMasterEnv->allSchedSlots = allSchedSlots; 128 _VMSMasterEnv->allSchedSlots = allSchedSlots;
122 _VMSMasterEnv->numProcrsCreated = 0;
123 129
124 130
125 //Aug 19, 2010: no longer need to place initial masterVP into queue 131 //Aug 19, 2010: no longer need to place initial masterVP into queue
126 // because coreLoop now controls -- animates its masterVP when no work 132 // because coreLoop now controls -- animates its masterVP when no work
127 133
128 _VMSMasterEnv->freeListHead = VMS__create_free_list();
129 _VMSMasterEnv->amtOfOutstandingMem = 0; //none allocated yet
130 134
131 //============================= MEASUREMENT STUFF ======================== 135 //============================= MEASUREMENT STUFF ========================
132 #ifdef STATS__TURN_ON_PROBES 136 #ifdef STATS__TURN_ON_PROBES
133 //creates intervalProbes array and sets pointer to it in masterEnv too
134 _VMSMasterEnv->dynIntervalProbesInfo = 137 _VMSMasterEnv->dynIntervalProbesInfo =
135 makeDynArrayOfSize( &(_VMSMasterEnv->intervalProbes), 20 ); 138 makePrivDynArrayOfSize( &(_VMSMasterEnv->intervalProbes), 200);
136 139
137 _VMSMasterEnv->probeNameHashTbl = makeHashTable( 1000, NULL ); 140 _VMSMasterEnv->probeNameHashTbl = makeHashTable( 1000, &VMS__free );
138 _VMSMasterEnv->masterCreateProbeID = 141
139 VMS_ext__record_time_point_into_new_probe( "masterCreateProbe" ); 142 //put creation time directly into master env, for fast retrieval
140 //Also put creation time directly into master env, for fast retrieval
141 struct timeval timeStamp; 143 struct timeval timeStamp;
142 gettimeofday( &(timeStamp), NULL); 144 gettimeofday( &(timeStamp), NULL);
143 _VMSMasterEnv->createPtInSecs = 145 _VMSMasterEnv->createPtInSecs =
144 timeStamp.tv_sec +(timeStamp.tv_usec/1000000.0); 146 timeStamp.tv_sec +(timeStamp.tv_usec/1000000.0);
145 #endif 147 #endif
150 SchedSlot ** 152 SchedSlot **
151 create_sched_slots() 153 create_sched_slots()
152 { SchedSlot **schedSlots; 154 { SchedSlot **schedSlots;
153 int i; 155 int i;
154 156
155 schedSlots = malloc( NUM_SCHED_SLOTS * sizeof(SchedSlot *) ); 157 schedSlots = VMS__malloc( NUM_SCHED_SLOTS * sizeof(SchedSlot *) );
156 158
157 for( i = 0; i < NUM_SCHED_SLOTS; i++ ) 159 for( i = 0; i < NUM_SCHED_SLOTS; i++ )
158 { 160 {
159 schedSlots[i] = malloc( sizeof(SchedSlot) ); 161 schedSlots[i] = VMS__malloc( sizeof(SchedSlot) );
160 162
161 //Set state to mean "handling requests done, slot needs filling" 163 //Set state to mean "handling requests done, slot needs filling"
162 schedSlots[i]->workIsDone = FALSE; 164 schedSlots[i]->workIsDone = FALSE;
163 schedSlots[i]->needsProcrAssigned = TRUE; 165 schedSlots[i]->needsProcrAssigned = TRUE;
164 } 166 }
169 void 171 void
170 freeSchedSlots( SchedSlot **schedSlots ) 172 freeSchedSlots( SchedSlot **schedSlots )
171 { int i; 173 { int i;
172 for( i = 0; i < NUM_SCHED_SLOTS; i++ ) 174 for( i = 0; i < NUM_SCHED_SLOTS; i++ )
173 { 175 {
174 free( schedSlots[i] ); 176 VMS__free( schedSlots[i] );
175 } 177 }
176 free( schedSlots ); 178 VMS__free( schedSlots );
177 } 179 }
178 180
179 181
180 void 182 void
181 create_the_coreLoop_OS_threads() 183 create_the_coreLoop_OS_threads()
189 // stuff before the coreLoops set off. 191 // stuff before the coreLoops set off.
190 _VMSMasterEnv->setupComplete = 0; 192 _VMSMasterEnv->setupComplete = 0;
191 193
192 //Make the threads that animate the core loops 194 //Make the threads that animate the core loops
193 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) 195 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ )
194 { coreLoopThdParams[coreIdx] = malloc( sizeof(ThdParams) ); 196 { coreLoopThdParams[coreIdx] = VMS__malloc( sizeof(ThdParams) );
195 coreLoopThdParams[coreIdx]->coreNum = coreIdx; 197 coreLoopThdParams[coreIdx]->coreNum = coreIdx;
196 198
197 retCode = 199 retCode =
198 pthread_create( &(coreLoopThdHandles[coreIdx]), 200 pthread_create( &(coreLoopThdHandles[coreIdx]),
199 thdAttrs, 201 thdAttrs,
261 create_procr_helper( VirtProcr *newPr, VirtProcrFnPtr fnPtr, 263 create_procr_helper( VirtProcr *newPr, VirtProcrFnPtr fnPtr,
262 void *initialData, char *stackLocs ) 264 void *initialData, char *stackLocs )
263 { 265 {
264 char *stackPtr; 266 char *stackPtr;
265 267
266 newPr->procrID = _VMSMasterEnv->numProcrsCreated++; 268 newPr->startOfStack = stackLocs;
267 newPr->nextInstrPt = fnPtr; 269 newPr->procrID = _VMSMasterEnv->numProcrsCreated++;
268 newPr->initialData = initialData; 270 newPr->nextInstrPt = fnPtr;
269 newPr->requests = NULL; 271 newPr->initialData = initialData;
270 newPr->schedSlot = NULL; 272 newPr->requests = NULL;
273 newPr->schedSlot = NULL;
271 274
272 //fnPtr takes two params -- void *initData & void *animProcr 275 //fnPtr takes two params -- void *initData & void *animProcr
273 //alloc stack locations, make stackPtr be the highest addr minus room 276 //alloc stack locations, make stackPtr be the highest addr minus room
274 // for 2 params + return addr. Return addr (NULL) is in loc pointed to 277 // for 2 params + return addr. Return addr (NULL) is in loc pointed to
275 // by stackPtr, initData at stackPtr + 4 bytes, animatingPr just above 278 // by stackPtr, initData at stackPtr + 4 bytes, animatingPr just above
283 286
284 //============================= MEASUREMENT STUFF ======================== 287 //============================= MEASUREMENT STUFF ========================
285 #ifdef STATS__TURN_ON_PROBES 288 #ifdef STATS__TURN_ON_PROBES
286 struct timeval timeStamp; 289 struct timeval timeStamp;
287 gettimeofday( &(timeStamp), NULL); 290 gettimeofday( &(timeStamp), NULL);
288 newPr->createPtInSecs = timeStamp.tv_sec +(timeStamp.tv_usec/1000000.0); 291 newPr->createPtInSecs = timeStamp.tv_sec +(timeStamp.tv_usec/1000000.0) -
292 _VMSMasterEnv->createPtInSecs;
289 #endif 293 #endif
290 //======================================================================== 294 //========================================================================
291 295
292 return newPr; 296 return newPr;
293 } 297 }
299 303
300 newPr = VMS__malloc( sizeof(VirtProcr) ); 304 newPr = VMS__malloc( sizeof(VirtProcr) );
301 stackLocs = VMS__malloc( VIRT_PROCR_STACK_SIZE ); 305 stackLocs = VMS__malloc( VIRT_PROCR_STACK_SIZE );
302 if( stackLocs == 0 ) 306 if( stackLocs == 0 )
303 { perror("VMS__malloc stack"); exit(1); } 307 { perror("VMS__malloc stack"); exit(1); }
304 newPr->startOfStack = stackLocs;
305 308
306 return create_procr_helper( newPr, fnPtr, initialData, stackLocs ); 309 return create_procr_helper( newPr, fnPtr, initialData, stackLocs );
307 } 310 }
308 311
309 /* "ext" designates that it's for use outside the VMS system -- should only 312 /* "ext" designates that it's for use outside the VMS system -- should only
317 320
318 newPr = malloc( sizeof(VirtProcr) ); 321 newPr = malloc( sizeof(VirtProcr) );
319 stackLocs = malloc( VIRT_PROCR_STACK_SIZE ); 322 stackLocs = malloc( VIRT_PROCR_STACK_SIZE );
320 if( stackLocs == 0 ) 323 if( stackLocs == 0 )
321 { perror("malloc stack"); exit(1); } 324 { perror("malloc stack"); exit(1); }
322 newPr->startOfStack = stackLocs;
323 325
324 return create_procr_helper( newPr, fnPtr, initialData, stackLocs ); 326 return create_procr_helper( newPr, fnPtr, initialData, stackLocs );
325 } 327 }
326 328
327 329
475 free( procrToDissipate ); 477 free( procrToDissipate );
476 } 478 }
477 479
478 480
479 481
480 /*This inserts the semantic-layer's request data into standard VMS carrier 482 /*This call's name indicates that request is malloc'd -- so req handler
481 * request data-struct is allocated on stack of this call & ptr to it sent 483 * has to free any extra requests tacked on before a send, using this.
482 * to plugin 484 *
485 * This inserts the semantic-layer's request data into standard VMS carrier
486 * request data-struct that is mallocd. The sem request doesn't need to
487 * be malloc'd if this is called inside the same call chain before the
488 * send of the last request is called.
489 *
490 *The request handler has to call VMS__free_VMSReq for any of these
483 */ 491 */
484 inline void 492 inline void
485 VMS__add_sem_request( void *semReqData, VirtProcr *callingPr ) 493 VMS__add_sem_request_in_mallocd_VMSReqst( void *semReqData,
486 { VMSReqst req; 494 VirtProcr *callingPr )
487 495 { VMSReqst *req;
488 req.reqType = semantic; 496
489 req.semReqData = semReqData; 497 req = VMS__malloc( sizeof(VMSReqst) );
490 req.nextReqst = callingPr->requests; 498 req->reqType = semantic;
491 callingPr->requests = &req; 499 req->semReqData = semReqData;
500 req->nextReqst = callingPr->requests;
501 callingPr->requests = req;
492 } 502 }
493 503
494 /*This inserts the semantic-layer's request data into standard VMS carrier 504 /*This inserts the semantic-layer's request data into standard VMS carrier
495 * request data-struct is allocated on stack of this call & ptr to it sent 505 * request data-struct is allocated on stack of this call & ptr to it sent
496 * to plugin 506 * to plugin
571 nameLen = strlen( semReq->nameStr ); 581 nameLen = strlen( semReq->nameStr );
572 newProbe->nameStr = VMS__malloc( nameLen ); 582 newProbe->nameStr = VMS__malloc( nameLen );
573 memcpy( newProbe->nameStr, semReq->nameStr, nameLen ); 583 memcpy( newProbe->nameStr, semReq->nameStr, nameLen );
574 newProbe->hist = NULL; 584 newProbe->hist = NULL;
575 newProbe->schedChoiceWasRecorded = FALSE; 585 newProbe->schedChoiceWasRecorded = FALSE;
586
587 //This runs in masterVP, so no race-condition worries
576 newProbe->probeID = 588 newProbe->probeID =
577 addToDynArray( newProbe, _VMSMasterEnv->dynIntervalProbesInfo ); 589 addToDynArray( newProbe, _VMSMasterEnv->dynIntervalProbesInfo );
578 590
579 requestingPr->dataReturnedFromReq = newProbe; 591 requestingPr->dataRetFromReq = newProbe;
580 592
581 (*resumePrFnPtr)( requestingPr, semEnv ); 593 (*resumePrFnPtr)( requestingPr, semEnv );
582 } 594 }
583 595
584 596
617 VMS__free( animatingPr->startOfStack ); 629 VMS__free( animatingPr->startOfStack );
618 VMS__free( animatingPr ); 630 VMS__free( animatingPr );
619 } 631 }
620 632
621 633
622 //TODO: re-architect so that have clean separation between request handler 634 //TODO: look at architecting cleanest separation between request handler
623 // and master loop, for dissipate, create, shutdown, and other non-semantic 635 // and master loop, for dissipate, create, shutdown, and other non-semantic
624 // requests. Issue is chain: one removes requests from AppVP, one dispatches 636 // requests. Issue is chain: one removes requests from AppVP, one dispatches
625 // on type of request, and one handles each type.. but some types require 637 // on type of request, and one handles each type.. but some types require
626 // action from both request handler and master loop -- maybe just give the 638 // action from both request handler and master loop -- maybe just give the
627 // request handler calls like: VMS__handle_X_request_type 639 // request handler calls like: VMS__handle_X_request_type
628 640
629 void
630 endOSThreadFn( void *initData, VirtProcr *animatingPr );
631 641
632 /*This is called by the semantic layer's request handler when it decides its 642 /*This is called by the semantic layer's request handler when it decides its
633 * time to shut down the VMS system. Calling this causes the core loop OS 643 * time to shut down the VMS system. Calling this causes the core loop OS
634 * threads to exit, which unblocks the entry-point function that started up 644 * threads to exit, which unblocks the entry-point function that started up
635 * VMS, and allows it to grab the result and return to the original single- 645 * VMS, and allows it to grab the result and return to the original single-
639 * and-wait function has to free a bunch of stuff after it detects the 649 * and-wait function has to free a bunch of stuff after it detects the
640 * threads have all died: the masterEnv, the thread-related locations, 650 * threads have all died: the masterEnv, the thread-related locations,
641 * masterVP any AppVPs that might still be allocated and sitting in the 651 * masterVP any AppVPs that might still be allocated and sitting in the
642 * semantic environment, or have been orphaned in the _VMSWorkQ. 652 * semantic environment, or have been orphaned in the _VMSWorkQ.
643 * 653 *
644 *NOTE: the semantic plug-in is expected to use VMS__malloc_to to get all the 654 *NOTE: the semantic plug-in is expected to use VMS__malloc to get all the
645 * locations it needs, and give ownership to masterVP. Then, they will be 655 * locations it needs, and give ownership to masterVP. Then, they will be
646 * automatically freed when the masterVP is dissipated. (This happens after 656 * automatically freed.
647 * the core loop threads have all exited)
648 * 657 *
649 *In here,create one core-loop shut-down processor for each core loop and put 658 *In here,create one core-loop shut-down processor for each core loop and put
650 * them all directly into the readyToAnimateQ. 659 * them all directly into the readyToAnimateQ.
651 *Note, this function can ONLY be called after the semantic environment no 660 *Note, this function can ONLY be called after the semantic environment no
652 * longer cares if AppVPs get animated after the point this is called. In 661 * longer cares if AppVPs get animated after the point this is called. In
653 * other words, this can be used as an abort, or else it should only be 662 * other words, this can be used as an abort, or else it should only be
654 * called when all AppVPs have finished dissipate requests -- only at that 663 * called when all AppVPs have finished dissipate requests -- only at that
655 * point is it sure that all results have completed. 664 * point is it sure that all results have completed.
656 */ 665 */
657 void 666 void
658 VMS__handle_shutdown_reqst( void *dummy, VirtProcr *animatingPr ) 667 VMS__shutdown()
659 { int coreIdx; 668 { int coreIdx;
660 VirtProcr *shutDownPr; 669 VirtProcr *shutDownPr;
661 670
662 //create the shutdown processors, one for each core loop -- put them 671 //create the shutdown processors, one for each core loop -- put them
663 // directly into the Q -- each core will die when gets one 672 // directly into the Q -- each core will die when gets one
701 /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi","%esi" \ 710 /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi","%esi" \
702 ); 711 );
703 } 712 }
704 713
705 714
706 /*This is called after the threads have shut down and control has returned 715 /*This is called from the startup & shutdown
707 * to the semantic layer, in the entry point function in the main thread. 716 */
708 * It has to free anything allocated during VMS_init, and any other alloc'd 717 void
709 * locations that might be left over. 718 VMS__cleanup_at_end_of_shutdown()
710 */
711 void
712 VMS__cleanup_after_shutdown()
713 { 719 {
714 SRSWQueueStruc **readyToAnimateQs; 720 SRSWQueueStruc **readyToAnimateQs;
715 int coreIdx; 721 int coreIdx;
716 VirtProcr **masterVPs; 722 VirtProcr **masterVPs;
717 SchedSlot ***allSchedSlots; //ptr to array of ptrs 723 SchedSlot ***allSchedSlots; //ptr to array of ptrs
718 724
725 //All the environment data has been allocated with VMS__malloc, so just
726 // free its internal big-chunk and all inside it disappear.
727 /*
719 readyToAnimateQs = _VMSMasterEnv->readyToAnimateQs; 728 readyToAnimateQs = _VMSMasterEnv->readyToAnimateQs;
720 masterVPs = _VMSMasterEnv->masterVPs; 729 masterVPs = _VMSMasterEnv->masterVPs;
721 allSchedSlots = _VMSMasterEnv->allSchedSlots; 730 allSchedSlots = _VMSMasterEnv->allSchedSlots;
722 731
723 for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 732 for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
724 { 733 {
725 freeSRSWQ( readyToAnimateQs[ coreIdx ] ); 734 freeSRSWQ( readyToAnimateQs[ coreIdx ] );
726 //master VPs were created external to VMS, so use external free 735 //master VPs were created external to VMS, so use external free
727 VMS_ext__dissipate_procr( masterVPs[ coreIdx ] ); 736 VMS__dissipate_procr( masterVPs[ coreIdx ] );
728 737
729 freeSchedSlots( allSchedSlots[ coreIdx ] ); 738 freeSchedSlots( allSchedSlots[ coreIdx ] );
730 } 739 }
731 740
732 free( _VMSMasterEnv->readyToAnimateQs ); 741 VMS__free( _VMSMasterEnv->readyToAnimateQs );
733 free( _VMSMasterEnv->masterVPs ); 742 VMS__free( _VMSMasterEnv->masterVPs );
734 free( _VMSMasterEnv->allSchedSlots ); 743 VMS__free( _VMSMasterEnv->allSchedSlots );
735 744
736 VMS_ext__free_free_list( _VMSMasterEnv->freeListHead );
737
738 //============================= MEASUREMENT STUFF ======================== 745 //============================= MEASUREMENT STUFF ========================
739 #ifdef STATS__TURN_ON_PROBES 746 #ifdef STATS__TURN_ON_PROBES
740 freeDynArrayDeep( _VMSMasterEnv->dynIntervalProbesInfo, &free ); 747 freeDynArrayDeep( _VMSMasterEnv->dynIntervalProbesInfo, &VMS__free_probe);
741 #endif 748 #endif
742 //======================================================================== 749 //========================================================================
743 750 */
744 free( _VMSMasterEnv ); 751 //These are the only two that use system free
745 } 752 VMS_ext__free_free_list( _VMSMasterEnv->freeListHead );
746 753 free( (void *)_VMSMasterEnv );
754 }
755
756
757 //================================
758
759
760 /*Later, improve this -- for now, just exits the application after printing
761 * the error message.
762 */
763 void
764 VMS__throw_exception( char *msgStr, VirtProcr *reqstPr, VMSExcp *excpData )
765 {
766 printf(msgStr);
767 fflush(stdin);
768 exit(1);
769 }
770
771
772