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