comparison VSs.c @ 3:468b8638ff92

Works -- first working version, includes slave pruning and shutdown detection
author Sean Halle <seanhalle@yahoo.com>
date Wed, 06 Jun 2012 17:55:36 -0700
parents f2ed1c379fe7
children 13af59ed7ea5
comparison
equal deleted inserted replaced
1:82dc3af3539d 2:f98d42cee3ff
10 10
11 #include "Queue_impl/PrivateQueue.h" 11 #include "Queue_impl/PrivateQueue.h"
12 #include "Hash_impl/PrivateHash.h" 12 #include "Hash_impl/PrivateHash.h"
13 13
14 #include "VSs.h" 14 #include "VSs.h"
15 #include "VSs_Counter_Recording.h" 15 #include "Measurement/VSs_Counter_Recording.h"
16 16
17 //========================================================================== 17 //==========================================================================
18 18
19 void 19 void
20 VSs__init(); 20 VSs__init();
72 * any of the data reachable from initData passed in to here 72 * any of the data reachable from initData passed in to here
73 */ 73 */
74 void 74 void
75 VSs__create_seed_slave_and_do_work( TopLevelFnPtr fnPtr, void *initData ) 75 VSs__create_seed_slave_and_do_work( TopLevelFnPtr fnPtr, void *initData )
76 { VSsSemEnv *semEnv; 76 { VSsSemEnv *semEnv;
77 SlaveVP *seedPr; 77 SlaveVP *seedSlv;
78 78
79 VSs__init(); //normal multi-thd 79 VSs__init(); //normal multi-thd
80 80
81 semEnv = _VMSMasterEnv->semanticEnv; 81 semEnv = _VMSMasterEnv->semanticEnv;
82 82
83 //VSs starts with one processor, which is put into initial environ, 83 //VSs starts with one processor, which is put into initial environ,
84 // and which then calls create() to create more, thereby expanding work 84 // and which then calls create() to create more, thereby expanding work
85 seedPr = VSs__create_slave_helper( fnPtr, initData, 85 seedSlv = VSs__create_slave_helper( fnPtr, initData,
86 semEnv, semEnv->nextCoreToGetNewPr++ ); 86 semEnv, semEnv->nextCoreToGetNewSlv++ );
87 87
88 resume_slaveVP( seedPr, semEnv ); 88 //seedVP doesn't do tasks
89 ((VSsSemData *)seedSlv->semanticData)->needsTaskAssigned = FALSE;
90
91 resume_slaveVP( seedSlv, semEnv );
89 92
90 VMS_SS__start_the_work_then_wait_until_done(); //normal multi-thd 93 VMS_SS__start_the_work_then_wait_until_done(); //normal multi-thd
91 94
92 VSs__cleanup_after_shutdown(); 95 VSs__cleanup_after_shutdown();
93 } 96 }
182 _VMSMasterEnv->semanticEnv = semanticEnv; 185 _VMSMasterEnv->semanticEnv = semanticEnv;
183 186
184 #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS 187 #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS
185 VSs__init_counter_data_structs(); 188 VSs__init_counter_data_structs();
186 #endif 189 #endif
190
187 semanticEnv->shutdownInitiated = FALSE; 191 semanticEnv->shutdownInitiated = FALSE;
188 for(i=0;i<NUM_CORES;++i){ 192 semanticEnv->coreIsDone = VMS_int__malloc( NUM_CORES * sizeof( bool32 ) );
189 for(j=0;j<NUM_ANIM_SLOTS;++j){ 193 for( i = 0; i < NUM_CORES; ++i )
190 semanticEnv->idlePr[i][j] = VMS_int__create_slaveVP(&idle_fn,NULL); 194 { semanticEnv->coreIsDone[i] = FALSE;
191 semanticEnv->idlePr[i][j]->coreAnimatedBy = i; 195 for( j = 0; j < NUM_ANIM_SLOTS; ++j )
196 {
197 semanticEnv->idleSlv[i][j] = VMS_int__create_slaveVP(&idle_fn,NULL);
198 semanticEnv->idleSlv[i][j]->coreAnimatedBy = i;
192 } 199 }
193 } 200 }
194 201
195 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 202 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
196 semanticEnv->unitList = makeListOfArrays(sizeof(Unit),128); 203 semanticEnv->unitList = makeListOfArrays(sizeof(Unit),128);
197 semanticEnv->ctlDependenciesList = makeListOfArrays(sizeof(Dependency),128); 204 semanticEnv->ctlDependenciesList = makeListOfArrays(sizeof(Dependency),128);
198 semanticEnv->commDependenciesList = makeListOfArrays(sizeof(Dependency),128); 205 semanticEnv->commDependenciesList = makeListOfArrays(sizeof(Dependency),128);
201 208
202 semanticEnv->hwArcs = makeListOfArrays(sizeof(Dependency),128); 209 semanticEnv->hwArcs = makeListOfArrays(sizeof(Dependency),128);
203 memset(semanticEnv->last_in_slot,0,sizeof(NUM_CORES * NUM_ANIM_SLOTS * sizeof(Unit))); 210 memset(semanticEnv->last_in_slot,0,sizeof(NUM_CORES * NUM_ANIM_SLOTS * sizeof(Unit)));
204 #endif 211 #endif
205 212
206 //create the ready queue, hash tables used for pairing send to receive 213 //create the ready queue, hash tables used for matching and so forth
207 // and so forth
208 //TODO: add hash tables for pairing sends with receives, and
209 // initialize the data ownership system
210 readyVPQs = VMS_int__malloc( NUM_CORES * sizeof(PrivQueueStruc *) ); 214 readyVPQs = VMS_int__malloc( NUM_CORES * sizeof(PrivQueueStruc *) );
211 215
212 for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 216 for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
213 { 217 {
214 readyVPQs[ coreIdx ] = makeVMSQ(); 218 readyVPQs[ coreIdx ] = makeVMSQ();
215 } 219 }
216 220
217 semanticEnv->readyVPQs = readyVPQs; 221 semanticEnv->readyVPQs = readyVPQs;
218 222
219 semanticEnv->nextCoreToGetNewPr = 0; 223 semanticEnv->taskReadyQ = makeVMSQ();
224
225 semanticEnv->nextCoreToGetNewSlv = 0;
220 semanticEnv->numSlaveVP = 0; 226 semanticEnv->numSlaveVP = 0;
221 227
222 semanticEnv->argPtrHashTbl = makeHashTable( 1<<16, &VMS_int__free );//start big 228 semanticEnv->argPtrHashTbl = makeHashTable32( 16, &VMS_int__free );
223 229
224 //TODO: bug -- turn these arrays into dyn arrays to eliminate limit 230 //TODO: bug -- turn these arrays into dyn arrays to eliminate limit
225 //semanticEnv->singletonHasBeenExecutedFlags = makeDynArrayInfo( ); 231 //semanticEnv->singletonHasBeenExecutedFlags = makeDynArrayInfo( );
226 //semanticEnv->transactionStrucs = makeDynArrayInfo( ); 232 //semanticEnv->transactionStrucs = makeDynArrayInfo( );
227 for( i = 0; i < NUM_STRUCS_IN_SEM_ENV; i++ ) 233 for( i = 0; i < NUM_STRUCS_IN_SEM_ENV; i++ )
374 380
375 /* 381 /*
376 */ 382 */
377 SlaveVP * 383 SlaveVP *
378 VSs__create_slave_with( TopLevelFnPtr fnPtr, void *initData, 384 VSs__create_slave_with( TopLevelFnPtr fnPtr, void *initData,
379 SlaveVP *creatingPr ) 385 SlaveVP *creatingSlv )
380 { VSsSemReq reqData; 386 { VSsSemReq reqData;
381 387
382 //the semantic request data is on the stack and disappears when this 388 //the semantic request data is on the stack and disappears when this
383 // call returns -- it's guaranteed to remain in the VP's stack for as 389 // call returns -- it's guaranteed to remain in the VP's stack for as
384 // long as the VP is suspended. 390 // long as the VP is suspended.
385 reqData.reqType = 0; //know type because in a VMS create req 391 reqData.reqType = 0; //know type because in a VMS create req
386 reqData.coreToAssignOnto = -1; //means round-robin assign 392 reqData.coreToAssignOnto = -1; //means round-robin assign
387 reqData.fnPtr = fnPtr; 393 reqData.fnPtr = fnPtr;
388 reqData.initData = initData; 394 reqData.initData = initData;
389 reqData.callingSlv = creatingPr; 395 reqData.callingSlv = creatingSlv;
390 396
391 VMS_WL__send_create_slaveVP_req( &reqData, creatingPr ); 397 VMS_WL__send_create_slaveVP_req( &reqData, creatingSlv );
392 398
393 return creatingPr->dataRetFromReq; 399 return creatingSlv->dataRetFromReq;
394 } 400 }
395 401
396 SlaveVP * 402 SlaveVP *
397 VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData, 403 VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData,
398 SlaveVP *creatingPr, int32 coreToAssignOnto ) 404 SlaveVP *creatingSlv, int32 coreToAssignOnto )
399 { VSsSemReq reqData; 405 { VSsSemReq reqData;
400 406
401 //the semantic request data is on the stack and disappears when this 407 //the semantic request data is on the stack and disappears when this
402 // call returns -- it's guaranteed to remain in the VP's stack for as 408 // call returns -- it's guaranteed to remain in the VP's stack for as
403 // long as the VP is suspended. 409 // long as the VP is suspended.
404 reqData.reqType = create_slave; 410 reqData.reqType = create_slave_w_aff; //not used, May 2012
405 reqData.coreToAssignOnto = coreToAssignOnto; 411 reqData.coreToAssignOnto = coreToAssignOnto;
406 reqData.fnPtr = fnPtr; 412 reqData.fnPtr = fnPtr;
407 reqData.initData = initData; 413 reqData.initData = initData;
408 reqData.callingSlv = creatingPr; 414 reqData.callingSlv = creatingSlv;
409 415
410 VMS_WL__send_create_slaveVP_req( &reqData, creatingPr ); 416 VMS_WL__send_create_slaveVP_req( &reqData, creatingSlv );
411 417
412 return creatingPr->dataRetFromReq; 418 return creatingSlv->dataRetFromReq;
413 } 419 }
414 420
415 421
416 void 422 void
417 VSs__dissipate_slave( SlaveVP *slaveToDissipate ) 423 VSs__dissipate_slave( SlaveVP *slaveToDissipate )
436 reqData.taskType = taskType; 442 reqData.taskType = taskType;
437 reqData.args = args; 443 reqData.args = args;
438 444
439 445
440 VMS_WL__send_sem_request( &reqData, animSlv ); 446 VMS_WL__send_sem_request( &reqData, animSlv );
441 return animSlv->dataRetFromReq; 447 return (int32)animSlv->dataRetFromReq;
442 } 448 }
443 449
444 /*NOTE: if want, don't need to send the animating SlaveVP around.. 450 /*NOTE: if want, don't need to send the animating SlaveVP around..
445 * instead, can make a single slave per core, and coreCtrlr looks up the 451 * instead, can make a single slave per core, and coreCtrlr looks up the
446 * slave from having the core number. 452 * slave from having the core number.
486 492
487 /*Fn singleton uses ID as index into array of singleton structs held in the 493 /*Fn singleton uses ID as index into array of singleton structs held in the
488 * semantic environment. 494 * semantic environment.
489 */ 495 */
490 void 496 void
491 VSs__start_fn_singleton( int32 singletonID, SlaveVP *animPr ) 497 VSs__start_fn_singleton( int32 singletonID, SlaveVP *animSlv )
492 { 498 {
493 VSsSemReq reqData; 499 VSsSemReq reqData;
494 500
495 // 501 //
496 reqData.reqType = singleton_fn_start; 502 reqData.reqType = singleton_fn_start;
497 reqData.singletonID = singletonID; 503 reqData.singletonID = singletonID;
498 504
499 VMS_WL__send_sem_request( &reqData, animPr ); 505 VMS_WL__send_sem_request( &reqData, animSlv );
500 if( animPr->dataRetFromReq ) //will be 0 or addr of label in end singleton 506 if( animSlv->dataRetFromReq ) //will be 0 or addr of label in end singleton
501 { 507 {
502 VSsSemEnv *semEnv = VMS_int__give_sem_env_for( animPr ); 508 VSsSemEnv *semEnv = VMS_int__give_sem_env_for( animSlv );
503 asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID])); 509 asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID]));
504 } 510 }
505 } 511 }
506 512
507 /*Data singleton hands addr of loc holding a pointer to a singleton struct. 513 /*Data singleton hands addr of loc holding a pointer to a singleton struct.
508 * The start_data_singleton makes the structure and puts its addr into the 514 * The start_data_singleton makes the structure and puts its addr into the
509 * location. 515 * location.
510 */ 516 */
511 void 517 void
512 VSs__start_data_singleton( VSsSingleton **singletonAddr, SlaveVP *animPr ) 518 VSs__start_data_singleton( VSsSingleton **singletonAddr, SlaveVP *animSlv )
513 { 519 {
514 VSsSemReq reqData; 520 VSsSemReq reqData;
515 521
516 if( *singletonAddr && (*singletonAddr)->hasFinished ) 522 if( *singletonAddr && (*singletonAddr)->hasFinished )
517 goto JmpToEndSingleton; 523 goto JmpToEndSingleton;
518 524
519 reqData.reqType = singleton_data_start; 525 reqData.reqType = singleton_data_start;
520 reqData.singletonPtrAddr = singletonAddr; 526 reqData.singletonPtrAddr = singletonAddr;
521 527
522 VMS_WL__send_sem_request( &reqData, animPr ); 528 VMS_WL__send_sem_request( &reqData, animSlv );
523 if( animPr->dataRetFromReq ) //either 0 or end singleton's return addr 529 if( animSlv->dataRetFromReq ) //either 0 or end singleton's return addr
524 { //Assembly code changes the return addr on the stack to the one 530 { //Assembly code changes the return addr on the stack to the one
525 // saved into the singleton by the end-singleton-fn 531 // saved into the singleton by the end-singleton-fn
526 //The return addr is at 0x4(%%ebp) 532 //The return addr is at 0x4(%%ebp)
527 JmpToEndSingleton: 533 JmpToEndSingleton:
528 asm_write_ret_from_singleton(*singletonAddr); 534 asm_write_ret_from_singleton(*singletonAddr);
536 * 542 *
537 *Note, this call cannot be inlined because the instr addr at the label 543 *Note, this call cannot be inlined because the instr addr at the label
538 * inside is shared by all invocations of a given singleton ID. 544 * inside is shared by all invocations of a given singleton ID.
539 */ 545 */
540 void 546 void
541 VSs__end_fn_singleton( int32 singletonID, SlaveVP *animPr ) 547 VSs__end_fn_singleton( int32 singletonID, SlaveVP *animSlv )
542 { 548 {
543 VSsSemReq reqData; 549 VSsSemReq reqData;
544 550
545 //don't need this addr until after at least one singleton has reached 551 //don't need this addr until after at least one singleton has reached
546 // this function 552 // this function
547 VSsSemEnv *semEnv = VMS_int__give_sem_env_for( animPr ); 553 VSsSemEnv *semEnv = VMS_int__give_sem_env_for( animSlv );
548 asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID])); 554 asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID]));
549 555
550 reqData.reqType = singleton_fn_end; 556 reqData.reqType = singleton_fn_end;
551 reqData.singletonID = singletonID; 557 reqData.singletonID = singletonID;
552 558
553 VMS_WL__send_sem_request( &reqData, animPr ); 559 VMS_WL__send_sem_request( &reqData, animSlv );
554 560
555 EndSingletonInstrAddr: 561 EndSingletonInstrAddr:
556 return; 562 return;
557 } 563 }
558 564
559 void 565 void
560 VSs__end_data_singleton( VSsSingleton **singletonPtrAddr, SlaveVP *animPr ) 566 VSs__end_data_singleton( VSsSingleton **singletonPtrAddr, SlaveVP *animSlv )
561 { 567 {
562 VSsSemReq reqData; 568 VSsSemReq reqData;
563 569
564 //don't need this addr until after singleton struct has reached 570 //don't need this addr until after singleton struct has reached
565 // this function for first time 571 // this function for first time
573 asm_save_ret_to_singleton(*singletonPtrAddr); 579 asm_save_ret_to_singleton(*singletonPtrAddr);
574 580
575 reqData.reqType = singleton_data_end; 581 reqData.reqType = singleton_data_end;
576 reqData.singletonPtrAddr = singletonPtrAddr; 582 reqData.singletonPtrAddr = singletonPtrAddr;
577 583
578 VMS_WL__send_sem_request( &reqData, animPr ); 584 VMS_WL__send_sem_request( &reqData, animSlv );
579 } 585 }
580 586
581 /*This executes the function in the masterVP, so it executes in isolation 587 /*This executes the function in the masterVP, so it executes in isolation
582 * from any other copies -- only one copy of the function can ever execute 588 * from any other copies -- only one copy of the function can ever execute
583 * at a time. 589 * at a time.
588 * isolation, use transaction-start and transaction-end, which run the code 594 * isolation, use transaction-start and transaction-end, which run the code
589 * between as work-code. 595 * between as work-code.
590 */ 596 */
591 void 597 void
592 VSs__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster, 598 VSs__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
593 void *data, SlaveVP *animPr ) 599 void *data, SlaveVP *animSlv )
594 { 600 {
595 VSsSemReq reqData; 601 VSsSemReq reqData;
596 602
597 // 603 //
598 reqData.reqType = atomic; 604 reqData.reqType = atomic;
599 reqData.fnToExecInMaster = ptrToFnToExecInMaster; 605 reqData.fnToExecInMaster = ptrToFnToExecInMaster;
600 reqData.dataForFn = data; 606 reqData.dataForFn = data;
601 607
602 VMS_WL__send_sem_request( &reqData, animPr ); 608 VMS_WL__send_sem_request( &reqData, animSlv );
603 } 609 }
604 610
605 611
606 /*This suspends to the master. 612 /*This suspends to the master.
607 *First, it looks at the VP's data, to see the highest transactionID that VP 613 *First, it looks at the VP's data, to see the highest transactionID that VP
615 * into queue in the struct. (At some point a holder will request 621 * into queue in the struct. (At some point a holder will request
616 * end-transaction, which will take this VP from the queue and resume it.) 622 * end-transaction, which will take this VP from the queue and resume it.)
617 *If NULL, then write requesting into the field and resume. 623 *If NULL, then write requesting into the field and resume.
618 */ 624 */
619 void 625 void
620 VSs__start_transaction( int32 transactionID, SlaveVP *animPr ) 626 VSs__start_transaction( int32 transactionID, SlaveVP *animSlv )
621 { 627 {
622 VSsSemReq reqData; 628 VSsSemReq reqData;
623 629
624 // 630 //
625 reqData.callingSlv = animPr; 631 reqData.callingSlv = animSlv;
626 reqData.reqType = trans_start; 632 reqData.reqType = trans_start;
627 reqData.transID = transactionID; 633 reqData.transID = transactionID;
628 634
629 VMS_WL__send_sem_request( &reqData, animPr ); 635 VMS_WL__send_sem_request( &reqData, animSlv );
630 } 636 }
631 637
632 /*This suspends to the master, then uses transactionID as index into an 638 /*This suspends to the master, then uses transactionID as index into an
633 * array of transaction structures. 639 * array of transaction structures.
634 *It looks at VP_currently_executing to be sure it's same as requesting VP. 640 *It looks at VP_currently_executing to be sure it's same as requesting VP.
637 *If it's empty, it sets VP_currently_executing field to NULL and resumes. 643 *If it's empty, it sets VP_currently_executing field to NULL and resumes.
638 *If something in, gets it, sets VP_currently_executing to that VP, then 644 *If something in, gets it, sets VP_currently_executing to that VP, then
639 * resumes both. 645 * resumes both.
640 */ 646 */
641 void 647 void
642 VSs__end_transaction( int32 transactionID, SlaveVP *animPr ) 648 VSs__end_transaction( int32 transactionID, SlaveVP *animSlv )
643 { 649 {
644 VSsSemReq reqData; 650 VSsSemReq reqData;
645 651
646 // 652 //
647 reqData.callingSlv = animPr; 653 reqData.callingSlv = animSlv;
648 reqData.reqType = trans_end; 654 reqData.reqType = trans_end;
649 reqData.transID = transactionID; 655 reqData.transID = transactionID;
650 656
651 VMS_WL__send_sem_request( &reqData, animPr ); 657 VMS_WL__send_sem_request( &reqData, animSlv );
652 } 658 }