Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
comparison AnimationMaster.c @ 267:608833ae2c5d
Checkpoint -- about to clean up AnimationMaster, deleting a bunch of stuff
| author | Sean Halle <seanhalle@yahoo.com> |
|---|---|
| date | Sun, 04 Nov 2012 18:39:28 -0800 |
| parents | a5fa1e087c7e |
| children | e5bd470b562b |
comparison
equal
deleted
inserted
replaced
| 11:cfb14d4ffc6d | 12:d13c619ea73b |
|---|---|
| 11 | 11 |
| 12 #include "PR.h" | 12 #include "PR.h" |
| 13 #include "VSs_impl/VSs.h" | 13 #include "VSs_impl/VSs.h" |
| 14 | 14 |
| 15 inline void | 15 inline void |
| 16 replaceWithNewSlotSlv( SlaveVP *requestingSlv, PRProcessEnv *processEnv ); | 16 replaceWithNewSlotSlv( SlaveVP *slave ); |
| 17 | 17 |
| 18 | 18 |
| 19 /*The animationMaster embodies most of the animator of the language. The | 19 /*The animationMaster embodies most of the animator of the language. The |
| 20 * animator is what emodies the behavior of language constructs. | 20 * animator is what emodies the behavior of language constructs. |
| 21 * As such, it is the animationMaster, in combination with the plugin | 21 * As such, it is the animationMaster, in combination with the plugin |
| 187 | 187 |
| 188 //Check if newly-done slave in slot, which will need request handled | 188 //Check if newly-done slave in slot, which will need request handled |
| 189 if( currSlot->workIsDone ) | 189 if( currSlot->workIsDone ) |
| 190 { | 190 { |
| 191 currSlot->workIsDone = FALSE; | 191 currSlot->workIsDone = FALSE; |
| 192 currSlot->needsSlaveAssigned = TRUE; | 192 currSlot->needsWorkAssigned = TRUE; |
| 193 | 193 |
| 194 HOLISTIC__Record_AppResponder_start; | 194 HOLISTIC__Record_AppResponder_start; |
| 195 MEAS__startReqHdlr; | 195 MEAS__startReqHdlr; |
| 196 | 196 |
| 197 currSlot->workIsDone = FALSE; | 197 currSlot->workIsDone = FALSE; |
| 198 currSlot->needsSlaveAssigned = TRUE; | 198 currSlot->needsWorkAssigned = TRUE; |
| 199 SlaveVP *currSlave = currSlot->slaveAssignedToSlot; | 199 SlaveVP *currSlave = currSlot->slaveAssignedToSlot; |
| 200 | 200 |
| 201 justAddedReqHdlrChg(); | 201 justAddedReqHdlrChg(); |
| 202 //handle the request, either by PR or by the language | 202 //handle the request, either by PR or by the language |
| 203 if( currSlave->requests->reqType != LangReq ) | 203 if( currSlave->requests->reqType != LangReq ) |
| 221 | 221 |
| 222 HOLISTIC__Record_AppResponder_end; | 222 HOLISTIC__Record_AppResponder_end; |
| 223 MEAS__endReqHdlr; | 223 MEAS__endReqHdlr; |
| 224 } | 224 } |
| 225 //If slot empty, hand to Assigner to fill with a slave | 225 //If slot empty, hand to Assigner to fill with a slave |
| 226 if( currSlot->needsSlaveAssigned ) | 226 if( currSlot->needsWorkAssigned ) |
| 227 { //Call plugin's Assigner to give slot a new slave | 227 { //Call plugin's Assigner to give slot a new slave |
| 228 HOLISTIC__Record_Assigner_start; | 228 HOLISTIC__Record_Assigner_start; |
| 229 assignedSlaveVP = | 229 assignedSlaveVP = |
| 230 (*slaveAssigner)( semanticEnv, currSlot ); | 230 (*slaveAssigner)( semanticEnv, currSlot ); |
| 231 | 231 |
| 232 //put the chosen slave into slot, and adjust flags and state | 232 //put the chosen slave into slot, and adjust flags and state |
| 233 if( assignedSlaveVP != NULL ) | 233 if( assignedSlaveVP != NULL ) |
| 234 { currSlot->slaveAssignedToSlot = assignedSlaveVP; | 234 { currSlot->slaveAssignedToSlot = assignedSlaveVP; |
| 235 assignedSlaveVP->animSlotAssignedTo = currSlot; | 235 assignedSlaveVP->animSlotAssignedTo = currSlot; |
| 236 currSlot->needsSlaveAssigned = FALSE; | 236 currSlot->needsWorkAssigned = FALSE; |
| 237 numSlotsFilled += 1; | 237 numSlotsFilled += 1; |
| 238 | 238 |
| 239 HOLISTIC__Record_Assigner_end; | 239 HOLISTIC__Record_Assigner_end; |
| 240 } | 240 } |
| 241 } | 241 } |
| 268 int32 thisCoresIdx; | 268 int32 thisCoresIdx; |
| 269 | 269 |
| 270 //#ifdef MODE__MULTI_LANG | 270 //#ifdef MODE__MULTI_LANG |
| 271 SlaveVP *slave; | 271 SlaveVP *slave; |
| 272 PRProcess *process; | 272 PRProcess *process; |
| 273 PRConstrEnvHolder *constrEnvHolder; | |
| 274 int32 langMagicNumber; | 273 int32 langMagicNumber; |
| 275 //#endif | 274 //#endif |
| 276 | 275 |
| 277 //======================== Initializations ======================== | 276 //======================== Initializations ======================== |
| 278 masterEnv = (MasterEnv*)_PRTopEnv; | 277 masterEnv = (MasterEnv*)_PRTopEnv; |
| 316 | 315 |
| 317 //process the request made by the slave (held inside slave struc) | 316 //process the request made by the slave (held inside slave struc) |
| 318 slave = currSlot->slaveAssignedToSlot; | 317 slave = currSlot->slaveAssignedToSlot; |
| 319 | 318 |
| 320 //check if the completed work was a task.. | 319 //check if the completed work was a task.. |
| 321 if( slave->taskMetaInfo->isATask ) | 320 if( slave->metaTask->isATask ) |
| 322 { | 321 { |
| 323 if( slave->reqst->type == TaskEnd ) | 322 if( slave->request->type == TaskEnd ) |
| 324 { //do task end handler, which is registered separately | 323 { //do task end handler, which is registered separately |
| 325 //note, end hdlr may use semantic data from reqst.. | 324 //note, end hdlr may use semantic data from reqst.. |
| 326 //#ifdef MODE__MULTI_LANG | 325 //#ifdef MODE__MULTI_LANG |
| 327 //get end-task handler | 326 //get end-task handler |
| 328 //taskEndHandler = lookup( slave->reqst->langMagicNumber, processEnv ); | 327 //taskEndHandler = lookup( slave->reqst->langMagicNumber, processEnv ); |
| 329 taskEndHandler = slave->taskMetaInfo->endTaskHandler; | 328 taskEndHandler = slave->metaTask->endTaskHandler; |
| 330 //#endif | 329 //#endif |
| 331 (*taskEndHandler)( slave, semanticEnv ); | 330 (*taskEndHandler)( slave, semanticEnv ); |
| 332 | 331 |
| 333 goto AssignWork; | 332 goto AssignWork; |
| 334 } | 333 } |
| 351 goto AssignWork; | 350 goto AssignWork; |
| 352 } | 351 } |
| 353 } //if has suspended slave that needs handling | 352 } //if has suspended slave that needs handling |
| 354 | 353 |
| 355 //if slot empty, hand to Assigner to fill with a slave | 354 //if slot empty, hand to Assigner to fill with a slave |
| 356 if( currSlot->needsSlaveAssigned ) | 355 if( currSlot->needsWorkAssigned ) |
| 357 { //Call plugin's Assigner to give slot a new slave | 356 { //Call plugin's Assigner to give slot a new slave |
| 358 HOLISTIC__Record_Assigner_start; | 357 HOLISTIC__Record_Assigner_start; |
| 359 | 358 |
| 360 AssignWork: | 359 AssignWork: |
| 361 | 360 |
| 363 | 362 |
| 364 //put the chosen slave into slot, and adjust flags and state | 363 //put the chosen slave into slot, and adjust flags and state |
| 365 if( assignedSlaveVP != NULL ) | 364 if( assignedSlaveVP != NULL ) |
| 366 { currSlot->slaveAssignedToSlot = assignedSlaveVP; | 365 { currSlot->slaveAssignedToSlot = assignedSlaveVP; |
| 367 assignedSlaveVP->animSlotAssignedTo = currSlot; | 366 assignedSlaveVP->animSlotAssignedTo = currSlot; |
| 368 currSlot->needsSlaveAssigned = FALSE; | 367 currSlot->needsWorkAssigned = FALSE; |
| 369 numSlotsFilled += 1; | 368 numSlotsFilled += 1; |
| 370 } | 369 } |
| 371 else | 370 else |
| 372 { | 371 { |
| 373 currSlot->needsSlaveAssigned = TRUE; //local write | 372 currSlot->needsWorkAssigned = TRUE; //local write |
| 374 } | 373 } |
| 375 HOLISTIC__Record_Assigner_end; | 374 HOLISTIC__Record_Assigner_end; |
| 376 }//if slot needs slave assigned | 375 }//if slot needs slave assigned |
| 377 }//for( slotIdx.. | 376 }//for( slotIdx.. |
| 378 | 377 |
| 494 int32 thisCoresIdx; | 493 int32 thisCoresIdx; |
| 495 | 494 |
| 496 //#ifdef MODE__MULTI_LANG | 495 //#ifdef MODE__MULTI_LANG |
| 497 SlaveVP *slave; | 496 SlaveVP *slave; |
| 498 PRProcess *process; | 497 PRProcess *process; |
| 499 PRConstrEnvHolder *constrEnvHolder; | |
| 500 int32 langMagicNumber; | 498 int32 langMagicNumber; |
| 501 //#endif | 499 //#endif |
| 502 | 500 |
| 503 //======================== Initializations ======================== | 501 //======================== Initializations ======================== |
| 504 masterEnv = (MasterEnv*)_PRTopEnv; | 502 masterEnv = (MasterEnv*)_PRTopEnv; |
| 577 goto AssignWork; | 575 goto AssignWork; |
| 578 } | 576 } |
| 579 } //if has suspended slave that needs handling | 577 } //if has suspended slave that needs handling |
| 580 | 578 |
| 581 //if slot empty, hand to Assigner to fill with a slave | 579 //if slot empty, hand to Assigner to fill with a slave |
| 582 if( currSlot->needsSlaveAssigned ) | 580 if( currSlot->needsWorkAssigned ) |
| 583 { //Call plugin's Assigner to give slot a new slave | 581 { //Call plugin's Assigner to give slot a new slave |
| 584 HOLISTIC__Record_Assigner_start; | 582 HOLISTIC__Record_Assigner_start; |
| 585 | 583 |
| 586 AssignWork: | 584 AssignWork: |
| 587 | 585 |
| 589 | 587 |
| 590 //put the chosen slave into slot, and adjust flags and state | 588 //put the chosen slave into slot, and adjust flags and state |
| 591 if( assignedSlaveVP != NULL ) | 589 if( assignedSlaveVP != NULL ) |
| 592 { currSlot->slaveAssignedToSlot = assignedSlaveVP; | 590 { currSlot->slaveAssignedToSlot = assignedSlaveVP; |
| 593 assignedSlaveVP->animSlotAssignedTo = currSlot; | 591 assignedSlaveVP->animSlotAssignedTo = currSlot; |
| 594 currSlot->needsSlaveAssigned = FALSE; | 592 currSlot->needsWorkAssigned = FALSE; |
| 595 numSlotsFilled += 1; | 593 numSlotsFilled += 1; |
| 596 } | 594 } |
| 597 else | 595 else |
| 598 { | 596 { |
| 599 currSlot->needsSlaveAssigned = TRUE; //local write | 597 currSlot->needsWorkAssigned = TRUE; //local write |
| 600 } | 598 } |
| 601 HOLISTIC__Record_Assigner_end; | 599 HOLISTIC__Record_Assigner_end; |
| 602 }//if slot needs slave assigned | 600 }//if slot needs slave assigned |
| 603 }//for( slotIdx.. | 601 }//for( slotIdx.. |
| 604 | 602 |
| 616 //#ifdef MODE__MULTI_LANG | 614 //#ifdef MODE__MULTI_LANG |
| 617 //#ifdef MODE__MULTI_PROCESS | 615 //#ifdef MODE__MULTI_PROCESS |
| 618 void animationMaster( void *initData, SlaveVP *masterVP ) | 616 void animationMaster( void *initData, SlaveVP *masterVP ) |
| 619 { | 617 { |
| 620 int32 slotIdx; | 618 int32 slotIdx; |
| 621 // int32 numSlotsFilled; | |
| 622 AnimSlot *currSlot; | 619 AnimSlot *currSlot; |
| 623 //Used while scanning and filling animation slots | 620 //Used while scanning and filling animation slots |
| 624 AnimSlot **animSlots; | 621 AnimSlot **animSlots; |
| 625 | 622 |
| 626 //Local copies, for performance | 623 //Local copies, for performance |
| 659 } | 656 } |
| 660 } | 657 } |
| 661 #endif //MODE__MULTI_LANG | 658 #endif //MODE__MULTI_LANG |
| 662 #endif //MODE__MULTI_PROCESS | 659 #endif //MODE__MULTI_PROCESS |
| 663 | 660 |
| 661 | |
| 662 //This version of the master selects one of three loops, depending upon | |
| 663 // whether stand-alone single language (just slaves), or standalone with | |
| 664 // tasks, or multi-lang (implies multi-process) | |
| 665 void animationMaster( void *initData, SlaveVP *masterVP ) | |
| 666 { | |
| 667 int32 slotIdx; | |
| 668 AnimSlot *currSlot; | |
| 669 //Used while scanning and filling animation slots | |
| 670 AnimSlot **animSlots; | |
| 671 | |
| 672 //Local copies, for performance | |
| 673 MasterEnv *masterEnv; | |
| 674 int32 thisCoresIdx; | |
| 675 | |
| 676 //======================== Initializations ======================== | |
| 677 masterEnv = (MasterEnv*)_PRTopEnv; | |
| 678 | |
| 679 thisCoresIdx = masterVP->coreAnimatedBy; | |
| 680 animSlots = masterEnv->allAnimSlots[thisCoresIdx]; | |
| 681 | |
| 682 HOLISTIC__Insert_Master_Global_Vars; | |
| 683 | |
| 684 //======================== animationMaster ======================== | |
| 685 //Have three different modes, and the master behavior is different for | |
| 686 // each, so jump to the loop that corresponds to the mode. | |
| 687 // | |
| 688 switch(mode) | |
| 689 { case StandaloneSlavesOnly: | |
| 690 while(1) | |
| 691 { MEAS__Capture_Pre_Master_Point | |
| 692 for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) | |
| 693 { | |
| 694 currSlot = animSlots[ slotIdx ]; | |
| 695 | |
| 696 masterFunction_StandaloneSlavesOnly( currSlot ); | |
| 697 } | |
| 698 MEAS__Capture_Post_Master_Point; | |
| 699 masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master | |
| 700 flushRegisters(); | |
| 701 } | |
| 702 case StandaloneWTasks: | |
| 703 while(1) | |
| 704 { MEAS__Capture_Pre_Master_Point | |
| 705 for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) | |
| 706 { | |
| 707 currSlot = animSlots[ slotIdx ]; | |
| 708 | |
| 709 masterFunction_StandaloneWTasks( currSlot ); | |
| 710 } | |
| 711 MEAS__Capture_Post_Master_Point; | |
| 712 masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master | |
| 713 flushRegisters(); | |
| 714 } | |
| 715 case MultiLang: | |
| 716 while(1) | |
| 717 { MEAS__Capture_Pre_Master_Point | |
| 718 for( slotIdx = 0; slotIdx < NUM_ANIM_SLOTS; slotIdx++) | |
| 719 { | |
| 720 currSlot = animSlots[ slotIdx ]; | |
| 721 | |
| 722 masterFunction_multiLang( currSlot ); | |
| 723 } | |
| 724 MEAS__Capture_Post_Master_Point; | |
| 725 masterSwitchToCoreCtlr( masterVP ); //returns when ctlr switches back to master | |
| 726 flushRegisters(); | |
| 727 } | |
| 728 } | |
| 729 } | |
| 730 | |
| 731 | |
| 664 inline | 732 inline |
| 665 void | 733 void |
| 666 masterFunction_multiLang( AnimSlot *currSlot ) | 734 masterFunction_multiLang( AnimSlot *currSlot ) |
| 667 { //Scan the animation slots | 735 { //Scan the animation slots |
| 668 int32 magicNumber; | 736 int32 magicNumber; |
| 673 RequestHandler requestHandler; | 741 RequestHandler requestHandler; |
| 674 | 742 |
| 675 //Check if newly-done slave in slot, which will need request handled | 743 //Check if newly-done slave in slot, which will need request handled |
| 676 if( currSlot->workIsDone ) | 744 if( currSlot->workIsDone ) |
| 677 { currSlot->workIsDone = FALSE; | 745 { currSlot->workIsDone = FALSE; |
| 746 currSlot->needsWorkAssigned = TRUE; | |
| 678 | 747 |
| 679 HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot | 748 HOLISTIC__Record_AppResponder_start; //TODO: update to check which process for each slot |
| 680 MEAS__startReqHdlr; | 749 MEAS__startReqHdlr; |
| 681 | 750 |
| 682 | 751 |
| 683 //process the request made by the slave (held inside slave struc) | 752 //process the request made by the slave (held inside slave struc) |
| 684 slave = currSlot->slaveAssignedToSlot; | 753 slave = currSlot->slaveAssignedToSlot; |
| 685 | 754 req = slave->request; |
| 686 //check if the slave was doing a task.. | 755 |
| 687 //Action depends on both on the request type, and whether it's on | 756 //If the requesting slave is a slot slave, and request is not |
| 688 // a generic slave vs a suspended task | 757 // task-end, then turn it into a free task slave. |
| 689 if( slave->metaTask->taskType == AtomicTask || | 758 if( slave->typeOfVP == SlotTaskSlv && req->reqType != TaskEnd ) |
| 690 slave->metaTask->taskType == SuspendedTask ) | 759 replaceWithNewSlotSlv( slave ); |
| 691 { | 760 |
| 692 switch( slave->request->reqType ) | 761 //Handle task create and end first -- they're special cases.. |
| 693 { case TaskEnd: | 762 switch( req->reqType ) |
| 694 { PRHandle_EndTask( slave ); //if free task slave, update count, put into recycle Q -- do handler before lang's handler | 763 { case TaskEnd: |
| 695 | 764 { //do PR handler, which calls lang's hdlr and does recycle of |
| 696 //do task end handler, which is registered separately | 765 // free task slave if needed -- PR handler checks for free task Slv |
| 697 //note, end hdlr may use semantic data from reqst.. | 766 PRHandle_EndTask( slave ); break; |
| 698 //get end-task handler | |
| 699 | |
| 700 RequestHandler | |
| 701 taskEndHandler = slave->request->handler; | |
| 702 semanticEnv = PR_int__give_sem_env_for_slave( slave, | |
| 703 slave->request->langMagicNumber ); | |
| 704 (*taskEndHandler)( slave, semanticEnv ); | |
| 705 | |
| 706 goto AssignWork; | |
| 707 } | |
| 708 case TaskCreate: | |
| 709 { PRHandle_CreateTask( slave ); | |
| 710 RequestHandler | |
| 711 taskCreateHandler = slave->request->handler; | |
| 712 semanticEnv = PR_int__give_sem_env_for_slave( slave, | |
| 713 slave->request->langMagicNumber ); | |
| 714 (*taskCreateHandler)( slave, semanticEnv ); //resumes creating slave | |
| 715 goto AssignWork; | |
| 716 } | |
| 717 default: | |
| 718 { //is a task, and just suspended, so tied to a free task slave | |
| 719 //First turn slot slave into free task slave & make replacement | |
| 720 if( slave->typeOfVP == SlotTaskSlv ) | |
| 721 replaceWithNewSlotSlv( slave, slave->processSlaveIsIn->processEnv ); | |
| 722 | |
| 723 //goto normal slave request handling | |
| 724 goto SlaveReqHandling; | |
| 725 } | |
| 726 } | 767 } |
| 727 } | 768 case TaskCreate: |
| 728 else //is a slave that suspended | 769 { //Do PR's create-task handler, which calls the lang's hdlr |
| 729 { | 770 // PR handler checks for free task Slv |
| 730 | 771 PRHandle_CreateTask( slave ); break; |
| 731 SlaveReqHandling: | |
| 732 //Q: put the switch in inline call, to clean up code? | |
| 733 req = slave->request; | |
| 734 switch( req->reqType ) | |
| 735 { case SlvCreate: PRHandle_CreateSlave( slave ); break; | |
| 736 case SlvDissipate: PRHandle_Dissipate( slave ); break; | |
| 737 case Service: PR_int__handle_PRServiceReq( slave ); break; //resume into PR's own semantic env | |
| 738 case Hardware: //for future expansion | |
| 739 case IO: //for future expansion | |
| 740 case OSCall: //for future expansion | |
| 741 case Language: //normal sem request | |
| 742 magicNumber = slave->request->langMagicNumber; | |
| 743 semanticEnv = PR_PI__give_sem_env_for( slave, magicNumber ); | |
| 744 requestHandler = semanticEnv->requestHdlr; | |
| 745 (*requestHandler)( slave, semanticEnv ); //(note: indirect Fn call more efficient when use fewer params, instead re-fetch from slave) | |
| 746 } | 772 } |
| 747 | 773 case SlvCreate: PRHandle_CreateSlave( slave ); break; |
| 748 HOLISTIC__Record_AppResponder_end; | 774 case SlvDissipate: PRHandle_Dissipate( slave ); break; |
| 749 MEAS__endReqHdlr; | 775 case Service: PR_int__handle_PRServiceReq( slave ); break; //resume into PR's own semantic env |
| 750 | 776 case Hardware: //for future expansion |
| 751 goto AssignWork; | 777 case IO: //for future expansion |
| 752 } | 778 case OSCall: //for future expansion |
| 753 } //if has suspended slave that needs handling | 779 PR_int__throw_exception("Not implemented"); break; |
| 780 case Language: //normal sem request | |
| 781 magicNumber = req->langMagicNumber; | |
| 782 semanticEnv = PR_PI__give_sem_env_for( slave, magicNumber ); | |
| 783 requestHandler = semanticEnv->requestHdlr; | |
| 784 (*requestHandler)( req->semReq, slave, semanticEnv ); | |
| 785 } | |
| 786 | |
| 787 HOLISTIC__Record_AppResponder_end; | |
| 788 MEAS__endReqHdlr; | |
| 789 } //if have request to be handled | |
| 754 | 790 |
| 755 //End up here when the slot did not have ended work in it (no req) | 791 if( currSlot->needsWorkAssigned ) |
| 756 //So, here, if slot empty, look for work to fill the slot | 792 { |
| 757 if( currSlot->needsSlaveAssigned ) | 793 HOLISTIC__Record_Assigner_start; |
| 758 { HOLISTIC__Record_Assigner_start; | 794 |
| 759 | |
| 760 AssignWork: | |
| 761 //Scan sem environs, looking for semEnv with ready work. | 795 //Scan sem environs, looking for semEnv with ready work. |
| 762 // call the Assigner for that sem Env, to get a slave for the slot | 796 // call the Assigner for that sem Env, to get a slave for the slot |
| 763 assignedSlaveVP = assignWork( semanticEnv, currSlot ); | 797 assignedSlaveVP = assignWork( semanticEnv, currSlot ); |
| 764 | 798 |
| 765 //put the chosen slave into slot, and adjust flags and state | 799 //if work found, put into slot, and adjust flags and state |
| 766 if( assignedSlaveVP != NULL ) | 800 if( assignedSlaveVP != NULL ) |
| 767 { currSlot->slaveAssignedToSlot = assignedSlaveVP; | 801 { currSlot->slaveAssignedToSlot = assignedSlaveVP; |
| 768 assignedSlaveVP->animSlotAssignedTo = currSlot; | 802 assignedSlaveVP->animSlotAssignedTo = currSlot; |
| 769 currSlot->needsSlaveAssigned = FALSE; | 803 currSlot->needsWorkAssigned = FALSE; |
| 770 } | |
| 771 else | |
| 772 { currSlot->needsSlaveAssigned = TRUE; //local write | |
| 773 } | 804 } |
| 774 HOLISTIC__Record_Assigner_end; | 805 HOLISTIC__Record_Assigner_end; |
| 775 }//if slot needs slave assigned | 806 }//if slot needs slave assigned |
| 776 } | 807 } |
| 777 | 808 |
| 784 */ | 815 */ |
| 785 inline void | 816 inline void |
| 786 replaceWithNewSlotSlv( SlaveVP *requestingSlv, PRProcess *process ) | 817 replaceWithNewSlotSlv( SlaveVP *requestingSlv, PRProcess *process ) |
| 787 { SlaveVP *newSlotSlv; | 818 { SlaveVP *newSlotSlv; |
| 788 | 819 |
| 820 When slot slave converted to a free task slave, insert the process pointer -- slot slaves are not assigned to any process; | |
| 821 when convert from slot slave to free task slave, check what should do about num (live slaves + live tasks) inside VSs's task stub, and properly update process's count of liveFreeTaskSlaves | |
| 822 | |
| 789 //get a new slave to be the slot slave | 823 //get a new slave to be the slot slave |
| 790 newSlotSlv = readPrivQ( process->freeTaskSlvRecycleQ ); | 824 newSlotSlv = readPrivQ( process->freeTaskSlvRecycleQ ); |
| 791 if( newSlotSlv == NULL ) | 825 if( newSlotSlv == NULL ) |
| 792 { newSlotSlv = PR_int__create_slaveVP( &idle_fn, NULL, process, 0); | 826 { newSlotSlv = PR_int__create_slaveVP( &idle_fn, NULL, process, 0); |
| 793 //just made a new free task slave, so count it | 827 //just made a new free task slave, so count it |
| 795 } | 829 } |
| 796 | 830 |
| 797 //set slave values to make it the slot slave | 831 //set slave values to make it the slot slave |
| 798 newSlotSlv->metaTask = NULL; | 832 newSlotSlv->metaTask = NULL; |
| 799 newSlotSlv->typeOfVP = SlotTaskSlv; | 833 newSlotSlv->typeOfVP = SlotTaskSlv; |
| 800 newSlotSlv->needsTaskAssigned = TRUE; | 834 // newSlotSlv->needsTaskAssigned = TRUE; |
| 801 | 835 |
| 802 //a slot slave is pinned to a particular slot on a particular core | 836 //a slot slave is pinned to a particular slot on a particular core |
| 803 //Note, this happens before the request is seen by handler, so nothing | 837 //Note, this happens before the request is seen by handler, so nothing |
| 804 // has had a chance to change the coreAnimatedBy or anything else.. | 838 // has had a chance to change the coreAnimatedBy or anything else.. |
| 805 newSlotSlv->animSlotAssignedTo = requestingSlv->animSlotAssignedTo; | 839 newSlotSlv->animSlotAssignedTo = requestingSlv->animSlotAssignedTo; |
| 811 process->slotTaskSlvs[coreNum][slotNum] = newSlotSlv; | 845 process->slotTaskSlvs[coreNum][slotNum] = newSlotSlv; |
| 812 | 846 |
| 813 //Fix up requester, to be an extra slave now (but not an ended one) | 847 //Fix up requester, to be an extra slave now (but not an ended one) |
| 814 // because it's active, doesn't go into freeTaskSlvRecycleQ | 848 // because it's active, doesn't go into freeTaskSlvRecycleQ |
| 815 requestingSlv->typeOfVP = FreeTaskSlv; | 849 requestingSlv->typeOfVP = FreeTaskSlv; |
| 816 check_if_need_to_change_metaTask_type_or_something; | 850 requestingSlv->metaTask->taskType = FreeTask; |
| 817 } | 851 } |
| 818 | 852 |
| 819 | 853 |
| 820 | 854 |
| 821 /*This does: | 855 /*This does: |
| 839 * but am making it possible. | 873 * but am making it possible. |
| 840 */ | 874 */ |
| 841 inline SlaveVP * | 875 inline SlaveVP * |
| 842 assignWork( PRProcess *process, AnimSlot *slot ) | 876 assignWork( PRProcess *process, AnimSlot *slot ) |
| 843 { SlaveVP *returnSlv; | 877 { SlaveVP *returnSlv; |
| 844 //VSsSemEnv *semEnv; | |
| 845 //VSsSemData *semData; | |
| 846 int32 coreNum, slotNum; | 878 int32 coreNum, slotNum; |
| 847 PRMetaTask *newMetaTask, *assignedMetaTask; | 879 PRMetaTask *assignedMetaTask; |
| 848 SlaveVP *freeTaskSlv; | |
| 849 | 880 |
| 850 coreNum = slot->coreSlotIsOn; | 881 coreNum = slot->coreSlotIsOn; |
| 851 | 882 |
| 852 if( _PRTopEnv->overrideAssigner != NULL ) | 883 if( process->overrideAssigner != NULL ) |
| 853 { assignedMetaTask = (*_PRTopEnv->overrideAssigner)( process, slot ); | 884 { assignedMetaTask = (*process->overrideAssigner)( process, slot ); |
| 854 if( assignedMetaTask != NULL ) | 885 if( assignedMetaTask != NULL ) |
| 855 { | 886 { |
| 856 //have work, so reset Done flag (caused by work generated on other core) | 887 //have work, so reset Done flag (caused by work generated on other core) |
| 857 if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf | 888 // if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf |
| 858 process->coreIsDone[coreNum] = FALSE; //don't just write always | 889 // process->coreIsDone[coreNum] = FALSE; //don't just write always |
| 859 | 890 |
| 860 switch( assignedMetaTask->taskType ) | 891 // switch( assignedMetaTask->taskType ) |
| 861 { case GenericSlave: goto AssignSlave; | 892 // { case GenericSlave: goto AssignSlave; |
| 862 case SuspendedTask: goto AssignSlave; | 893 // case FreeTask: goto AssignSlave; |
| 863 case AtomicTask: goto AssignNewTask; | 894 // case SlotTask: goto AssignNewTask; |
| 864 default: PR_int__throw_exception( "unknown task type ret by assigner" ); | 895 // default: PR_int__throw_exception( "unknown task type ret by assigner" ); |
| 865 } | 896 // } |
| 897 //If meta task has a slave attached, then goto assign slave, | |
| 898 // else it's a new task, so goto where assign it to a slot slave | |
| 899 if( assignedMetaTask->slaveAssignedTo != NULL ) | |
| 900 goto AssignSlave; | |
| 901 else | |
| 902 goto AssignNewTask; | |
| 866 } | 903 } |
| 867 else | 904 else //metaTask is NULL, so no work.. |
| 868 goto NoWork; | 905 goto NoWork; |
| 869 } | 906 } |
| 870 | 907 |
| 871 //If here, then no override assigner, so search semantic envs for work | 908 //If here, then no override assigner, so search semantic envs for work |
| 872 int32 envIdx, numEnvs; PRSemEnv **semEnvs, *semEnv; SlaveAssigner assigner; | 909 int32 envIdx, numEnvs; PRSemEnv **semEnvs, *semEnv; SlaveAssigner assigner; |
| 873 semEnvs = process->semEnvs; | 910 semEnvs = process->semEnvs; |
| 874 numEnvs = process->numSemEnvs; | 911 numEnvs = process->numSemEnvs; |
| 875 for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep semEnvs in hash AND array | 912 for( envIdx = 0; envIdx < numEnvs; envIdx++ ) //keep semEnvs in hash & array |
| 876 { semEnv = semEnvs[envIdx]; | 913 { semEnv = semEnvs[envIdx]; |
| 877 if( semEnv->hasWork ) | 914 if( semEnv->hasWork ) |
| 878 { assigner = semEnv->slaveAssigner; | 915 { assigner = semEnv->slaveAssigner; |
| 879 assignedMetaTask = (*assigner)( semEnv, slot ); | 916 assignedMetaTask = (*assigner)( semEnv, slot ); |
| 880 | 917 |
| 881 //have work, so reset Done flag (caused by work generated on other core) | 918 //have work, so reset Done flag (caused by work generated on other core) |
| 882 if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf | 919 // if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf |
| 883 process->coreIsDone[coreNum] = FALSE; //don't just write always | 920 // process->coreIsDone[coreNum] = FALSE; //don't just write always |
| 884 | 921 |
| 885 switch( assignedMetaTask->taskType ) | 922 // switch( assignedMetaTask->taskType ) |
| 886 { case GenericSlave: goto AssignSlave; | 923 // { case GenericSlave: goto AssignSlave; |
| 887 case SuspendedTask: goto AssignSlave; | 924 // case FreeTask: goto AssignSlave; |
| 888 case AtomicTask: goto AssignNewTask; | 925 // case SlotTask: goto AssignNewTask; |
| 889 default: PR_int__throw_exception( "unknown task type ret by assigner" ); | 926 // default: PR_int__throw_exception( "unknown task type ret by assigner" ); |
| 890 } | 927 // } |
| 928 //If meta task has a slave attached, then goto assign slave, | |
| 929 // else it's a new task, so goto where assign it to a slot slave | |
| 930 if( assignedMetaTask->slaveAssignedTo != NULL ) | |
| 931 goto AssignSlave; | |
| 932 else | |
| 933 goto AssignNewTask; | |
| 891 } | 934 } |
| 892 } | 935 } |
| 936 //If reach here, then have searched all semEnv's & none have work.. | |
| 893 | 937 |
| 894 NoWork: | 938 NoWork: |
| 895 //No work, if reach here.. | 939 //No work, if reach here.. |
| 896 { goto ReturnTheSlv; | 940 { goto ReturnTheSlv; |
| 897 } | 941 } |
| 898 | 942 |
| 899 AssignSlave: //Have a metaTask attached to a slave, so get the slave out | 943 AssignSlave: //Have a metaTask attached to a slave, so get the slave & ret it |
| 900 { //get slave pointed to by meta task. | 944 { returnSlv = assignedMetaTask->slaveAssignedTo; |
| 901 returnSlv = assignedMetaTask->slaveAssignedTo; | |
| 902 | |
| 903 returnSlv->coreAnimatedBy = coreNum; | 945 returnSlv->coreAnimatedBy = coreNum; |
| 904 | 946 |
| 905 goto ReturnTheSlv; | 947 goto ReturnTheSlv; |
| 906 } | 948 } |
| 907 | 949 |
| 908 AssignNewTask: | 950 AssignNewTask: //Have a new metaTask that has no slave yet.. assign to slot slv |
| 909 { | 951 { |
| 910 //get the slot slave to assign the task to.. | 952 //get the slot slave to assign the task to.. |
| 911 coreNum = slot->coreSlotIsOn; | |
| 912 slotNum = slot->slotIdx; | 953 slotNum = slot->slotIdx; |
| 913 returnSlv = process->slotTaskSlvs[coreNum][slotNum]; | 954 returnSlv = process->slotTaskSlvs[coreNum][slotNum]; |
| 914 | 955 |
| 915 //point slave to task's function, and mark slave as having task | 956 //point slave to task's function |
| 916 PR_int__reset_slaveVP_to_TopLvlFn( returnSlv, | 957 PR_int__reset_slaveVP_to_TopLvlFn( returnSlv, |
| 917 assignedMetaTask->topLevelFn, assignedMetaTask->initData ); | 958 assignedMetaTask->topLevelFn, assignedMetaTask->initData ); |
| 918 returnSlv->metaTask = assignedMetaTask; | 959 returnSlv->metaTask = assignedMetaTask; |
| 919 assignedMetaTask->slaveAssignedTo = returnSlv; | 960 assignedMetaTask->slaveAssignedTo = returnSlv; |
| 920 returnSlv->needsTaskAssigned = FALSE; //slot slave is a "Task" slave type | 961 // returnSlv->needsTaskAssigned = FALSE; //slot slave is a "Task" slave type |
| 921 | 962 |
| 922 //have work, so reset Done flag, if was set | 963 //have work, so reset Done flag, if was set |
| 923 if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf | 964 // if( process->coreIsDone[coreNum] == TRUE ) //reads are higher perf |
| 924 process->coreIsDone[coreNum] = FALSE; //don't just write always | 965 // process->coreIsDone[coreNum] = FALSE; //don't just write always |
| 925 | 966 |
| 926 goto ReturnTheSlv; | 967 goto ReturnTheSlv; |
| 927 } | 968 } |
| 928 | 969 |
| 929 | 970 |
| 1003 newSlv->typeOfVP = GenericSlv; | 1044 newSlv->typeOfVP = GenericSlv; |
| 1004 newSlv->processSlaveIsIn = process; | 1045 newSlv->processSlaveIsIn = process; |
| 1005 process->numLiveGenericSlvs += 1; | 1046 process->numLiveGenericSlvs += 1; |
| 1006 metaTask = PR_int__create_slave_meta_task(); | 1047 metaTask = PR_int__create_slave_meta_task(); |
| 1007 metaTask->taskID = req->ID; | 1048 metaTask->taskID = req->ID; |
| 1008 metaTask->taskType = GenericSlave; | 1049 // metaTask->taskType = GenericSlave; |
| 1009 | 1050 |
| 1010 (*req->handler)(newSlv); | 1051 (*req->handler)( req->semReq, newSlv, requestingSlv, semEnv ); |
| 1011 } | 1052 } |
| 1012 | 1053 |
| 1013 /*The dissipate handler has to update the number of slaves of the type, within | 1054 /*The dissipate handler has to, sdate the number of slaves of the type, within |
| 1014 * the process, and call the langlet handler linked into the request, | 1055 * the process, and call the langlet handler linked into the request, |
| 1015 * and after that returns, then call the PR function that frees the slave state | 1056 * and after that returns, then call the PR function that frees the slave state |
| 1016 * (or recycles the slave). | 1057 * (or recycles the slave). |
| 1017 * | 1058 * |
| 1018 *The PR function that frees the slave state has to also free all of the | 1059 *The PR function that frees the slave state has to also free all of the |
| 1025 void *semEnv; | 1066 void *semEnv; |
| 1026 | 1067 |
| 1027 process = slave->processSlaveIsIn; | 1068 process = slave->processSlaveIsIn; |
| 1028 | 1069 |
| 1029 //do the language's dissipate handler | 1070 //do the language's dissipate handler |
| 1030 semEnv = PR_int__give_sem_env_for( slave, slave->request->langMagicNumber ); | 1071 semEnv = PR_int__give_sem_env_for_slave( slave, slave->request->langMagicNumber ); |
| 1031 (*slave->request->handler)( slave, semEnv ); | 1072 (*slave->request->handler)( slave->request->semReq, slave, semEnv ); |
| 1032 | 1073 |
| 1033 process->numLiveGenericSlvs -= 1; | 1074 process->numLiveGenericSlvs -= 1; |
| 1034 PR_int__dissipate_slaveVP_multilang( slave ); //recycles and resets semDatas | 1075 PR_int__recycle_slave_multilang( requestingSlv ); |
| 1035 | 1076 |
| 1036 //check End Of Process Condition | 1077 //check End Of Process Condition |
| 1037 if( process->numLiveTasks == 0 && | 1078 if( process->numLiveTasks == 0 && |
| 1038 process->numLiveGenericSlvs == 0 ) | 1079 process->numLiveGenericSlvs == 0 ) |
| 1039 signalEndOfProcess; | 1080 PR_SS__shutdown_process( process ); |
| 1040 } | 1081 } |
| 1041 | 1082 |
| 1042 /*Create task is a special form, that has PR behavior in addition to plugin | 1083 /*Create task is a special form, that has PR behavior in addition to plugin |
| 1043 * behavior. Master calls this first, and this in turn calls the plugin's | 1084 * behavior. Master calls this first, and then calls the plugin's |
| 1044 * create task handler. | 1085 * create task handler. |
| 1086 * | |
| 1087 *Note: the requesting slave must be either generic slave or free task slave | |
| 1045 */ | 1088 */ |
| 1046 inline void | 1089 inline PRMetaTask * |
| 1047 PRHandle_CreateTask( TopLevelFn topLevelFn, void *initData, PRReqst *req, | 1090 PRHandle_CreateTask( PRReqst *req, SlaveVP *requestingSlv ) |
| 1048 SlaveVP *requestingSlv ) | 1091 { PRMetaTask *metaTask; |
| 1049 { PRMetaTask *metaTask; | 1092 PRProcess *process; |
| 1050 PRProcess *process; | |
| 1051 void *semEnv, _langMetaTask; | |
| 1052 PRLangMetaTask *langMetaTask; | 1093 PRLangMetaTask *langMetaTask; |
| 1053 | 1094 PRSemEnv *semanticEnv; |
| 1095 | |
| 1054 process = requestingSlv->processSlaveIsIn; | 1096 process = requestingSlv->processSlaveIsIn; |
| 1055 | 1097 |
| 1056 metaTask = PR_int__create_meta_task( req ); | 1098 metaTask = PR_int__create_meta_task( req ); |
| 1057 metaTask->taskID = req->ID; //may be NULL | 1099 metaTask->taskID = req->ID; //may be NULL |
| 1058 metaTask->topLevelFn = topLevelFn; | 1100 metaTask->topLevelFn = req->topLevelFn; |
| 1059 metaTask->initData = initData; | 1101 metaTask->initData = req->initData; |
| 1060 | 1102 |
| 1061 process->numLiveTasks += 1; | 1103 process->numLiveTasks += 1; |
| 1062 | 1104 |
| 1063 //plugin tracks tasks ready, and has its own assigner, so task doesn't | 1105 semanticEnv = PR_int__give_sem_env_for_slave( slave, |
| 1064 // come back from lang's handler -- it's consumed and stays in semEnv. | 1106 req->langMagicNumber ); |
| 1065 //But handler gives back the language-specific meta-task it creates, and | 1107 |
| 1066 // then hook that into the PR meta-task | 1108 //Do the langlet's create-task handler, which keeps the task |
| 1067 //(Could also do PRMetaTask as a prolog -- make a Fn that takes the size | 1109 // inside the langlet's sem env, but returns the langMetaTask |
| 1068 // of the lang's metaTask, and alloc's that plus the prolog and returns | 1110 // so PR can hook it to the PRMetaTask. |
| 1069 // ptr to position just above the prolog) | 1111 //(Could also do PRMetaTask as a prolog -- make a Fn that takes the size |
| 1070 semEnv = PR_int__give_semEnv_of_req( req, requestingSlv ); //magic num in req | 1112 // of the lang's metaTask, and alloc's that plus the prolog and returns |
| 1071 _langMetaTask = (*requestingSlv->request->handler)(req, semEnv); | 1113 // ptr to position just above the prolog) |
| 1072 langMetaTask = (PRLangMetaTask *)_langMetaTask; | 1114 langMetaTask = (*req->handler)(req->semReq, slave, semanticEnv); |
| 1073 metaTask->langMetaTask = langMetaTask; | 1115 metaTask->langMetaTask = langMetaTask; |
| 1074 langMetaTask->protoMetaTask = metaTask; | 1116 langMetaTask->protoMetaTask = metaTask; |
| 1075 | 1117 |
| 1076 return; | 1118 return; |
| 1077 } | 1119 } |
| 1078 | 1120 |
| 1079 /*When a task ends, are two scenarios: 1) task ran to completion, or 2) task | 1121 /*When a task ends, are two scenarios: 1) task ran to completion, or 2) task |
| 1080 * suspended at some point in its code. | 1122 * suspended at some point in its code. |
| 1085 * now has nothing more to do, so send it to the recycle Q (which includes | 1127 * now has nothing more to do, so send it to the recycle Q (which includes |
| 1086 * freeing all the semData and meta task structs alloc'd for it). Then | 1128 * freeing all the semData and meta task structs alloc'd for it). Then |
| 1087 * decrement the live task count and check end condition. | 1129 * decrement the live task count and check end condition. |
| 1088 * | 1130 * |
| 1089 *PR has to update count of live tasks, and check end of process condition. | 1131 *PR has to update count of live tasks, and check end of process condition. |
| 1090 * There are constructs that wait for a process to end, so when end detected, | 1132 * The "main" can invoke constructs that wait for a process to end, so when |
| 1091 * have to resume what's waiting.. | 1133 * end detected, have to resume what's waiting.. |
| 1092 *Thing is, the wait is used in "main", so it's an OS thread. That means | 1134 *Thing is, that wait involves the main OS thread. That means |
| 1093 * PR internals have to do OS thread signaling. Want to do that in the | 1135 * PR internals have to do OS thread signaling. Want to do that in the |
| 1094 * core controller, which has the original stack of an OS thread. | 1136 * core controller, which has the original stack of an OS thread. So the |
| 1137 * end process handling happens in the core controller. | |
| 1095 * | 1138 * |
| 1096 *So here, when detect process end, signal to the core controller, which will | 1139 *So here, when detect process end, signal to the core controller, which will |
| 1097 * then do the condition variable notify to the OS thread that's waiting. | 1140 * then do the condition variable notify to the OS thread that's waiting. |
| 1141 * | |
| 1142 *Note: slave may be either a slot slave or a free task slave. | |
| 1098 */ | 1143 */ |
| 1099 inline void | 1144 inline void |
| 1100 PRHandle_EndTask( SlaveVP *requestingSlv ) | 1145 PRHandle_EndTask( SlaveVP *requestingSlv ) |
| 1101 { void *semEnv; | 1146 { void *semEnv; |
| 1102 PRReqst *req; | 1147 PRReqst *req; |
| 1103 PRMetaTask *metaTask; | 1148 PRLangMetaTask *langMetaTask; |
| 1104 PRProcess *process; | 1149 PRProcess *process; |
| 1105 | 1150 |
| 1106 req = requestingSlv->request; | 1151 req = requestingSlv->request; |
| 1107 semEnv = PR_int__give_semEnv_of_req( req, requestingSlv ); //magic num in req | 1152 semEnv = PR_int__give_sem_env_of_req( req, requestingSlv ); //magic num in req |
| 1108 metaTask = req->metaTask; | 1153 langMetaTask = requestingSlv->metaTask->langMetaTask; |
| 1109 //Want to keep PRMetaTask hidden from plugin, so extract semReq.. | 1154 |
| 1110 (*req->handler)( metaTask, req->semReq, semEnv ); | 1155 //Do the langlet's request handler |
| 1111 | 1156 //Want to keep PR structs hidden from plugin, so extract semReq.. |
| 1112 recycleFreeTaskSlave( requestingSlv ); | 1157 (*req->handler)( langMetaTask, req->semReq, semEnv ); |
| 1158 | |
| 1159 //Now that the langlet's done with it, recycle the slave if it's a freeTaskSlv | |
| 1160 if( requestingSlv->typeOfVP == FreeTaskSlv ) | |
| 1161 PR_int__recycle_slave_multilang( requestingSlv ); | |
| 1113 | 1162 |
| 1114 process->numLiveTasks -= 1; | 1163 process->numLiveTasks -= 1; |
| 1115 | 1164 |
| 1116 //check End Of Process Condition | 1165 //check End Of Process Condition |
| 1117 if( process->numLiveTasks == 0 && | 1166 if( process->numLiveTasks == 0 && |
| 1118 process->numLiveGenericSlvs == 0 ) | 1167 process->numLiveGenericSlvs == 0 ) |
| 1119 signalEndOfProcessToCoreCtlr; | 1168 //Tell the core controller to do wakeup of any waiting OS thread |
| 1169 PR_SS__shutdown_process( process ); | |
| 1120 } | 1170 } |
| 1121 | 1171 |
| 1122 |
