Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VSs_impls > VSs__MC_shared_impl
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 } |
