# HG changeset patch # User Nina Engelhardt # Date 1346160796 -7200 # Node ID 1ffd5df22df98b75a8903e76f93871f5f2f3ca5a # Parent 459055db7fc05c9729ced0752225192967a8c589 add CG instrumentation; still missing WaR hazard constraints diff -r 459055db7fc0 -r 1ffd5df22df9 Measurement/VSs_Counter_Recording.c --- a/Measurement/VSs_Counter_Recording.c Thu Aug 23 03:21:03 2012 -0700 +++ b/Measurement/VSs_Counter_Recording.c Tue Aug 28 15:33:16 2012 +0200 @@ -28,14 +28,14 @@ list->next_free_index++; } -void VSs__counter_handler(int evt_type, int vpid, int task, SlaveVP* pr, uint64 cycles, uint64 instrs) +void VSs__counter_handler(int evt_type, int vpid, int task, SlaveVP* pr, uint64 cycles, uint64 instrs, uint64 cachem) { if (pr->typeOfVP == Master || pr->typeOfVP == Shutdown) { //Only save values for application work, done in a SlaveVP return; } - + VSsSemEnv *semanticEnv = _VMSMasterEnv->semanticEnv; CounterEvent e; @@ -45,6 +45,7 @@ e.cycles = cycles; e.instrs = instrs; + e.cachem = cachem; if(pr){ e.coreID = pr->coreAnimatedBy; @@ -112,7 +113,7 @@ default: fprintf(counterfile, "unknown event"); } - fprintf(counterfile,", %d, %d, %llu, %llu",e->vp,e->task,e->cycles,e->instrs); + fprintf(counterfile,", %d, %d, %llu, %llu, %llu",e->vp,e->task,e->cycles,e->instrs,e->cachem); if(e->coreID >=0) fprintf(counterfile,", %d",e->coreID); fprintf(counterfile,"\n"); diff -r 459055db7fc0 -r 1ffd5df22df9 Measurement/VSs_Counter_Recording.h --- a/Measurement/VSs_Counter_Recording.h Thu Aug 23 03:21:03 2012 -0700 +++ b/Measurement/VSs_Counter_Recording.h Tue Aug 28 15:33:16 2012 +0200 @@ -18,13 +18,14 @@ int task; uint64 cycles; uint64 instrs; + uint64 cachem; } CounterEvent; FILE* counterfile; void VSs__init_counter_data_structs(); -void VSs__counter_handler(int evt_type, int vpid, int task, SlaveVP* pr, uint64 cycles, uint64 instrs); +void VSs__counter_handler(int evt_type, int vpid, int task, SlaveVP* pr, uint64 cycles, uint64 instrs, uint64 cachem); void set_counter_file(FILE* f); diff -r 459055db7fc0 -r 1ffd5df22df9 Measurement/dependency.c --- a/Measurement/dependency.c Thu Aug 23 03:21:03 2012 -0700 +++ b/Measurement/dependency.c Tue Aug 28 15:33:16 2012 +0200 @@ -36,6 +36,18 @@ fprintf(dependency_file,"commDep,%d,%d,%d,%d\n",dep->from_vp,dep->from_task,dep->to_vp,dep->to_task); } +void print_data_dependency_to_file(void* _dep){ + Dependency* dep = (Dependency*) _dep; + if(!dep) return; + fprintf(dependency_file,"dataDep,%d,%d,%d,%d\n",dep->from_vp,dep->from_task,dep->to_vp,dep->to_task); +} + +void print_singleton_dependency_to_file(void* _dep){ + Dependency* dep = (Dependency*) _dep; + if(!dep) return; + fprintf(dependency_file,"singDep,%d,%d,%d,%d\n",dep->from_vp,dep->from_task,dep->to_vp,dep->to_task); +} + void print_dyn_dependency_to_file(void* _dep){ Dependency* dep = (Dependency*) _dep; if(!dep) return; diff -r 459055db7fc0 -r 1ffd5df22df9 Measurement/dependency.h --- a/Measurement/dependency.h Thu Aug 23 03:21:03 2012 -0700 +++ b/Measurement/dependency.h Tue Aug 28 15:33:16 2012 +0200 @@ -42,6 +42,10 @@ void print_comm_dependency_to_file(void* _dep); +void print_data_dependency_to_file(void* _dep); + +void print_singleton_dependency_to_file(void* _dep); + void print_dyn_dependency_to_file(void* _dep); void print_hw_dependency_to_file(void* _dep); diff -r 459055db7fc0 -r 1ffd5df22df9 VSs.c --- a/VSs.c Thu Aug 23 03:21:03 2012 -0700 +++ b/VSs.c Tue Aug 28 15:33:16 2012 +0200 @@ -97,7 +97,8 @@ parentTaskStub->isEnded = TRUE; parentTaskStub->numLiveChildThreads = 1; //so dissipate works for seed threadTaskStub->parentTaskStub = parentTaskStub; - + threadTaskStub->slaveAssignedTo = seedSlv; + semData = (VSsSemData *)seedSlv->semanticData; //seedVP is a thread, so has a permanent task semData->needsTaskAssigned = FALSE; @@ -260,6 +261,8 @@ semanticEnv->ctlDependenciesList = makeListOfArrays(sizeof(Dependency),128); semanticEnv->commDependenciesList = makeListOfArrays(sizeof(Dependency),128); semanticEnv->dynDependenciesList = makeListOfArrays(sizeof(Dependency),128); + semanticEnv->dataDependenciesList = makeListOfArrays(sizeof(Dependency),128); + semanticEnv->singletonDependenciesList = makeListOfArrays(sizeof(Dependency),128); semanticEnv->ntonGroupsInfo = makePrivDynArrayOfSize((void***)&(semanticEnv->ntonGroups),8); semanticEnv->hwArcs = makeListOfArrays(sizeof(Dependency),128); @@ -304,6 +307,8 @@ forAllInListOfArraysDo(semanticEnv->unitList, &print_unit_to_file); forAllInListOfArraysDo( semanticEnv->commDependenciesList, &print_comm_dependency_to_file ); forAllInListOfArraysDo( semanticEnv->ctlDependenciesList, &print_ctl_dependency_to_file ); + forAllInListOfArraysDo( semanticEnv->dataDependenciesList, &print_data_dependency_to_file ); + forAllInListOfArraysDo( semanticEnv->singletonDependenciesList, &print_singleton_dependency_to_file ); forAllInDynArrayDo(semanticEnv->ntonGroupsInfo,&print_nton_to_file); //fprintf(output,"}\n"); fflush(output); @@ -337,6 +342,8 @@ forAllInListOfArraysDo( semanticEnv->unitList, &print_unit_to_file ); forAllInListOfArraysDo( semanticEnv->commDependenciesList, &print_comm_dependency_to_file ); forAllInListOfArraysDo( semanticEnv->ctlDependenciesList, &print_ctl_dependency_to_file ); + forAllInListOfArraysDo( semanticEnv->dataDependenciesList, &print_data_dependency_to_file ); + forAllInListOfArraysDo( semanticEnv->singletonDependenciesList, &print_singleton_dependency_to_file ); forAllInListOfArraysDo( semanticEnv->dynDependenciesList, &print_dyn_dependency_to_file ); forAllInListOfArraysDo( semanticEnv->hwArcs, &print_hw_dependency_to_file ); //fprintf(output,"}\n"); @@ -353,6 +360,7 @@ freeListOfArrays(semanticEnv->commDependenciesList); freeListOfArrays(semanticEnv->ctlDependenciesList); freeListOfArrays(semanticEnv->dynDependenciesList); + freeListOfArrays(semanticEnv->dataDependenciesList); #endif #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS diff -r 459055db7fc0 -r 1ffd5df22df9 VSs.h --- a/VSs.h Thu Aug 23 03:21:03 2012 -0700 +++ b/VSs.h Tue Aug 28 15:33:16 2012 +0200 @@ -62,6 +62,10 @@ bool32 hasEnabledNonFinishedWriter; int32 numEnabledNonDoneReaders; PrivQueueStruc *waitersQ; +#ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + int lastWriterVP; + int lastWriterTask; +#endif } VSsPointerEntry; @@ -111,6 +115,8 @@ int32 hasBeenStarted; int32 hasFinished; PrivQueueStruc *waitQ; + int executingVp; + int executingTask; } VSsSingleton; @@ -197,9 +203,11 @@ ListOfArrays* unitList; ListOfArrays* ctlDependenciesList; ListOfArrays* commDependenciesList; + ListOfArrays* dataDependenciesList; NtoN** ntonGroups; PrivDynArrayInfo* ntonGroupsInfo; ListOfArrays* dynDependenciesList; + ListOfArrays* singletonDependenciesList; Unit last_in_slot[NUM_CORES * NUM_ANIM_SLOTS]; ListOfArrays* hwArcs; #endif diff -r 459055db7fc0 -r 1ffd5df22df9 VSs_PluginFns.c --- a/VSs_PluginFns.c Thu Aug 23 03:21:03 2012 -0700 +++ b/VSs_PluginFns.c Tue Aug 28 15:33:16 2012 +0200 @@ -13,19 +13,20 @@ //=========================== Local Fn Prototypes =========================== void -resume_slaveVP( SlaveVP *slave, VSsSemEnv *semEnv ); +resume_slaveVP(SlaveVP *slave, VSsSemEnv *semEnv); inline void -handleSemReq( VMSReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv ); +handleSemReq(VMSReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv); inline void -handleDissipate( SlaveVP *requestingSlv, VSsSemEnv *semEnv ); +handleDissipate(SlaveVP *requestingSlv, VSsSemEnv *semEnv); inline void -handleCreate( VMSReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv ); +handleCreate(VMSReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv); //============================== Assigner ================================== // + /*The assigner is complicated by having both tasks and explicitly created * VPs, and by tasks being able to suspend. *It can't use an explicit slave to animate a task because of stack @@ -49,359 +50,349 @@ * the junk tasks are allowed to leave behind. */ SlaveVP * -VSs__assign_slaveVP_to_slot( void *_semEnv, AnimSlot *slot ) - { SlaveVP *returnSlv; - VSsSemEnv *semEnv; - VSsSemData *semData; - int32 coreNum, slotNum; - VSsTaskStub *newTaskStub; - SlaveVP *extraSlv; - - coreNum = slot->coreSlotIsOn; - slotNum = slot->slotIdx; - - semEnv = (VSsSemEnv *)_semEnv; - +VSs__assign_slaveVP_to_slot(void *_semEnv, AnimSlot *slot) { + SlaveVP *returnSlv; + VSsSemEnv *semEnv; + VSsSemData *semData; + int32 coreNum, slotNum; + VSsTaskStub *newTaskStub; + SlaveVP *extraSlv; + + coreNum = slot->coreSlotIsOn; + slotNum = slot->slotIdx; + + semEnv = (VSsSemEnv *) _semEnv; + //Check for suspended slaves that are ready to resume - returnSlv = readPrivQ( semEnv->slavesReadyToResumeQ ); - if( returnSlv != NULL ) //Yes, have a slave, so return it. + returnSlv = readPrivQ(semEnv->slavesReadyToResumeQ); + if (returnSlv != NULL) //Yes, have a slave, so return it. { returnSlv->coreAnimatedBy = coreNum; //have work, so reset Done flag (when work generated on other core) - if( semEnv->coreIsDone[coreNum] == TRUE ) //reads are higher perf - semEnv->coreIsDone[coreNum] = FALSE; //don't just write always - goto ReturnTheSlv; + if (semEnv->coreIsDone[coreNum] == TRUE) //reads are higher perf + semEnv->coreIsDone[coreNum] = FALSE; //don't just write always + goto ReturnTheSlv; } //If none, speculate will have a task, so get the slot slave //TODO: false sharing ? (think not bad cause mostly read..) - returnSlv = semEnv->slotTaskSlvs[coreNum][slotNum]; - - semData = (VSsSemData *)returnSlv->semanticData; + returnSlv = semEnv->slotTaskSlvs[coreNum][slotNum]; - //There is always a curr task slave, and it always needs a task - // (task slaves that are resuming are in resumeQ) - newTaskStub = readPrivQ( semEnv->taskReadyQ ); - if( newTaskStub != NULL ) - { //point slave to task's function, and mark slave as having task - VMS_int__reset_slaveVP_to_TopLvlFn( returnSlv, - newTaskStub->taskType->fn, newTaskStub->args ); - semData->taskStub = newTaskStub; - newTaskStub->slaveAssignedTo = returnSlv; - semData->needsTaskAssigned = FALSE; + semData = (VSsSemData *) returnSlv->semanticData; + + //There is always a curr task slave, and it always needs a task + // (task slaves that are resuming are in resumeQ) + newTaskStub = readPrivQ(semEnv->taskReadyQ); + if (newTaskStub != NULL) { //point slave to task's function, and mark slave as having task + VMS_int__reset_slaveVP_to_TopLvlFn(returnSlv, + newTaskStub->taskType->fn, newTaskStub->args); + semData->taskStub = newTaskStub; + newTaskStub->slaveAssignedTo = returnSlv; + semData->needsTaskAssigned = FALSE; //have work, so reset Done flag, if was set - if( semEnv->coreIsDone[coreNum] == TRUE ) //reads are higher perf - semEnv->coreIsDone[coreNum] = FALSE; //don't just write always - goto ReturnTheSlv; - } - else - { //no task, so try to clean up unused extra task slaves - extraSlv = readPrivQ( semEnv->freeExtraTaskSlvQ ); - if( extraSlv != NULL ) + if (semEnv->coreIsDone[coreNum] == TRUE) //reads are higher perf + semEnv->coreIsDone[coreNum] = FALSE; //don't just write always + goto ReturnTheSlv; + } else { //no task, so try to clean up unused extra task slaves + extraSlv = readPrivQ(semEnv->freeExtraTaskSlvQ); + if (extraSlv != NULL) { //have two slaves need tasks, so delete one //This both bounds the num extras, and delivers shutdown cond - handleDissipate( extraSlv, semEnv ); + handleDissipate(extraSlv, semEnv); //then return NULL - returnSlv = NULL; - goto ReturnTheSlv; - } - else - { //candidate for shutdown.. if all extras dissipated, and no tasks - // and no ready to resume slaves, then no way to generate + returnSlv = NULL; + goto ReturnTheSlv; + } else { //candidate for shutdown.. if all extras dissipated, and no tasks + // and no ready to resume slaves, then no way to generate // more tasks (on this core -- other core might have task still) - if( semEnv->numLiveExtraTaskSlvs == 0 && - semEnv->numLiveThreadSlvs == 0 ) - { //This core sees no way to generate more tasks, so say it - if( semEnv->coreIsDone[coreNum] == FALSE ) - { semEnv->numCoresDone += 1; - semEnv->coreIsDone[coreNum] = TRUE; - #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE - semEnv->shutdownInitiated = TRUE; + if (semEnv->numLiveExtraTaskSlvs == 0 && + semEnv->numLiveThreadSlvs == 0) { //This core sees no way to generate more tasks, so say it + if (semEnv->coreIsDone[coreNum] == FALSE) { + semEnv->numCoresDone += 1; + semEnv->coreIsDone[coreNum] = TRUE; +#ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE + semEnv->shutdownInitiated = TRUE; - #else - if( semEnv->numCoresDone == NUM_CORES ) - { //means no cores have work, and none can generate more - semEnv->shutdownInitiated = TRUE; +#else + if (semEnv->numCoresDone == NUM_CORES) { //means no cores have work, and none can generate more + semEnv->shutdownInitiated = TRUE; + } +#endif } - #endif - } - } + } //return NULL.. no task and none to resume - returnSlv = NULL; + returnSlv = NULL; //except if shutdown has been initiated by this or other core - if(semEnv->shutdownInitiated) - { returnSlv = VMS_SS__create_shutdown_slave(); - } - goto ReturnTheSlv; //don't need, but completes pattern - } //if( extraSlv != NULL ) + if (semEnv->shutdownInitiated) { + returnSlv = VMS_SS__create_shutdown_slave(); + } + goto ReturnTheSlv; //don't need, but completes pattern + } //if( extraSlv != NULL ) } //if( newTaskStub == NULL ) - //outcome: 1)slave was just pointed to task, 2)no tasks, so slave NULL + //outcome: 1)slave was just pointed to task, 2)no tasks, so slave NULL -ReturnTheSlv: //Nina, doing gotos to here should help with holistic.. +ReturnTheSlv: //Nina, doing gotos to here should help with holistic.. - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC - if( returnSlv == NULL ) - { returnSlv = semEnv->idleSlv[coreNum][slotNum]; - - //things that would normally happen in resume(), but these VPs - // never go there - returnSlv->assignCount++; //Somewhere here! - Unit newu; - newu.vp = returnSlv->slaveID; - newu.task = returnSlv->assignCount; - addToListOfArrays(Unit,newu,semEnv->unitList); - if (returnSlv->assignCount > 1) - { Dependency newd; - newd.from_vp = returnSlv->slaveID; - newd.from_task = returnSlv->assignCount - 1; - newd.to_vp = returnSlv->slaveID; - newd.to_task = returnSlv->assignCount; - addToListOfArrays(Dependency, newd ,semEnv->ctlDependenciesList); - } +#ifdef IDLE_SLAVES + if (!returnSlv) { + returnSlv = semEnv->idlePr[coreNum][slotNum]; + + if (semEnv->shutdownInitiated) { + returnSlv = VMS_SS__create_shutdown_slave(); + } } - #endif - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC - if( returnSlv != NULL ) - { //assignSlv->numTimesAssigned++; - Unit prev_in_slot = - semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum]; - if(prev_in_slot.vp != 0) - { Dependency newd; - newd.from_vp = prev_in_slot.vp; - newd.from_task = prev_in_slot.task; - newd.to_vp = returnSlv->slaveID; - newd.to_task = returnSlv->assignCount; - addToListOfArrays(Dependency,newd,semEnv->hwArcs); - } - prev_in_slot.vp = returnSlv->slaveID; - prev_in_slot.task = returnSlv->assignCount; - semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum] = - prev_in_slot; +#endif +#ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + if (returnSlv && (returnSlv->typeOfVP == Slave || returnSlv->typeOfVP == Idle)) { + returnSlv->assignCount++; + + Unit newu; + newu.vp = returnSlv->slaveID; + newu.task = returnSlv->assignCount; + addToListOfArrays(Unit, newu, semEnv->unitList); + + if (returnSlv->assignCount > 1) { + Dependency newd; + newd.from_vp = returnSlv->slaveID; + newd.from_task = returnSlv->assignCount - 1; + newd.to_vp = returnSlv->slaveID; + newd.to_task = returnSlv->assignCount; + addToListOfArrays(Dependency, newd, semEnv->ctlDependenciesList); + } + + Unit prev_in_slot = semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum]; + if (prev_in_slot.vp != 0) { + Dependency newd; + newd.from_vp = prev_in_slot.vp; + newd.from_task = prev_in_slot.task; + newd.to_vp = returnSlv->slaveID; + newd.to_task = returnSlv->assignCount; + addToListOfArrays(Dependency, newd, semEnv->hwArcs); + } + prev_in_slot.vp = returnSlv->slaveID; + prev_in_slot.task = returnSlv->assignCount; + semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum] = prev_in_slot; } - #endif - return( returnSlv ); - } +#endif + return ( returnSlv); +} //=========================== Request Handler ============================ // + /* * (BTW not inline because invoked indirectly via a pointer) */ void -VSs__Request_Handler( SlaveVP *requestingSlv, void *_semEnv ) - { VSsSemEnv *semEnv; - VMSReqst *req; - - semEnv = (VSsSemEnv *)_semEnv; +VSs__Request_Handler(SlaveVP *requestingSlv, void *_semEnv) { + VSsSemEnv *semEnv; + VMSReqst *req; - req = VMS_PI__take_next_request_out_of( requestingSlv ); + semEnv = (VSsSemEnv *) _semEnv; - while( req != NULL ) - { - switch( req->reqType ) - { case semantic: handleSemReq( req, requestingSlv, semEnv); - break; - case createReq: handleCreate( req, requestingSlv, semEnv); - break; - case dissipate: handleDissipate( requestingSlv, semEnv); - break; - case VMSSemantic: VMS_PI__handle_VMSSemReq(req, requestingSlv, semEnv, - (ResumeSlvFnPtr) &resume_slaveVP); - break; - default: - break; - } - - req = VMS_PI__take_next_request_out_of( requestingSlv ); + req = VMS_PI__take_next_request_out_of(requestingSlv); + + while (req != NULL) { + switch (req->reqType) { + case semantic: handleSemReq(req, requestingSlv, semEnv); + break; + case createReq: handleCreate(req, requestingSlv, semEnv); + break; + case dissipate: handleDissipate(requestingSlv, semEnv); + break; + case VMSSemantic: VMS_PI__handle_VMSSemReq(req, requestingSlv, semEnv, + (ResumeSlvFnPtr) & resume_slaveVP); + break; + default: + break; + } + + req = VMS_PI__take_next_request_out_of(requestingSlv); } //while( req != NULL ) - } - +} inline void -handleSemReq( VMSReqst *req, SlaveVP *reqSlv, VSsSemEnv *semEnv ) - { VSsSemReq *semReq; +handleSemReq(VMSReqst *req, SlaveVP *reqSlv, VSsSemEnv *semEnv) { + VSsSemReq *semReq; - semReq = VMS_PI__take_sem_reqst_from(req); - if( semReq == NULL ) return; - switch( semReq->reqType ) //sem handlers are all in other file + semReq = VMS_PI__take_sem_reqst_from(req); + if (semReq == NULL) return; + switch (semReq->reqType) //sem handlers are all in other file { - case submit_task: handleSubmitTask( semReq, semEnv); - break; - case end_task: handleEndTask( semReq, semEnv); - break; - case send_type_to: handleSendTypeTo( semReq, semEnv); - break; - case send_from_to: handleSendFromTo( semReq, semEnv); - break; - case receive_type_to: handleReceiveTypeTo(semReq, semEnv); - break; - case receive_from_to: handleReceiveFromTo(semReq, semEnv); - break; - case taskwait: handleTaskwait( semReq, reqSlv, semEnv); - break; - - //==================================================================== - case malloc_req: handleMalloc( semReq, reqSlv, semEnv); - break; - case free_req: handleFree( semReq, reqSlv, semEnv); - break; - case singleton_fn_start: handleStartFnSingleton(semReq, reqSlv, semEnv); - break; - case singleton_fn_end: handleEndFnSingleton( semReq, reqSlv, semEnv); - break; - case singleton_data_start:handleStartDataSingleton(semReq,reqSlv,semEnv); - break; - case singleton_data_end: handleEndDataSingleton(semReq, reqSlv, semEnv); - break; - case atomic: handleAtomic( semReq, reqSlv, semEnv); - break; - case trans_start: handleTransStart( semReq, reqSlv, semEnv); - break; - case trans_end: handleTransEnd( semReq, reqSlv, semEnv); - break; + case submit_task: handleSubmitTask(semReq, semEnv); + break; + case end_task: handleEndTask(semReq, semEnv); + break; + case send_type_to: handleSendTypeTo(semReq, semEnv); + break; + case send_from_to: handleSendFromTo(semReq, semEnv); + break; + case receive_type_to: handleReceiveTypeTo(semReq, semEnv); + break; + case receive_from_to: handleReceiveFromTo(semReq, semEnv); + break; + case taskwait: handleTaskwait(semReq, reqSlv, semEnv); + break; + + //==================================================================== + case malloc_req: handleMalloc(semReq, reqSlv, semEnv); + break; + case free_req: handleFree(semReq, reqSlv, semEnv); + break; + case singleton_fn_start: handleStartFnSingleton(semReq, reqSlv, semEnv); + break; + case singleton_fn_end: handleEndFnSingleton(semReq, reqSlv, semEnv); + break; + case singleton_data_start:handleStartDataSingleton(semReq, reqSlv, semEnv); + break; + case singleton_data_end: handleEndDataSingleton(semReq, reqSlv, semEnv); + break; + case atomic: handleAtomic(semReq, reqSlv, semEnv); + break; + case trans_start: handleTransStart(semReq, reqSlv, semEnv); + break; + case trans_end: handleTransEnd(semReq, reqSlv, semEnv); + break; } - } +} //=========================== VMS Request Handlers ============================== + /*SlaveVP dissipate -- this is NOT task-end!, only call this to get rid of * extra task slaves, and to end explicitly created threads */ inline void -handleDissipate( SlaveVP *requestingSlv, VSsSemEnv *semEnv ) - { VSsSemData *semData; - VSsTaskStub *parentTaskStub, *ownTaskStub; - - DEBUG__printf1(dbgRqstHdlr,"Dissipate request from processor %d", - requestingSlv->slaveID) - semData = (VSsSemData *)requestingSlv->semanticData; +handleDissipate(SlaveVP *requestingSlv, VSsSemEnv *semEnv) { + VSsSemData *semData; + VSsTaskStub *parentTaskStub, *ownTaskStub; - if( semData->slaveType == ExtraTaskSlv ) - { semEnv->numLiveExtraTaskSlvs -= 1; //for detecting shutdown condition - //Has no task assigned, so no parents and no children, so free self - goto FreeSlaveStateAndReturn; + DEBUG__printf1(dbgRqstHdlr, "Dissipate request from processor %d", + requestingSlv->slaveID) + semData = (VSsSemData *) requestingSlv->semanticData; + + if (semData->slaveType == ExtraTaskSlv) { + semEnv->numLiveExtraTaskSlvs -= 1; //for detecting shutdown condition + //Has no task assigned, so no parents and no children, so free self + goto FreeSlaveStateAndReturn; } - if( semData->slaveType == SlotTaskSlv ) - { //should never call dissipate on a slot assigned slave - VMS_PI__throw_exception( "dissipate a slot-assigned slave", requestingSlv, NULL ); + if (semData->slaveType == SlotTaskSlv) { //should never call dissipate on a slot assigned slave + VMS_PI__throw_exception("dissipate a slot-assigned slave", requestingSlv, NULL); } - //if make it to here, then is a thread slave ending - semEnv->numLiveThreadSlvs -= 1; //for detecting shutdown condition + //if make it to here, then is a thread slave ending + semEnv->numLiveThreadSlvs -= 1; //for detecting shutdown condition - ownTaskStub = semData->taskStub; - parentTaskStub = ownTaskStub->parentTaskStub; - parentTaskStub->numLiveChildThreads -= 1; //not freed, even if ended - - //if all children ended, then free this task's stub - // else, keep stub around, and last child will free it (below) - if( ownTaskStub->numLiveChildTasks == 0 && - ownTaskStub->numLiveChildThreads == 0 ) - free_task_stub( ownTaskStub ); - else - ownTaskStub->isEnded = TRUE; //for children to see when they end + ownTaskStub = semData->taskStub; + parentTaskStub = ownTaskStub->parentTaskStub; + parentTaskStub->numLiveChildThreads -= 1; //not freed, even if ended - //Now, check on parents waiting on child threads to end - if( parentTaskStub->isWaitingForChildThreadsToEnd && - parentTaskStub->numLiveChildThreads == 0 ) - { parentTaskStub->isWaitingForChildThreadsToEnd = FALSE; - if( parentTaskStub->isWaitingForChildTasksToEnd ) - return; //still waiting on tasks (should be impossible) - else //parent free to resume - resume_slaveVP( parentTaskStub->slaveAssignedTo, semEnv ); - } - - //check if this is last child of ended parent (note, not possible to - // have more than one level of ancestor waiting to be freed) - if( parentTaskStub->isEnded ) - { if( parentTaskStub->numLiveChildTasks == 0 && - parentTaskStub->numLiveChildThreads == 0 ) - free_task_stub( parentTaskStub ); //just stub, semData already freed + //if all children ended, then free this task's stub + // else, keep stub around, and last child will free it (below) + if (ownTaskStub->numLiveChildTasks == 0 && + ownTaskStub->numLiveChildThreads == 0) + free_task_stub(ownTaskStub); + else + ownTaskStub->isEnded = TRUE; //for children to see when they end + + //Now, check on parents waiting on child threads to end + if (parentTaskStub->isWaitingForChildThreadsToEnd && + parentTaskStub->numLiveChildThreads == 0) { + parentTaskStub->isWaitingForChildThreadsToEnd = FALSE; + if (parentTaskStub->isWaitingForChildTasksToEnd) + return; //still waiting on tasks (should be impossible) + else //parent free to resume + resume_slaveVP(parentTaskStub->slaveAssignedTo, semEnv); } - //Free the semData and requesting slave's base state for all cases - FreeSlaveStateAndReturn: - VMS_PI__free( semData ); - VMS_PI__dissipate_slaveVP( requestingSlv ); - return; + //check if this is last child of ended parent (note, not possible to + // have more than one level of ancestor waiting to be freed) + if (parentTaskStub->isEnded) { + if (parentTaskStub->numLiveChildTasks == 0 && + parentTaskStub->numLiveChildThreads == 0) + free_task_stub(parentTaskStub); //just stub, semData already freed + } + + //Free the semData and requesting slave's base state for all cases +FreeSlaveStateAndReturn: + VMS_PI__free(semData); + VMS_PI__dissipate_slaveVP(requestingSlv); + return; //Note, this is not a location to check for shutdown because doesn't // say anything about work availability here.. check for shutdown in // places try to get work for the core (in the assigner) - } - - +} /*Re-use this in the entry-point fn */ inline SlaveVP * -VSs__create_slave_helper( TopLevelFnPtr fnPtr, void *initData, - VSsSemEnv *semEnv, int32 coreToAssignOnto ) - { SlaveVP *newSlv; - VSsSemData *semData; +VSs__create_slave_helper(TopLevelFnPtr fnPtr, void *initData, + VSsSemEnv *semEnv, int32 coreToAssignOnto) { + SlaveVP *newSlv; + VSsSemData *semData; - //This is running in master, so use internal version - newSlv = VMS_PI__create_slaveVP( fnPtr, initData ); + //This is running in master, so use internal version + newSlv = VMS_PI__create_slaveVP(fnPtr, initData); - //task slaves differ from thread slaves by the settings in the taskStub - //so, don't create task stub here, only create semData, which is same - // for all kinds of slaves - semData = VMS_PI__malloc( sizeof(VSsSemData) ); - semData->highestTransEntered = -1; - semData->lastTransEntered = NULL; - semData->needsTaskAssigned = TRUE; - semData->taskStub = NULL; + //task slaves differ from thread slaves by the settings in the taskStub + //so, don't create task stub here, only create semData, which is same + // for all kinds of slaves + semData = VMS_PI__malloc(sizeof (VSsSemData)); + semData->highestTransEntered = -1; + semData->lastTransEntered = NULL; + semData->needsTaskAssigned = TRUE; + semData->taskStub = NULL; + + newSlv->semanticData = semData; + + //=================== Assign new processor to a core ===================== +#ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE + newSlv->coreAnimatedBy = 0; + +#else + //Assigning slaves to cores is part of SSR code.. + if (coreToAssignOnto < 0 || coreToAssignOnto >= NUM_CORES) { //out-of-range, so round-robin assignment + newSlv->coreAnimatedBy = semEnv->nextCoreToGetNewSlv; + + if (semEnv->nextCoreToGetNewSlv >= NUM_CORES - 1) + semEnv->nextCoreToGetNewSlv = 0; + else + semEnv->nextCoreToGetNewSlv += 1; + } else //core num in-range, so use it + { + newSlv->coreAnimatedBy = coreToAssignOnto; + } +#endif + //======================================================================== - newSlv->semanticData = semData; - - //=================== Assign new processor to a core ===================== - #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE - newSlv->coreAnimatedBy = 0; - - #else - //Assigning slaves to cores is part of SSR code.. - if(coreToAssignOnto < 0 || coreToAssignOnto >= NUM_CORES ) - { //out-of-range, so round-robin assignment - newSlv->coreAnimatedBy = semEnv->nextCoreToGetNewSlv; - - if( semEnv->nextCoreToGetNewSlv >= NUM_CORES - 1 ) - semEnv->nextCoreToGetNewSlv = 0; - else - semEnv->nextCoreToGetNewSlv += 1; - } - else //core num in-range, so use it - { newSlv->coreAnimatedBy = coreToAssignOnto; - } - #endif - //======================================================================== - - return newSlv; - } + return newSlv; +} VSsTaskStub * -create_thread_task_stub( void *initData ) - { VSsTaskStub *newStub; - - newStub = VMS_PI__malloc( sizeof(VSsTaskStub) ); - newStub->numBlockingProp = 0; - newStub->slaveAssignedTo = NULL; //set later - newStub->taskType = IS_A_THREAD; - newStub->ptrEntries = NULL; - newStub->args = initData; - newStub->numLiveChildTasks = 0; - newStub->numLiveChildThreads = 0; - newStub->parentTaskStub = NULL; - newStub->isWaitingForChildTasksToEnd = FALSE; - newStub->isWaitingForChildThreadsToEnd = FALSE; - newStub->taskID = NULL; +create_thread_task_stub(void *initData) { + VSsTaskStub *newStub; - return newStub; - } + newStub = VMS_PI__malloc(sizeof (VSsTaskStub)); + newStub->numBlockingProp = 0; + newStub->slaveAssignedTo = NULL; //set later + newStub->taskType = IS_A_THREAD; + newStub->ptrEntries = NULL; + newStub->args = initData; + newStub->numLiveChildTasks = 0; + newStub->numLiveChildThreads = 0; + newStub->parentTaskStub = NULL; + newStub->isWaitingForChildTasksToEnd = FALSE; + newStub->isWaitingForChildThreadsToEnd = FALSE; + newStub->taskID = NULL; + + return newStub; +} /*Application invokes this when it explicitly creates a thread via the * "VSs__create_thread()" command. @@ -417,89 +408,91 @@ *When the slave calls dissipate, have to recycle the task stub. */ inline void -handleCreate( VMSReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv ) - { VSsSemReq *semReq; - SlaveVP *newSlv; - VSsSemData *semData, *parentSemData; - - semReq = VMS_PI__take_sem_reqst_from( req ); +handleCreate(VMSReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv) { + VSsSemReq *semReq; + SlaveVP *newSlv; + VSsSemData *semData, *parentSemData; - semEnv->numLiveThreadSlvs += 1; - - //Deceptive -- must work when creator is a normal task, or seed, - // or another thd.. think have valid sem data and task stub for all - //This hdlr is NOT called when creating the seed slave - parentSemData = (VSsSemData *)semReq->callingSlv->semanticData; - parentSemData->taskStub->numLiveChildThreads += 1; + semReq = VMS_PI__take_sem_reqst_from(req); - //use an idle "extra" slave, if have one - newSlv = readPrivQ( semEnv->freeExtraTaskSlvQ ); - if( newSlv != NULL ) //got an idle one, so reset it - { semData = (VSsSemData *)newSlv->semanticData; - semData->highestTransEntered = -1; - semData->lastTransEntered = NULL; - VMS_int__reset_slaveVP_to_TopLvlFn( newSlv, semReq->fnPtr, - semReq->initData ); - } - else //no idle ones, create a new - { newSlv = VSs__create_slave_helper( semReq->fnPtr, semReq->initData, - semEnv, semReq->coreToAssignOnto ); - semData = (VSsSemData *)newSlv->semanticData; + semEnv->numLiveThreadSlvs += 1; + + //Deceptive -- must work when creator is a normal task, or seed, + // or another thd.. think have valid sem data and task stub for all + //This hdlr is NOT called when creating the seed slave + parentSemData = (VSsSemData *) semReq->callingSlv->semanticData; + parentSemData->taskStub->numLiveChildThreads += 1; + + //use an idle "extra" slave, if have one + newSlv = readPrivQ(semEnv->freeExtraTaskSlvQ); + if (newSlv != NULL) //got an idle one, so reset it + { + semData = (VSsSemData *) newSlv->semanticData; + semData->highestTransEntered = -1; + semData->lastTransEntered = NULL; + VMS_int__reset_slaveVP_to_TopLvlFn(newSlv, semReq->fnPtr, + semReq->initData); + } else //no idle ones, create a new + { + newSlv = VSs__create_slave_helper(semReq->fnPtr, semReq->initData, + semEnv, semReq->coreToAssignOnto); + semData = (VSsSemData *) newSlv->semanticData; } - //now, create a new task and assign to the thread - semData->needsTaskAssigned = FALSE; //thread has a permanent task - semData->taskStub = create_thread_task_stub( semReq->initData ); - semData->taskStub->parentTaskStub = parentSemData->taskStub; - semData->slaveType = ThreadSlv; //this hdlr only creates thread slvs + //now, create a new task and assign to the thread + semData->needsTaskAssigned = FALSE; //thread has a permanent task + semData->taskStub = create_thread_task_stub(semReq->initData); + semData->taskStub->parentTaskStub = parentSemData->taskStub; + semData->slaveType = ThreadSlv; //this hdlr only creates thread slvs - DEBUG__printf2(dbgRqstHdlr,"Create from: %d, new VP: %d", - requestingSlv->slaveID, newSlv->slaveID) + DEBUG__printf2(dbgRqstHdlr, "Create from: %d, new VP: %d", + requestingSlv->slaveID, newSlv->slaveID) - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC - Dependency newd; - newd.from_vp = requestingSlv->slaveID; - newd.from_task = requestingSlv->assignCount; - newd.to_vp = newSlv->slaveID; - newd.to_task = 1; - addToListOfArrays(Dependency,newd,semEnv->commDependenciesList); - #endif +#ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + Dependency newd; + newd.from_vp = requestingSlv->slaveID; + newd.from_task = requestingSlv->assignCount; + newd.to_vp = newSlv->slaveID; + newd.to_task = 1; + addToListOfArrays(Dependency, newd, semEnv->commDependenciesList); +#endif - //For VSs, caller needs ptr to created thread returned to it - requestingSlv->dataRetFromReq = newSlv; - resume_slaveVP(requestingSlv , semEnv ); - resume_slaveVP( newSlv, semEnv ); - } + //For VSs, caller needs ptr to created thread returned to it + requestingSlv->dataRetFromReq = newSlv; + resume_slaveVP(requestingSlv, semEnv); + resume_slaveVP(newSlv, semEnv); +} //=========================== Helper ============================== + void -resume_slaveVP( SlaveVP *slave, VSsSemEnv *semEnv ) - { - //both suspended tasks and suspended explicit slaves resumed with this - writePrivQ( slave, semEnv->slavesReadyToResumeQ ); - - #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS -/* - int lastRecordIdx = slave->counter_history_array_info->numInArray -1; - CounterRecord* lastRecord = slave->counter_history[lastRecordIdx]; - saveLowTimeStampCountInto(lastRecord->unblocked_timestamp); -*/ - #endif - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC - slave->assignCount++; //Somewhere here! - Unit newu; - newu.vp = slave->slaveID; - newu.task = slave->assignCount; - addToListOfArrays(Unit,newu,semEnv->unitList); - - if (slave->assignCount > 1){ +resume_slaveVP(SlaveVP *slave, VSsSemEnv *semEnv) { + //both suspended tasks and suspended explicit slaves resumed with this + writePrivQ(slave, semEnv->slavesReadyToResumeQ); + +#ifdef HOLISTIC__TURN_ON_PERF_COUNTERS + /* + int lastRecordIdx = slave->counter_history_array_info->numInArray -1; + CounterRecord* lastRecord = slave->counter_history[lastRecordIdx]; + saveLowTimeStampCountInto(lastRecord->unblocked_timestamp); + */ +#endif +#ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + /* + slave->assignCount++; //Somewhere here! + Unit newu; + newu.vp = slave->slaveID; + newu.task = slave->assignCount; + addToListOfArrays(Unit, newu, semEnv->unitList); + + if (slave->assignCount > 1) { Dependency newd; newd.from_vp = slave->slaveID; newd.from_task = slave->assignCount - 1; newd.to_vp = slave->slaveID; newd.to_task = slave->assignCount; - addToListOfArrays(Dependency, newd ,semEnv->ctlDependenciesList); - } - #endif - } + addToListOfArrays(Dependency, newd, semEnv->ctlDependenciesList); + }*/ +#endif +} diff -r 459055db7fc0 -r 1ffd5df22df9 VSs_Request_Handlers.c --- a/VSs_Request_Handlers.c Thu Aug 23 03:21:03 2012 -0700 +++ b/VSs_Request_Handlers.c Tue Aug 28 15:33:16 2012 +0200 @@ -18,7 +18,7 @@ //=========================== Local Fn Prototypes =========================== void -resume_slaveVP( SlaveVP *slave, VSsSemEnv *semEnv ); +resume_slaveVP(SlaveVP *slave, VSsSemEnv *semEnv); @@ -29,94 +29,97 @@ /*Only clone the elements of req used in these reqst handlers */ VSsSemReq * -cloneReq( VSsSemReq *semReq ) - { VSsSemReq *clonedReq; +cloneReq(VSsSemReq *semReq) { + VSsSemReq *clonedReq; - clonedReq = VMS_PI__malloc( sizeof(VSsSemReq) ); - clonedReq->reqType = semReq->reqType; - clonedReq->senderSlv = semReq->senderSlv; - clonedReq->receiverSlv= semReq->receiverSlv; - clonedReq->msg = semReq->msg; - clonedReq->nextReqInHashEntry = NULL; - - return clonedReq; - } + clonedReq = VMS_PI__malloc(sizeof (VSsSemReq)); + clonedReq->reqType = semReq->reqType; + clonedReq->senderSlv = semReq->senderSlv; + clonedReq->receiverSlv = semReq->receiverSlv; + clonedReq->msg = semReq->msg; + clonedReq->nextReqInHashEntry = NULL; - + return clonedReq; +} HashEntry * -giveEntryElseInsertReqst32( int32 *key, VSsSemReq *semReq, - HashTable *commHashTbl ) - { HashEntry *entry; - VSsSemReq *waitingReq; +giveEntryElseInsertReqst32(int32 *key, VSsSemReq *semReq, + HashTable *commHashTbl) { + HashEntry *entry; + VSsSemReq *waitingReq; - entry = getEntryFromTable32( key, commHashTbl ); - if( entry == NULL ) - { //no waiting sends or receives, so add this request and exit - // note: have to clone the request because it's on stack of sender - addValueIntoTable32( key, cloneReq( semReq ), commHashTbl ); - return NULL; + entry = getEntryFromTable32(key, commHashTbl); + if (entry == NULL) { //no waiting sends or receives, so add this request and exit + // note: have to clone the request because it's on stack of sender + addValueIntoTable32(key, cloneReq(semReq), commHashTbl); + return NULL; } - waitingReq = (VSsSemReq *)entry->content; - if( waitingReq == NULL ) //might happen when last waiting gets paired - { //no waiting sends or receives, so add this request and exit - entry->content = semReq; - return NULL; + waitingReq = (VSsSemReq *) entry->content; + if (waitingReq == NULL) //might happen when last waiting gets paired + { //no waiting sends or receives, so add this request and exit + entry->content = semReq; + return NULL; } - return entry; - } + return entry; +} - inline VSsPointerEntry * -create_pointer_entry( ) - { VSsPointerEntry *newEntry; - - newEntry = VMS_PI__malloc( sizeof(VSsPointerEntry) ); - newEntry->hasEnabledNonFinishedWriter = FALSE; - newEntry->numEnabledNonDoneReaders = 0; - newEntry->waitersQ = makePrivQ(); - - return newEntry; - } +create_pointer_entry() { + VSsPointerEntry *newEntry; + + newEntry = VMS_PI__malloc(sizeof (VSsPointerEntry)); + newEntry->hasEnabledNonFinishedWriter = FALSE; + newEntry->numEnabledNonDoneReaders = 0; + newEntry->waitersQ = makePrivQ(); +#ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + newEntry->lastWriterVP = 0; + newEntry->lastWriterTask = 0; +#endif + return newEntry; +} /*malloc's space and initializes fields -- and COPIES the arg values * to new space */ inline VSsTaskStub * -create_task_stub( VSsTaskType *taskType, void **args ) - { void **newArgs; - VSsTaskStub* newStub = VMS_int__malloc( sizeof(VSsTaskStub) + taskType->sizeOfArgs ); - newStub->numBlockingProp = taskType->numCtldArgs; - newStub->slaveAssignedTo = NULL; - newStub->taskType = taskType; - newStub->ptrEntries = - VMS_int__malloc( taskType->numCtldArgs * sizeof(VSsPointerEntry *) ); - newArgs = (void **)( (uint8 *)newStub + sizeof(VSsTaskStub) ); - newStub->args = newArgs; - newStub->numLiveChildTasks = 0; - newStub->numLiveChildThreads = 0; - newStub->isEnded = FALSE; - - //Copy the arg-pointers.. can be more arguments than just the ones - // that StarSs uses to control ordering of task execution. - memcpy( newArgs, args, taskType->sizeOfArgs ); - - return newStub; - } +create_task_stub(VSsTaskType *taskType, void **args) { + void **newArgs; + VSsTaskStub* newStub = VMS_int__malloc(sizeof (VSsTaskStub) + taskType->sizeOfArgs); + newStub->numBlockingProp = taskType->numCtldArgs; + newStub->slaveAssignedTo = NULL; + newStub->taskType = taskType; + newStub->ptrEntries = + VMS_int__malloc(taskType->numCtldArgs * sizeof (VSsPointerEntry *)); + newArgs = (void **) ((uint8 *) newStub + sizeof (VSsTaskStub)); + newStub->args = newArgs; + newStub->numLiveChildTasks = 0; + newStub->numLiveChildThreads = 0; + newStub->isWaitingForChildTasksToEnd = FALSE; + newStub->isWaitingForChildThreadsToEnd = FALSE; + newStub->isEnded = FALSE; + newStub->taskID = NULL; + newStub->parentTaskStub = NULL; + //Copy the arg-pointers.. can be more arguments than just the ones + // that StarSs uses to control ordering of task execution. + memcpy(newArgs, args, taskType->sizeOfArgs); + + return newStub; +} inline VSsTaskStubCarrier * -create_task_carrier( VSsTaskStub *taskStub, int32 argNum, int32 rdOrWrite ) - { VSsTaskStubCarrier *newCarrier; - - newCarrier = VMS_PI__malloc( sizeof(VSsTaskStubCarrier) ); - newCarrier->taskStub = taskStub; - newCarrier->argNum = argNum; - newCarrier->isReader = rdOrWrite == READER; - } +create_task_carrier(VSsTaskStub *taskStub, int32 argNum, int32 rdOrWrite) { + VSsTaskStubCarrier *newCarrier; + + newCarrier = VMS_PI__malloc(sizeof (VSsTaskStubCarrier)); + newCarrier->taskStub = taskStub; + newCarrier->argNum = argNum; + newCarrier->isReader = rdOrWrite == READER; +} //========================================================================== // // + /*Submit Task * *Uses a hash table to match the arg-pointers to each other. So, an @@ -215,126 +218,115 @@ *That should be it -- that should work. */ inline void -handleSubmitTask( VSsSemReq *semReq, VSsSemEnv *semEnv ) - { uint32 key[3]; - HashEntry *rawHashEntry; //has char *, but use with uint32 * - VSsPointerEntry *ptrEntry; //contents of hash table entry for an arg pointer - void **args; - VSsTaskStub *taskStub; - VSsTaskType *taskType; - VSsTaskStubCarrier *taskCarrier; - - HashTable * - argPtrHashTbl = semEnv->argPtrHashTbl; - +handleSubmitTask(VSsSemReq *semReq, VSsSemEnv *semEnv) { + uint32 key[3]; + HashEntry *rawHashEntry; //has char *, but use with uint32 * + VSsPointerEntry *ptrEntry; //contents of hash table entry for an arg pointer + void **args; + VSsTaskStub *taskStub; + VSsTaskType *taskType; + VSsTaskStubCarrier *taskCarrier; + + HashTable * + argPtrHashTbl = semEnv->argPtrHashTbl; + //suspending a task always makes the slave into an extra slot slave, // because it ends up in the resumeQ, even when resumes immediately. //Eventually task_end will put the slave into the freeExtraTaskSlvQ replaceWithNewSlotSlvIfNeeded( semReq->callingSlv, semEnv ); - - /* ========================== creation ========================== - * - *At creation, make a task-stub. Set the count of blocking propendents - * to the number of controlled arguments (a task can have - * arguments that are not controlled by the language, like simple integer - * inputs from the sequential portion. Note that all controlled arguments - * are pointers, and marked as controlled in the application code). - */ - args = semReq->args; - taskType = semReq->taskType; - taskStub = create_task_stub( taskType, args );//copies arg ptrs - taskStub->numBlockingProp = taskType->numCtldArgs; - taskStub->taskID = semReq->taskID; //may be NULL - - VSsSemData* - parentSemData = (VSsSemData*) semReq->callingSlv->semanticData; - taskStub->parentTaskStub = (void*) parentSemData->taskStub; - parentSemData->taskStub->numLiveChildTasks += 1; - + + /* ========================== creation ========================== + * + *At creation, make a task-stub. Set the count of blocking propendents + * to the number of controlled arguments (a task can have + * arguments that are not controlled by the language, like simple integer + * inputs from the sequential portion. Note that all controlled arguments + * are pointers, and marked as controlled in the application code). + */ + args = semReq->args; + taskType = semReq->taskType; + taskStub = create_task_stub(taskType, args); //copies arg ptrs + taskStub->numBlockingProp = taskType->numCtldArgs; + taskStub->taskID = semReq->taskID; //may be NULL + + VSsSemData* + parentSemData = (VSsSemData*) semReq->callingSlv->semanticData; + taskStub->parentTaskStub = (void*) parentSemData->taskStub; + parentSemData->taskStub->numLiveChildTasks += 1; + //DEBUG__printf3(dbgRqstHdlr,"Submit req from slaveID: %d, from task: %d, for task: %d", semReq->callingSlv->slaveID, parentSemData->taskStub->taskID[1], taskStub->taskID[1]) - DEBUG__printf2(dbgRqstHdlr,"Submit req from slaveID: %d, for task: %d", semReq->callingSlv->slaveID, taskStub->taskID[1]) - - /*The controlled arguments are then processed one by one. - *Processing an argument means getting the hash of the pointer. Then, - * looking up the hash entry. (If none, create one). - */ - int32 argNum; - for( argNum = 0; argNum < taskType->numCtldArgs; argNum++ ) - { - key[0] = 2; //two 32b values in key - *( (uint64*)&key[1]) = (uint64)args[argNum]; //write 64b into two 32b + if(semReq->taskID) { DEBUG__printf2(dbgRqstHdlr,"Submit req from slaveID: %d, for task: %d", semReq->callingSlv->slaveID, taskStub->taskID[1]) } + else { DEBUG__printf1(dbgRqstHdlr,"Submit req from slaveID: %d, for anonymous task", semReq->callingSlv->slaveID) } + /*The controlled arguments are then processed one by one. + *Processing an argument means getting the hash of the pointer. Then, + * looking up the hash entry. (If none, create one). + */ + int32 argNum; + for (argNum = 0; argNum < taskType->numCtldArgs; argNum++) { + key[0] = 2; //two 32b values in key + *((uint64*) & key[1]) = (uint64) args[argNum]; //write 64b into two 32b - /*If the hash entry was chained, put it at the - * start of the chain. (Means no-longer-used pointers accumulate - * at end of chain, decide garbage collection later) */ - rawHashEntry = getEntryFromTable32( key, argPtrHashTbl ); - if( rawHashEntry == NULL ) - { //adding a value auto-creates the hash-entry - ptrEntry = create_pointer_entry(); - rawHashEntry = addValueIntoTable32( key, ptrEntry, argPtrHashTbl ); - } - else - { ptrEntry = (VSsPointerEntry *)rawHashEntry->content; - if( ptrEntry == NULL ) - { ptrEntry = create_pointer_entry(); + /*If the hash entry was chained, put it at the + * start of the chain. (Means no-longer-used pointers accumulate + * at end of chain, decide garbage collection later) */ + rawHashEntry = getEntryFromTable32(key, argPtrHashTbl); + if (rawHashEntry == NULL) { //adding a value auto-creates the hash-entry + ptrEntry = create_pointer_entry(); rawHashEntry = addValueIntoTable32(key, ptrEntry, argPtrHashTbl); - } - } - taskStub->ptrEntries[argNum] = ptrEntry; - - /*Have the hash entry. - *If the arg is a reader and the entry does not have an enabled - * non-finished writer, and the queue is empty. */ - if( taskType->argTypes[argNum] == READER ) - { if( !ptrEntry->hasEnabledNonFinishedWriter && - isEmptyPrivQ( ptrEntry->waitersQ ) ) - { /*The reader is free. So, decrement the blocking-propendent + } else { + ptrEntry = (VSsPointerEntry *) rawHashEntry->content; + if (ptrEntry == NULL) { + ptrEntry = create_pointer_entry(); + rawHashEntry = addValueIntoTable32(key, ptrEntry, argPtrHashTbl); + } + } + taskStub->ptrEntries[argNum] = ptrEntry; + + /*Have the hash entry. + *If the arg is a reader and the entry does not have an enabled + * non-finished writer, and the queue is empty. */ + if (taskType->argTypes[argNum] == READER) { + if (!ptrEntry->hasEnabledNonFinishedWriter && + isEmptyPrivQ(ptrEntry->waitersQ)) { /*The reader is free. So, decrement the blocking-propendent * count in the task-stub. If the count is zero, then put the * task-stub into the readyQ. At the same time, increment * the hash-entry's count of enabled and non-finished readers.*/ - taskStub->numBlockingProp -= 1; - if( taskStub->numBlockingProp == 0 ) - { writePrivQ( taskStub, semEnv->taskReadyQ ); - } - ptrEntry->numEnabledNonDoneReaders += 1; - } - else - { /*Otherwise, the reader is put into the hash-entry's Q of + taskStub->numBlockingProp -= 1; + if (taskStub->numBlockingProp == 0) { + writePrivQ(taskStub, semEnv->taskReadyQ); + } + ptrEntry->numEnabledNonDoneReaders += 1; + } else { /*Otherwise, the reader is put into the hash-entry's Q of * waiters*/ - taskCarrier = create_task_carrier( taskStub, argNum, READER ); - writePrivQ( taskCarrier, ptrEntry->waitersQ ); - } - } - else //arg is a writer - { /*the arg is a writer, plus the entry does not have a current + taskCarrier = create_task_carrier(taskStub, argNum, READER); + writePrivQ(taskCarrier, ptrEntry->waitersQ); + } + } else //arg is a writer + { /*the arg is a writer, plus the entry does not have a current * writer, plus the number of enabled non-finished readers is * zero, (the Q must be empty, else bug!) then the writer is free*/ - if( !ptrEntry->hasEnabledNonFinishedWriter && - ptrEntry->numEnabledNonDoneReaders == 0 ) - { /*Mark the entry has having a enabled and non-finished writer. + if (!ptrEntry->hasEnabledNonFinishedWriter && + ptrEntry->numEnabledNonDoneReaders == 0) { /*Mark the entry has having a enabled and non-finished writer. * Decrement the blocking-propenden count in the writer's * task-stub. If the count is zero, then put the task-stub * into the readyQ.*/ - taskStub->numBlockingProp -= 1; - if( taskStub->numBlockingProp == 0 ) - { writePrivQ( taskStub, semEnv->taskReadyQ ); - } - ptrEntry->hasEnabledNonFinishedWriter = TRUE; - } - else - {/*Otherwise, put the writer into the entry's Q of waiters.*/ - taskCarrier = create_task_carrier( taskStub, argNum, WRITER ); - writePrivQ( taskCarrier, ptrEntry->waitersQ ); - } - } + taskStub->numBlockingProp -= 1; + if (taskStub->numBlockingProp == 0) { + writePrivQ(taskStub, semEnv->taskReadyQ); + } + ptrEntry->hasEnabledNonFinishedWriter = TRUE; + } else {/*Otherwise, put the writer into the entry's Q of waiters.*/ + taskCarrier = create_task_carrier(taskStub, argNum, WRITER); + writePrivQ(taskCarrier, ptrEntry->waitersQ); + } + } } //for argNum - - - resume_slaveVP( semReq->callingSlv, semEnv ); - return; - } + resume_slaveVP(semReq->callingSlv, semEnv); + + return; +} /* ========================== end of task =========================== * @@ -372,177 +364,193 @@ * and no readers and no writers.. */ inline void -handleEndTask( VSsSemReq *semReq, VSsSemEnv *semEnv ) - { VSsPointerEntry *ptrEntry; //contents of hash table entry for an arg pointer - void **args; - VSsSemData *endingSlvSemData; - VSsTaskStub *endingTaskStub, *waitingTaskStub, *parent; - VSsTaskType *endingTaskType; - VSsTaskStubCarrier *waitingTaskCarrier; - VSsPointerEntry **ptrEntries; - - - endingSlvSemData = (VSsSemData *)semReq->callingSlv->semanticData; - endingTaskStub = endingSlvSemData->taskStub; - args = endingTaskStub->args; - endingTaskType = endingTaskStub->taskType; - ptrEntries = endingTaskStub->ptrEntries; //saved in stub when create - - DEBUG__printf2(dbgRqstHdlr,"EndTask req from slaveID: %d, task: %d",semReq->callingSlv->slaveID, endingTaskStub->taskID[1]) +handleEndTask(VSsSemReq *semReq, VSsSemEnv *semEnv) { + VSsPointerEntry *ptrEntry; //contents of hash table entry for an arg pointer + void **args; + VSsSemData *endingSlvSemData; + VSsTaskStub *endingTaskStub, *waitingTaskStub, *parent; + VSsTaskType *endingTaskType; + VSsTaskStubCarrier *waitingTaskCarrier; + VSsPointerEntry **ptrEntries; + + + endingSlvSemData = (VSsSemData *) semReq->callingSlv->semanticData; + endingTaskStub = endingSlvSemData->taskStub; + args = endingTaskStub->args; + endingTaskType = endingTaskStub->taskType; + ptrEntries = endingTaskStub->ptrEntries; //saved in stub when create + + if(semReq->taskID) { DEBUG__printf2(dbgRqstHdlr,"EndTask req from slaveID: %d, task: %d",semReq->callingSlv->slaveID, endingTaskStub->taskID[1]) } + else {DEBUG__printf1(dbgRqstHdlr,"EndTask req from slaveID: %d",semReq->callingSlv->slaveID)} - //Check if parent was waiting on this task - parent = (VSsTaskStub *) endingTaskStub->parentTaskStub; - parent->numLiveChildTasks -= 1; - if( parent->isWaitingForChildTasksToEnd && parent->numLiveChildTasks == 0) - { - parent->isWaitingForChildTasksToEnd = FALSE; - resume_slaveVP( parent->slaveAssignedTo, semEnv ); + //Check if parent was waiting on this task + parent = (VSsTaskStub *) endingTaskStub->parentTaskStub; + parent->numLiveChildTasks -= 1; + +#ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + if (parent->isWaitingForChildTasksToEnd) { + Dependency newd; + newd.from_vp = semReq->callingSlv->slaveID; + newd.from_task = semReq->callingSlv->assignCount; + newd.to_vp = parent->slaveAssignedTo->slaveID; + newd.to_task = parent->slaveAssignedTo->assignCount + 1; + addToListOfArrays(Dependency, newd, semEnv->commDependenciesList); + } +#endif + + if (parent->isWaitingForChildTasksToEnd && parent->numLiveChildTasks == 0) { + parent->isWaitingForChildTasksToEnd = FALSE; + resume_slaveVP(parent->slaveAssignedTo, semEnv); } - - //Check if parent ended, and this was last descendent, then free it - if( parent->isEnded && parent->numLiveChildTasks == 0 ) - { VMS_PI__free( parent ); + + //Check if parent ended, and this was last descendent, then free it + if (parent->isEnded && parent->numLiveChildTasks == 0) { + VMS_PI__free(parent); } - - - //Now, update state of dependents and start ready tasks - /*The task's controlled arguments are processed one by one. - *Processing an argument means getting arg-pointer's entry. - */ - int32 argNum; - for( argNum = 0; argNum < endingTaskType->numCtldArgs; argNum++ ) - { - /* commented out 'cause remembering entry ptr when create stub - key[0] = 2; //says are 2 32b values in key - *( (uint64*)&key[1] ) = args[argNum]; //write 64b ptr into two 32b - /*If the hash entry was chained, put it at the - * start of the chain. (Means no-longer-used pointers accumulate - * at end of chain, decide garbage collection later) - */ - /*NOTE: don't do hash lookups here, instead, have a pointer to the - * hash entry inside task-stub, put there during task creation. - rawHashEntry = getEntryFromTable32( key, ptrHashTbl ); - ptrEntry = (VSsPointerEntry *)rawHashEntry->content; - if( ptrEntry == NULL ) - VMS_App__throw_exception("hash entry NULL", NULL, NULL); - */ - - ptrEntry = ptrEntries[argNum]; - /*check if the ending task was reader of this arg*/ - if( endingTaskType->argTypes[argNum] == READER ) - { /*then decrement the enabled and non-finished reader-count in - * the hash-entry. */ - ptrEntry->numEnabledNonDoneReaders -= 1; - - /*If the count becomes zero, then take the next entry from the Q. - *It should be a writer, or else there's a bug in this algorithm.*/ - if( ptrEntry->numEnabledNonDoneReaders == 0 ) - { waitingTaskCarrier = readPrivQ( ptrEntry->waitersQ ); - if( waitingTaskCarrier == NULL ) - { //TODO: looks safe to delete the ptr entry at this point - continue; //next iter of loop - } - if( waitingTaskCarrier->isReader ) - VMS_App__throw_exception("READER waiting", NULL, NULL); - + + //Now, update state of dependents and start ready tasks + /*The task's controlled arguments are processed one by one. + *Processing an argument means getting arg-pointer's entry. + */ + int32 argNum; + for (argNum = 0; argNum < endingTaskType->numCtldArgs; argNum++) { + /* commented out 'cause remembering entry ptr when create stub + key[0] = 2; //says are 2 32b values in key + *( (uint64*)&key[1] ) = args[argNum]; //write 64b ptr into two 32b + + /*If the hash entry was chained, put it at the + * start of the chain. (Means no-longer-used pointers accumulate + * at end of chain, decide garbage collection later) + */ + /*NOTE: don't do hash lookups here, instead, have a pointer to the + * hash entry inside task-stub, put there during task creation. + rawHashEntry = getEntryFromTable32( key, ptrHashTbl ); + ptrEntry = (VSsPointerEntry *)rawHashEntry->content; + if( ptrEntry == NULL ) + VMS_App__throw_exception("hash entry NULL", NULL, NULL); + */ + + ptrEntry = ptrEntries[argNum]; + /*check if the ending task was reader of this arg*/ + if (endingTaskType->argTypes[argNum] == READER) { /*then decrement the enabled and non-finished reader-count in + * the hash-entry. */ + ptrEntry->numEnabledNonDoneReaders -= 1; +#ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + if (ptrEntry->lastWriterVP) { + Dependency newd; + newd.from_vp = ptrEntry->lastWriterVP; + newd.from_task = ptrEntry->lastWriterTask; + newd.to_vp = semReq->callingSlv->slaveID; + newd.to_task = semReq->callingSlv->assignCount; + addToListOfArrays(Dependency, newd, semEnv->dataDependenciesList); + } +#endif + /*If the count becomes zero, then take the next entry from the Q. + *It should be a writer, or else there's a bug in this algorithm.*/ + if (ptrEntry->numEnabledNonDoneReaders == 0) { + waitingTaskCarrier = readPrivQ(ptrEntry->waitersQ); + if (waitingTaskCarrier == NULL) { //TODO: looks safe to delete the ptr entry at this point + continue; //next iter of loop + } + if (waitingTaskCarrier->isReader) + VMS_App__throw_exception("READER waiting", NULL, NULL); + + waitingTaskStub = waitingTaskCarrier->taskStub; + + /*Set the hash-entry to have an enabled non-finished writer.*/ + ptrEntry->hasEnabledNonFinishedWriter = TRUE; + + /* Decrement the blocking-propendent-count of the writer's + * task-stub. If the count has reached zero, then put the + * task-stub into the readyQ.*/ + waitingTaskStub->numBlockingProp -= 1; + if (waitingTaskStub->numBlockingProp == 0) { + writePrivQ(waitingTaskStub, semEnv->taskReadyQ); + } + } + } else /*the ending task is a writer of this arg*/ { /*clear the enabled non-finished writer flag of the hash-entry.*/ + ptrEntry->hasEnabledNonFinishedWriter = FALSE; + #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + ptrEntry->lastWriterVP = semReq->callingSlv->slaveID; + ptrEntry->lastWriterTask = semReq->callingSlv->assignCount; + #endif + + /*Take the next waiter from the hash-entry's Q.*/ + waitingTaskCarrier = readPrivQ(ptrEntry->waitersQ); + if (waitingTaskCarrier == NULL) { //TODO: looks safe to delete ptr entry at this point + continue; //go to next iter of loop, done here. + } waitingTaskStub = waitingTaskCarrier->taskStub; - - /*Set the hash-entry to have an enabled non-finished writer.*/ - ptrEntry->hasEnabledNonFinishedWriter = TRUE; - - /* Decrement the blocking-propendent-count of the writer's - * task-stub. If the count has reached zero, then put the - * task-stub into the readyQ.*/ - waitingTaskStub->numBlockingProp -= 1; - if( waitingTaskStub->numBlockingProp == 0 ) - { writePrivQ( waitingTaskStub, semEnv->taskReadyQ ); - } - } - } - else /*the ending task is a writer of this arg*/ - { /*clear the enabled non-finished writer flag of the hash-entry.*/ - ptrEntry->hasEnabledNonFinishedWriter = FALSE; - - /*Take the next waiter from the hash-entry's Q.*/ - waitingTaskCarrier = readPrivQ( ptrEntry->waitersQ ); - if( waitingTaskCarrier == NULL ) - { //TODO: looks safe to delete ptr entry at this point - continue; //go to next iter of loop, done here. - } - waitingTaskStub = waitingTaskCarrier->taskStub; - - /*If task is a writer of this hash-entry's pointer*/ - if( !waitingTaskCarrier->isReader ) - { /* then turn the flag back on.*/ - ptrEntry->hasEnabledNonFinishedWriter = TRUE; - /*Decrement the writer's blocking-propendent-count in task-stub - * If it becomes zero, then put the task-stub into the readyQ.*/ - waitingTaskStub->numBlockingProp -= 1; - if( waitingTaskStub->numBlockingProp == 0 ) - { writePrivQ( waitingTaskStub, semEnv->taskReadyQ ); - } - } - else - { /*Waiting task is a reader, so do a loop, of all waiting readers + + /*If task is a writer of this hash-entry's pointer*/ + if (!waitingTaskCarrier->isReader) { /* then turn the flag back on.*/ + ptrEntry->hasEnabledNonFinishedWriter = TRUE; + /*Decrement the writer's blocking-propendent-count in task-stub + * If it becomes zero, then put the task-stub into the readyQ.*/ + waitingTaskStub->numBlockingProp -= 1; + if (waitingTaskStub->numBlockingProp == 0) { + writePrivQ(waitingTaskStub, semEnv->taskReadyQ); + } + } else { /*Waiting task is a reader, so do a loop, of all waiting readers * until encounter a writer or waitersQ is empty*/ - while( TRUE ) /*The checks guarantee have a waiting reader*/ - { /*Increment the hash-entry's count of enabled non-finished + while (TRUE) /*The checks guarantee have a waiting reader*/ { /*Increment the hash-entry's count of enabled non-finished * readers.*/ - ptrEntry->numEnabledNonDoneReaders += 1; + ptrEntry->numEnabledNonDoneReaders += 1; - /*Decrement the blocking propendents count of the reader's - * task-stub. If it reaches zero, then put the task-stub - * into the readyQ.*/ - waitingTaskStub->numBlockingProp -= 1; - if( waitingTaskStub->numBlockingProp == 0 ) - { writePrivQ( waitingTaskStub, semEnv->taskReadyQ ); - } - /*Get next waiting task*/ - waitingTaskCarrier = peekPrivQ( ptrEntry->waitersQ ); - if( waitingTaskCarrier == NULL ) break; - if( !waitingTaskCarrier->isReader ) break; - waitingTaskCarrier = readPrivQ( ptrEntry->waitersQ ); - waitingTaskStub = waitingTaskCarrier->taskStub; - }//while waiter is a reader - }//if-else, first waiting task is a reader - }//if-else, check of ending task, whether writer or reader + /*Decrement the blocking propendents count of the reader's + * task-stub. If it reaches zero, then put the task-stub + * into the readyQ.*/ + waitingTaskStub->numBlockingProp -= 1; + if (waitingTaskStub->numBlockingProp == 0) { + writePrivQ(waitingTaskStub, semEnv->taskReadyQ); + } + /*Get next waiting task*/ + waitingTaskCarrier = peekPrivQ(ptrEntry->waitersQ); + if (waitingTaskCarrier == NULL) break; + if (!waitingTaskCarrier->isReader) break; + waitingTaskCarrier = readPrivQ(ptrEntry->waitersQ); + waitingTaskStub = waitingTaskCarrier->taskStub; + }//while waiter is a reader + }//if-else, first waiting task is a reader + }//if-else, check of ending task, whether writer or reader }//for argnum in ending task - - - //done ending the task, now free the stub + args copy - // if still has live children, then keep stub around - if( endingTaskStub->numLiveChildTasks == 0 && - endingTaskStub->numLiveChildThreads == 0 ) - { free_task_stub( endingTaskStub ); + + + //done ending the task, now free the stub + args copy + // if still has live children, then keep stub around + if (endingTaskStub->numLiveChildTasks == 0 && + endingTaskStub->numLiveChildThreads == 0) { + free_task_stub(endingTaskStub); } - - - endingSlvSemData->needsTaskAssigned = TRUE; - - //Check if the slave is an extra task slave, and put into free Q - if( endingSlvSemData->slaveType == ExtraTaskSlv ) - { writePrivQ( semReq->callingSlv, semEnv->freeExtraTaskSlvQ ); + + + endingSlvSemData->needsTaskAssigned = TRUE; + + //Check if the slave is an extra task slave, and put into free Q + if (endingSlvSemData->slaveType == ExtraTaskSlv) { + writePrivQ(semReq->callingSlv, semEnv->freeExtraTaskSlvQ); } - - //otherwise, it's a slot slave, so it will get used from matrix - // so, do nothing with it, just return - return; - } + + //otherwise, it's a slot slave, so it will get used from matrix + // so, do nothing with it, just return + return; +} inline void -free_task_stub( VSsTaskStub *stubToFree ) +free_task_stub(VSsTaskStub *stubToFree) { if(stubToFree->ptrEntries != NULL ) //a thread stub has NULL entry { VMS_PI__free( stubToFree->ptrEntries ); } VMS_PI__free( stubToFree ); - } +} //========================== Task Comm handlers =========================== //============================ Send Handlers ============================== + /*Send of Type -- The semantic request has the receiving task ID and Type * *Messages of a given Type have to be kept separate.. so need a separate @@ -554,16 +562,16 @@ * receive task, so they will stack up. */ inline void -handleSendTypeTo( VSsSemReq *semReq, VSsSemEnv *semEnv ) - { SlaveVP *senderSlv, *receiverSlv; - int32 *senderID, *receiverID; - int32 *key, keySz, receiverIDNumInt; - VSsSemReq *waitingReq; - HashEntry *entry; - HashTable *commHashTbl = semEnv->commHashTbl; - - receiverID = semReq->receiverID; //For "send", know both send & recv procrs - senderSlv = semReq->senderSlv; +handleSendTypeTo(VSsSemReq *semReq, VSsSemEnv *semEnv) { + SlaveVP *senderSlv, *receiverSlv; + int32 *senderID, *receiverID; + int32 *key, keySz, receiverIDNumInt; + VSsSemReq *waitingReq; + HashEntry *entry; + HashTable *commHashTbl = semEnv->commHashTbl; + + receiverID = semReq->receiverID; //For "send", know both send & recv procrs + senderSlv = semReq->senderSlv; DEBUG__printf2(dbgRqstHdlr,"SendType req from sender slaveID: %d, recTask: %d", senderSlv->slaveID, receiverID[1]) @@ -572,106 +580,105 @@ //Eventually task_end will put the slave into the freeExtraTaskSlvQ replaceWithNewSlotSlvIfNeeded( senderSlv, semEnv ); - receiverIDNumInt = receiverID[0] + 1; //pos 0 doesn't include itself + receiverIDNumInt = receiverID[0] + 1; //pos 0 doesn't include itself keySz = receiverIDNumInt * sizeof(int32) + 2 * sizeof(int32); - key = VMS_PI__malloc( keySz ); + key = VMS_PI__malloc(keySz); key[0] = receiverIDNumInt + 1; //loc 0 is num int32 in key memcpy( &key[1], receiverID, receiverIDNumInt * sizeof(int32) ); key[ 1 + receiverIDNumInt ] = semReq->msgType; - - entry = giveEntryElseInsertReqst32( key, semReq, commHashTbl ); - if( entry == NULL ) //was just inserted, means task has to wait + + entry = giveEntryElseInsertReqst32(key, semReq, commHashTbl); + if (entry == NULL) //was just inserted, means task has to wait { return; } - //if here, found a waiting request with same key - waitingReq = (VSsSemReq *)entry->content; + //if here, found a waiting request with same key + waitingReq = (VSsSemReq *) entry->content; - //At this point, know have waiting request(s) -- either sends or recv - //Note, can only have max of one receive waiting, and cannot have both - // sends and receives waiting (they would have paired off) - // but can have multiple sends from diff sending VPs, all same msg-type - if( waitingReq->reqType == send_type_to ) - { //waiting request is another send, so stack this up on list - // but first clone the sending request so it persists. - VSsSemReq *clonedReq = cloneReq( semReq ); - clonedReq-> nextReqInHashEntry = waitingReq->nextReqInHashEntry; - waitingReq->nextReqInHashEntry = clonedReq; - DEBUG__printf2( dbgRqstHdlr, "linked requests: %p, %p ", clonedReq,\ - waitingReq ) - return; - } - else - { - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + //At this point, know have waiting request(s) -- either sends or recv + //Note, can only have max of one receive waiting, and cannot have both + // sends and receives waiting (they would have paired off) + // but can have multiple sends from diff sending VPs, all same msg-type + if (waitingReq->reqType == send_type_to) { //waiting request is another send, so stack this up on list + // but first clone the sending request so it persists. + VSsSemReq *clonedReq = cloneReq(semReq); + clonedReq-> nextReqInHashEntry = waitingReq->nextReqInHashEntry; + waitingReq->nextReqInHashEntry = clonedReq; + DEBUG__printf2(dbgRqstHdlr, "linked requests: %p, %p ", clonedReq,\ + waitingReq) + return; + } else { + + + //set receiver slave, from the waiting request + receiverSlv = waitingReq->receiverSlv; + +#ifdef HOLISTIC__TURN_ON_OBSERVE_UCC Dependency newd; - newd.from_vp = senderID->slaveID; - newd.from_task = senderID->assignCount; - newd.to_vp = receiverID->slaveID; - newd.to_task = receiverID->assignCount +1; + newd.from_vp = senderSlv->slaveID; + newd.from_task = senderSlv->assignCount; + newd.to_vp = receiverSlv->slaveID; + newd.to_task = receiverSlv->assignCount + 1; //(newd,semEnv->commDependenciesList); - addToListOfArrays(Dependency,newd,semEnv->dynDependenciesList); - int32 groupId = semReq->msgType; - if(semEnv->ntonGroupsInfo->numInArray <= groupId){ + addToListOfArrays(Dependency, newd, semEnv->dynDependenciesList); + int32 groupId = semReq->msgType; + if (semEnv->ntonGroupsInfo->numInArray <= groupId) { makeHighestDynArrayIndexBeAtLeast(semEnv->ntonGroupsInfo, groupId); } - if(semEnv->ntonGroups[groupId] == NULL){ + if (semEnv->ntonGroups[groupId] == NULL) { semEnv->ntonGroups[groupId] = new_NtoN(groupId); } Unit u; - u.vp = senderID->slaveID; - u.task = senderID->assignCount; - addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->senders); - u.vp = receiverID->slaveID; - u.task = receiverID->assignCount +1; - addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->receivers); - #endif + u.vp = senderSlv->slaveID; + u.task = senderSlv->assignCount; + addToListOfArrays(Unit, u, semEnv->ntonGroups[groupId]->senders); + u.vp = receiverSlv->slaveID; + u.task = receiverSlv->assignCount + 1; + addToListOfArrays(Unit, u, semEnv->ntonGroups[groupId]->receivers); +#endif - //set receiver slave, from the waiting request - receiverSlv = waitingReq->receiverSlv; - - //waiting request is a receive_type_to, so it pairs to this send - //First, remove the waiting receive request from the entry - entry->content = waitingReq->nextReqInHashEntry; - VMS_PI__free( waitingReq ); //Don't use contents -- so free it - - if( entry->content == NULL ) - { //TODO: mod hash table to double-link, so can delete entry from + //waiting request is a receive_type_to, so it pairs to this send + //First, remove the waiting receive request from the entry + entry->content = waitingReq->nextReqInHashEntry; + VMS_PI__free(waitingReq); //Don't use contents -- so free it + + if (entry->content == NULL) { //TODO: mod hash table to double-link, so can delete entry from // table without hashing the key and looking it up again - deleteEntryFromTable32( (uint32*)entry->key, commHashTbl ); //frees hashEntry - } - - //attach msg that's in this send request to receiving task's Slv - // when comes back from suspend will have msg in dataRetFromReq - receiverSlv->dataRetFromReq = semReq->msg; + deleteEntryFromTable32((uint32*) entry->key, commHashTbl); //frees hashEntry + } - //bring both processors back from suspend - resume_slaveVP( senderSlv, semEnv ); - resume_slaveVP( receiverSlv, semEnv ); + //attach msg that's in this send request to receiving task's Slv + // when comes back from suspend will have msg in dataRetFromReq + receiverSlv->dataRetFromReq = semReq->msg; - return; + //bring both processors back from suspend + resume_slaveVP(senderSlv, semEnv); + resume_slaveVP(receiverSlv, semEnv); + + return; } - } +} /*Looks like can make single handler for both sends.. */ //TODO: combine both send handlers into single handler + inline void -handleSendFromTo( VSsSemReq *semReq, VSsSemEnv *semEnv) - { SlaveVP *senderSlv, *receiverSlv; - int32 *senderID, *receiverID; - int32 *key, keySz, receiverIDNumInt, senderIDNumInt; - VSsSemReq *waitingReq; - HashEntry *entry; - HashTable *commHashTbl = semEnv->commHashTbl; +handleSendFromTo(VSsSemReq *semReq, VSsSemEnv *semEnv) { + SlaveVP *senderSlv, *receiverSlv; + int32 *senderID, *receiverID; + int32 *key, keySz, receiverIDNumInt, senderIDNumInt; + VSsSemReq *waitingReq; + HashEntry *entry; + HashTable *commHashTbl = semEnv->commHashTbl; DEBUG__printf2(dbgRqstHdlr,"SendFromTo req from task %d to %d", - semReq->senderID[1],semReq->receiverID[1]) - - receiverID = semReq->receiverID; //For "send", know both send & recv procrs - senderID = semReq->senderID; - senderSlv = semReq->senderSlv; + semReq->senderID[1], semReq->receiverID[1]) + + receiverID = semReq->receiverID; //For "send", know both send & recv procrs + senderID = semReq->senderID; + senderSlv = semReq->senderSlv; //suspending a task always makes the slave into an extra slot slave, // because it ends up in the resumeQ, even when resumes immediately. @@ -679,229 +686,224 @@ replaceWithNewSlotSlvIfNeeded( senderSlv, semEnv ); receiverIDNumInt = receiverID[0] + 1; //include the count in the key - senderIDNumInt = senderID[0] + 1; + senderIDNumInt = senderID[0] + 1; keySz = (receiverIDNumInt + senderIDNumInt) * sizeof(int32) + sizeof(int32); - key = VMS_PI__malloc( keySz ); + key = VMS_PI__malloc(keySz); key[0] = receiverIDNumInt + senderIDNumInt; memcpy( &key[1], receiverID, receiverIDNumInt * sizeof(int32) ); memcpy( &key[1 + receiverIDNumInt], senderID, senderIDNumInt * sizeof(int32) ); - entry = giveEntryElseInsertReqst32( key, semReq, commHashTbl ); - if( entry == NULL ) //was just inserted, means task has to wait + entry = giveEntryElseInsertReqst32(key, semReq, commHashTbl); + if (entry == NULL) //was just inserted, means task has to wait { return; } - waitingReq = (VSsSemReq *)entry->content; + waitingReq = (VSsSemReq *) entry->content; - //At this point, know have waiting request(s) -- either sends or recv - if( waitingReq->reqType == send_from_to ) - { printf("\n ERROR: shouldn't be two send-from-tos waiting \n"); + //At this point, know have waiting request(s) -- either sends or recv + if (waitingReq->reqType == send_from_to) { + printf("\n ERROR: shouldn't be two send-from-tos waiting \n"); + } else { //waiting request is a receive, so it completes pair with this send + + //set receiver slave, from the waiting request + receiverSlv = waitingReq->receiverSlv; + +#ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + Dependency newd; + newd.from_vp = senderSlv->slaveID; + newd.from_task = senderSlv->assignCount; + newd.to_vp = receiverSlv->slaveID; + newd.to_task = receiverSlv->assignCount + 1; + //addToListOfArraysDependency(newd,semEnv->commDependenciesList); + addToListOfArrays(Dependency, newd, semEnv->commDependenciesList); +#endif + + //First, remove the waiting receive request from the entry + entry->content = waitingReq->nextReqInHashEntry; + VMS_PI__free(waitingReq); //Don't use contents -- so free it + + //can only be one waiting req for "from-to" semantics + if (entry->content != NULL) { + printf("\nERROR in handleSendFromTo\n"); + } + deleteEntryFromTable32((uint32*) entry->key, commHashTbl); //frees HashEntry + + //attach msg that's in this send request to receiving procr + // when comes back from suspend, will have msg in dataRetFromReq + receiverSlv->dataRetFromReq = semReq->msg; + + //bring both processors back from suspend + resume_slaveVP(senderSlv, semEnv); + resume_slaveVP(receiverSlv, semEnv); + + return; } - else - { //waiting request is a receive, so it completes pair with this send - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC - Dependency newd; - newd.from_vp = sendPr->slaveID; - newd.from_task = sendPr->assignCount; - newd.to_vp = receivePr->slaveID; - newd.to_task = receivePr->assignCount +1; - //addToListOfArraysDependency(newd,semEnv->commDependenciesList); - addToListOfArrays(Dependency,newd,semEnv->commDependenciesList); - #endif - - //set receiver slave, from the waiting request - receiverSlv = waitingReq->receiverSlv; - - //First, remove the waiting receive request from the entry - entry->content = waitingReq->nextReqInHashEntry; - VMS_PI__free( waitingReq ); //Don't use contents -- so free it - - //can only be one waiting req for "from-to" semantics - if( entry->content != NULL ) - { - printf("\nERROR in handleSendFromTo\n"); - } - deleteEntryFromTable32( (uint32*)entry->key, commHashTbl ); //frees HashEntry - - //attach msg that's in this send request to receiving procr - // when comes back from suspend, will have msg in dataRetFromReq - receiverSlv->dataRetFromReq = semReq->msg; - - //bring both processors back from suspend - resume_slaveVP( senderSlv, semEnv ); - resume_slaveVP( receiverSlv, semEnv ); - - return; - } - } +} //============================== Receives =========================== // +inline void +handleReceiveTypeTo(VSsSemReq *semReq, VSsSemEnv *semEnv) { + SlaveVP *senderSlv, *receiverSlv; + int32 *receiverID; + int32 *key, keySz, receiverIDNumInt; + VSsSemReq *waitingReq; + HashEntry *entry; + HashTable *commHashTbl = semEnv->commHashTbl; -inline void -handleReceiveTypeTo( VSsSemReq *semReq, VSsSemEnv *semEnv) - { SlaveVP *senderSlv, *receiverSlv; - int32 *receiverID; - int32 *key, keySz, receiverIDNumInt; - VSsSemReq *waitingReq; - HashEntry *entry; - HashTable *commHashTbl = semEnv->commHashTbl; - DEBUG__printf2(dbgRqstHdlr,"ReceiveType req to ID: %d type: %d",semReq->receiverID[1], semReq->msgType) - - receiverID = semReq->receiverID; //For "send", know both send & recv procrs - receiverSlv = semReq->receiverSlv; + + receiverID = semReq->receiverID; //For "send", know both send & recv procrs + receiverSlv = semReq->receiverSlv; //suspending a task always makes the slave into an extra slot slave, // because it ends up in the resumeQ, even when resumes immediately. //Eventually task_end will put the slave into the freeExtraTaskSlvQ replaceWithNewSlotSlvIfNeeded( receiverSlv, semEnv ); - //key is the receiverID plus the type -- have to copy them into key - receiverIDNumInt = receiverID[0] + 1; //pos 0 doesn't include itself + //key is the receiverID plus the type -- have to copy them into key + receiverIDNumInt = receiverID[0] + 1; //pos 0 doesn't include itself keySz = receiverIDNumInt * sizeof(int32) + 2 * sizeof(int32); - key = VMS_PI__malloc( keySz ); + key = VMS_PI__malloc(keySz); key[0] = receiverIDNumInt + 1; //loc 0 is num int32s in key memcpy( &key[1], receiverID, receiverIDNumInt * sizeof(int32) ); key[ 1 + receiverIDNumInt ] = semReq->msgType; - entry = giveEntryElseInsertReqst32( key, semReq, commHashTbl );//clones - if( entry == NULL ) //was just inserted, means task has to wait + entry = giveEntryElseInsertReqst32(key, semReq, commHashTbl); //clones + if (entry == NULL) //was just inserted, means task has to wait { return; } - waitingReq = (VSsSemReq *)entry->content; //previously cloned by insert + waitingReq = (VSsSemReq *) entry->content; //previously cloned by insert - //At this point, know have waiting request(s) -- should be send(s) - if( waitingReq->reqType == send_type_to ) - { - //set sending slave from the request - senderSlv = waitingReq->senderSlv; - - //waiting request is a send, so pair it with this receive - //first, remove the waiting send request from the list in entry - entry->content = waitingReq->nextReqInHashEntry; - if( entry->content == NULL ) - { deleteEntryFromTable32( (uint32*)entry->key, commHashTbl ); //frees HashEntry - } - - //attach msg that's in the send request to receiving procr - // when comes back from suspend, will have msg in dataRetFromReq - receiverSlv->dataRetFromReq = waitingReq->msg; + //At this point, know have waiting request(s) -- should be send(s) + if (waitingReq->reqType == send_type_to) { + //set sending slave from the request + senderSlv = waitingReq->senderSlv; - //bring both processors back from suspend - VMS_PI__free( waitingReq ); + //waiting request is a send, so pair it with this receive + //first, remove the waiting send request from the list in entry + entry->content = waitingReq->nextReqInHashEntry; + if (entry->content == NULL) { + deleteEntryFromTable32((uint32*) entry->key, commHashTbl); //frees HashEntry + } - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + //attach msg that's in the send request to receiving procr + // when comes back from suspend, will have msg in dataRetFromReq + receiverSlv->dataRetFromReq = waitingReq->msg; + + //bring both processors back from suspend + VMS_PI__free(waitingReq); + +#ifdef HOLISTIC__TURN_ON_OBSERVE_UCC Dependency newd; - newd.from_vp = sendPr->slaveID; - newd.from_task = sendPr->assignCount; - newd.to_vp = receivePr->slaveID; - newd.to_task = receivePr->assignCount +1; + newd.from_vp = senderSlv->slaveID; + newd.from_task = senderSlv->assignCount; + newd.to_vp = receiverSlv->slaveID; + newd.to_task = receiverSlv->assignCount + 1; //addToListOfArraysDependency(newd,semEnv->commDependenciesList); - addToListOfArrays(Dependency,newd,semEnv->dynDependenciesList); + addToListOfArrays(Dependency, newd, semEnv->dynDependenciesList); int32 groupId = semReq->msgType; - if(semEnv->ntonGroupsInfo->numInArray <= groupId){ + if (semEnv->ntonGroupsInfo->numInArray <= groupId) { makeHighestDynArrayIndexBeAtLeast(semEnv->ntonGroupsInfo, groupId); } - if(semEnv->ntonGroups[groupId] == NULL){ + if (semEnv->ntonGroups[groupId] == NULL) { semEnv->ntonGroups[groupId] = new_NtoN(groupId); } Unit u; - u.vp = sendPr->slaveID; - u.task = sendPr->assignCount; - addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->senders); - u.vp = receivePr->slaveID; - u.task = receivePr->assignCount +1; - addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->receivers); - #endif - - resume_slaveVP( senderSlv, semEnv ); - resume_slaveVP( receiverSlv, semEnv ); + u.vp = senderSlv->slaveID; + u.task = senderSlv->assignCount; + addToListOfArrays(Unit, u, semEnv->ntonGroups[groupId]->senders); + u.vp = receiverSlv->slaveID; + u.task = receiverSlv->assignCount + 1; + addToListOfArrays(Unit, u, semEnv->ntonGroups[groupId]->receivers); +#endif - return; + resume_slaveVP(senderSlv, semEnv); + resume_slaveVP(receiverSlv, semEnv); + + return; } - printf("\nLang Impl Error: Should never be two waiting receives!\n"); - } - + printf("\nLang Impl Error: Should never be two waiting receives!\n"); +} /* */ inline void -handleReceiveFromTo( VSsSemReq *semReq, VSsSemEnv *semEnv) - { SlaveVP *senderSlv, *receiverSlv; - int32 *senderID, *receiverID; - int32 *key, keySz, receiverIDNumInt, senderIDNumInt; - VSsSemReq *waitingReq; - HashEntry *entry; - HashTable *commHashTbl = semEnv->commHashTbl; +handleReceiveFromTo(VSsSemReq *semReq, VSsSemEnv *semEnv) { + SlaveVP *senderSlv, *receiverSlv; + int32 *senderID, *receiverID; + int32 *key, keySz, receiverIDNumInt, senderIDNumInt; + VSsSemReq *waitingReq; + HashEntry *entry; + HashTable *commHashTbl = semEnv->commHashTbl; DEBUG__printf2(dbgRqstHdlr,"RecFromTo req from ID: %d to ID: %d",semReq->senderID[1],semReq->receiverID[1]) - - receiverID = semReq->receiverID; //For "send", know both send & recv procrs - senderID = semReq->senderID; - receiverSlv = semReq->receiverSlv; + + receiverID = semReq->receiverID; //For "send", know both send & recv procrs + senderID = semReq->senderID; + receiverSlv = semReq->receiverSlv; //suspending a task always makes the slave into an extra slot slave, // because it ends up in the resumeQ, even when resumes immediately. //Eventually task_end will put the slave into the freeExtraTaskSlvQ replaceWithNewSlotSlvIfNeeded( receiverSlv, semEnv ); - receiverIDNumInt = receiverID[0] + 1; //pos 0 doesn't include itself - senderIDNumInt = senderID[0] + 1; + receiverIDNumInt = receiverID[0] + 1; //pos 0 doesn't include itself + senderIDNumInt = senderID[0] + 1; keySz = (receiverIDNumInt + senderIDNumInt) * sizeof(int32) + sizeof(int32); - key = VMS_PI__malloc( keySz ); + key = VMS_PI__malloc(keySz); key[0] = receiverIDNumInt + senderIDNumInt; //loc 0 is num int32s in key memcpy( &key[1], receiverID, receiverIDNumInt * sizeof(int32) ); memcpy( &key[1 + receiverIDNumInt], senderID, senderIDNumInt * sizeof(int32)); - entry = giveEntryElseInsertReqst32( key, semReq, commHashTbl ); - if( entry == NULL ) //was just inserted, means task has to wait + entry = giveEntryElseInsertReqst32(key, semReq, commHashTbl); + if (entry == NULL) //was just inserted, means task has to wait { return; } - waitingReq = (VSsSemReq *)entry->content; + waitingReq = (VSsSemReq *) entry->content; - //At this point, know have a request to rendez-vous -- should be send - if( waitingReq->reqType == send_from_to ) - { //waiting request is a send, so pair it with this receive - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + //At this point, know have a request to rendez-vous -- should be send + if (waitingReq->reqType == send_from_to) { //waiting request is a send, so pair it with this receive +#ifdef HOLISTIC__TURN_ON_OBSERVE_UCC Dependency newd; - newd.from_vp = sendPr->slaveID; - newd.from_task = sendPr->assignCount; - newd.to_vp = receivePr->slaveID; - newd.to_task = receivePr->assignCount +1; + newd.from_vp = senderSlv->slaveID; + newd.from_task = senderSlv->assignCount; + newd.to_vp = receiverSlv->slaveID; + newd.to_task = receiverSlv->assignCount + 1; //addToListOfArraysDependency(newd,semEnv->commDependenciesList); - addToListOfArrays(Dependency,newd,semEnv->commDependenciesList); - #endif - - //have receiver slave, now set sender slave - senderSlv = waitingReq->senderSlv; - - //For from-to, should only ever be a single reqst waiting tobe paird - entry->content = waitingReq->nextReqInHashEntry; - if( entry->content != NULL ) printf("\nERROR in handleRecvFromTo\n"); - deleteEntryFromTable32( (uint32*)entry->key, commHashTbl ); //frees entry too + addToListOfArrays(Dependency, newd, semEnv->commDependenciesList); +#endif - //attach msg that's in the send request to receiving procr - // when comes back from suspend, will have msg in dataRetFromReq - receiverSlv->dataRetFromReq = waitingReq->msg; + //have receiver slave, now set sender slave + senderSlv = waitingReq->senderSlv; - //bring both processors back from suspend - VMS_PI__free( waitingReq ); + //For from-to, should only ever be a single reqst waiting tobe paird + entry->content = waitingReq->nextReqInHashEntry; + if (entry->content != NULL) printf("\nERROR in handleRecvFromTo\n"); + deleteEntryFromTable32((uint32*) entry->key, commHashTbl); //frees entry too - resume_slaveVP( senderSlv, semEnv ); - resume_slaveVP( receiverSlv, semEnv ); + //attach msg that's in the send request to receiving procr + // when comes back from suspend, will have msg in dataRetFromReq + receiverSlv->dataRetFromReq = waitingReq->msg; - return; + //bring both processors back from suspend + VMS_PI__free(waitingReq); + + resume_slaveVP(senderSlv, semEnv); + resume_slaveVP(receiverSlv, semEnv); + + return; } - printf("\nLang Impl Error: Should never be two waiting receives!\n"); - } + printf("\nLang Impl Error: Should never be two waiting receives!\n"); +} //========================================================================== + inline void replaceWithNewSlotSlvIfNeeded( SlaveVP *requestingSlv, VSsSemEnv *semEnv ) { SlaveVP *newSlotSlv; @@ -911,202 +913,209 @@ if( reqSemData->slaveType != SlotTaskSlv ) return; //already replaced, so just return - //get a new slave to be the slot slave - newSlotSlv = readPrivQ( semEnv->freeExtraTaskSlvQ ); - if( newSlotSlv == NULL ) - { newSlotSlv = VSs__create_slave_helper( &idle_fn, NULL, semEnv, 0); + //get a new slave to be the slot slave + newSlotSlv = readPrivQ(semEnv->freeExtraTaskSlvQ); + if (newSlotSlv == NULL) { + newSlotSlv = VSs__create_slave_helper(&idle_fn, NULL, semEnv, 0); //just made a new extra task slave, so count it semEnv->numLiveExtraTaskSlvs += 1; } - - //set slave values to make it the slot slave - semData = newSlotSlv->semanticData; - semData->taskStub = NULL; - semData->slaveType = SlotTaskSlv; - semData->needsTaskAssigned = TRUE; + + //set slave values to make it the slot slave + semData = newSlotSlv->semanticData; + semData->taskStub = NULL; + semData->slaveType = SlotTaskSlv; + semData->needsTaskAssigned = TRUE; //a slot slave is pinned to a particular slot on a particular core - newSlotSlv->animSlotAssignedTo = requestingSlv->animSlotAssignedTo; - newSlotSlv->coreAnimatedBy = requestingSlv->coreAnimatedBy; - - //put it into the slot slave matrix - int32 slotNum = requestingSlv->animSlotAssignedTo->slotIdx; - int32 coreNum = requestingSlv->coreAnimatedBy; - semEnv->slotTaskSlvs[coreNum][slotNum] = newSlotSlv; + newSlotSlv->animSlotAssignedTo = requestingSlv->animSlotAssignedTo; + newSlotSlv->coreAnimatedBy = requestingSlv->coreAnimatedBy; - //Fix up requester, to be an extra slave now (but not a free one) - // because it's not free, doesn't go into freeExtraTaskSlvQ - semData = requestingSlv->semanticData; - semData->slaveType = ExtraTaskSlv; - } + //put it into the slot slave matrix + int32 slotNum = requestingSlv->animSlotAssignedTo->slotIdx; + int32 coreNum = requestingSlv->coreAnimatedBy; + semEnv->slotTaskSlvs[coreNum][slotNum] = newSlotSlv; + + //Fix up requester, to be an extra slave now (but not a free one) + // because it's not free, doesn't go into freeExtraTaskSlvQ + semData = requestingSlv->semanticData; + semData->slaveType = ExtraTaskSlv; +} inline void -handleTaskwait( VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv) - { VSsTaskStub* requestingTaskStub; - VSsSemData* semData; - DEBUG__printf1(dbgRqstHdlr,"Taskwait request from processor %d", - requestingSlv->slaveID) - - semData = (VSsSemData *)semReq->callingSlv->semanticData; - requestingTaskStub = semData->taskStub; - - if( semData->taskStub->numLiveChildTasks == 0 ) - { //nobody to wait for, resume - resume_slaveVP( requestingSlv, semEnv ); +handleTaskwait(VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv) { + VSsTaskStub* requestingTaskStub; + VSsSemData* semData; + DEBUG__printf1(dbgRqstHdlr, "Taskwait request from processor %d", + requestingSlv->slaveID) + + semData = (VSsSemData *) semReq->callingSlv->semanticData; + requestingTaskStub = semData->taskStub; + + if (semData->taskStub->numLiveChildTasks == 0) { //nobody to wait for, resume + resume_slaveVP(requestingSlv, semEnv); + } else //have to wait, replace requester with new slot slv & mark waiting + { + if (semData->slaveType == SlotTaskSlv) { + replaceWithNewSlotSlvIfNeeded( requestingSlv, semEnv ); + } + + requestingTaskStub->isWaitingForChildTasksToEnd = TRUE; } - else //have to wait, replace requester with new slot slv & mark waiting - { - if(semData->slaveType == SlotTaskSlv){ - replaceWithNewSlotSlvIfNeeded( requestingSlv, semEnv ); - } - - requestingTaskStub->isWaitingForChildTasksToEnd = TRUE; - } - } +} //========================================================================== -/* - */ -void -handleMalloc( VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv ) - { void *ptr; - - DEBUG__printf1(dbgRqstHdlr,"Malloc request from processor %d",requestingSlv->slaveID) - - ptr = VMS_PI__malloc( semReq->sizeToMalloc ); - requestingSlv->dataRetFromReq = ptr; - resume_slaveVP( requestingSlv, semEnv ); - } /* */ void -handleFree( VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv ) - { - DEBUG__printf1(dbgRqstHdlr,"Free request from processor %d",requestingSlv->slaveID) - VMS_PI__free( semReq->ptrToFree ); - resume_slaveVP( requestingSlv, semEnv ); - } +handleMalloc(VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv) { + void *ptr; + + DEBUG__printf1(dbgRqstHdlr, "Malloc request from processor %d", requestingSlv->slaveID) + + ptr = VMS_PI__malloc(semReq->sizeToMalloc); + requestingSlv->dataRetFromReq = ptr; + resume_slaveVP(requestingSlv, semEnv); +} + +/* + */ +void +handleFree(VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv) { + DEBUG__printf1(dbgRqstHdlr, "Free request from processor %d", requestingSlv->slaveID) + VMS_PI__free(semReq->ptrToFree); + resume_slaveVP(requestingSlv, semEnv); +} //=========================================================================== // + /*Uses ID as index into array of flags. If flag already set, resumes from * end-label. Else, sets flag and resumes normally. */ void inline -handleStartSingleton_helper( VSsSingleton *singleton, SlaveVP *reqstingSlv, - VSsSemEnv *semEnv ) - { - if( singleton->hasFinished ) - { //the code that sets the flag to true first sets the end instr addr - reqstingSlv->dataRetFromReq = singleton->endInstrAddr; - resume_slaveVP( reqstingSlv, semEnv ); - return; +handleStartSingleton_helper(VSsSingleton *singleton, SlaveVP *reqstingSlv, + VSsSemEnv *semEnv) { + if (singleton->hasFinished) { //the code that sets the flag to true first sets the end instr addr + reqstingSlv->dataRetFromReq = singleton->endInstrAddr; +#ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + Dependency newd; + newd.from_vp = singleton->executingVp; + newd.from_task = singleton->executingTask; + newd.to_vp = reqstingSlv->slaveID; + newd.to_task = reqstingSlv->assignCount + 1; + addToListOfArrays(Dependency, newd, semEnv->singletonDependenciesList); +#endif + resume_slaveVP(reqstingSlv, semEnv); + return; + } else if (singleton->hasBeenStarted) { //singleton is in-progress in a diff slave, so wait for it to finish + writePrivQ(reqstingSlv, singleton->waitQ); + return; + } else { //hasn't been started, so this is the first attempt at the singleton + singleton->hasBeenStarted = TRUE; + reqstingSlv->dataRetFromReq = 0x0; + resume_slaveVP(reqstingSlv, semEnv); + return; } - else if( singleton->hasBeenStarted ) - { //singleton is in-progress in a diff slave, so wait for it to finish - writePrivQ(reqstingSlv, singleton->waitQ ); - return; - } - else - { //hasn't been started, so this is the first attempt at the singleton - singleton->hasBeenStarted = TRUE; - reqstingSlv->dataRetFromReq = 0x0; - resume_slaveVP( reqstingSlv, semEnv ); - return; - } - } -void inline -handleStartFnSingleton( VSsSemReq *semReq, SlaveVP *requestingSlv, - VSsSemEnv *semEnv ) - { VSsSingleton *singleton; - DEBUG__printf1(dbgRqstHdlr,"StartFnSingleton request from processor %d",requestingSlv->slaveID) - - singleton = &(semEnv->fnSingletons[ semReq->singletonID ]); - handleStartSingleton_helper( singleton, requestingSlv, semEnv ); - } -void inline -handleStartDataSingleton( VSsSemReq *semReq, SlaveVP *requestingSlv, - VSsSemEnv *semEnv ) - { VSsSingleton *singleton; - - DEBUG__printf1(dbgRqstHdlr,"StartDataSingleton request from processor %d",requestingSlv->slaveID) - if( *(semReq->singletonPtrAddr) == NULL ) - { singleton = VMS_PI__malloc( sizeof(VSsSingleton) ); - singleton->waitQ = makeVMSQ(); - singleton->endInstrAddr = 0x0; - singleton->hasBeenStarted = FALSE; - singleton->hasFinished = FALSE; - *(semReq->singletonPtrAddr) = singleton; - } - else - singleton = *(semReq->singletonPtrAddr); - handleStartSingleton_helper( singleton, requestingSlv, semEnv ); - } - +} void inline -handleEndSingleton_helper( VSsSingleton *singleton, SlaveVP *requestingSlv, - VSsSemEnv *semEnv ) - { PrivQueueStruc *waitQ; - int32 numWaiting, i; - SlaveVP *resumingSlv; +handleStartFnSingleton(VSsSemReq *semReq, SlaveVP *requestingSlv, + VSsSemEnv *semEnv) { + VSsSingleton *singleton; + DEBUG__printf1(dbgRqstHdlr, "StartFnSingleton request from processor %d", requestingSlv->slaveID) - if( singleton->hasFinished ) - { //by definition, only one slave should ever be able to run end singleton - // so if this is true, is an error - ERROR1( "singleton code ran twice", requestingSlv ); + singleton = &(semEnv->fnSingletons[ semReq->singletonID ]); + handleStartSingleton_helper(singleton, requestingSlv, semEnv); +} + +void inline +handleStartDataSingleton(VSsSemReq *semReq, SlaveVP *requestingSlv, + VSsSemEnv *semEnv) { + VSsSingleton *singleton; + + DEBUG__printf1(dbgRqstHdlr, "StartDataSingleton request from processor %d", requestingSlv->slaveID) + if (*(semReq->singletonPtrAddr) == NULL) { + singleton = VMS_PI__malloc(sizeof (VSsSingleton)); + singleton->waitQ = makeVMSQ(); + singleton->endInstrAddr = 0x0; + singleton->hasBeenStarted = FALSE; + singleton->hasFinished = FALSE; + *(semReq->singletonPtrAddr) = singleton; + } else + singleton = *(semReq->singletonPtrAddr); + handleStartSingleton_helper(singleton, requestingSlv, semEnv); +} + +void inline +handleEndSingleton_helper(VSsSingleton *singleton, SlaveVP *requestingSlv, + VSsSemEnv *semEnv) { + PrivQueueStruc *waitQ; + int32 numWaiting, i; + SlaveVP *resumingSlv; + + if (singleton->hasFinished) { //by definition, only one slave should ever be able to run end singleton + // so if this is true, is an error + ERROR1("singleton code ran twice", requestingSlv); } - singleton->hasFinished = TRUE; - waitQ = singleton->waitQ; - numWaiting = numInPrivQ( waitQ ); - for( i = 0; i < numWaiting; i++ ) - { //they will resume inside start singleton, then jmp to end singleton - resumingSlv = readPrivQ( waitQ ); - resumingSlv->dataRetFromReq = singleton->endInstrAddr; - resume_slaveVP( resumingSlv, semEnv ); + singleton->hasFinished = TRUE; + singleton->executingVp = requestingSlv->slaveID; + singleton->executingTask = requestingSlv->assignCount; + waitQ = singleton->waitQ; + numWaiting = numInPrivQ(waitQ); + for (i = 0; i < numWaiting; i++) { //they will resume inside start singleton, then jmp to end singleton + resumingSlv = readPrivQ(waitQ); + resumingSlv->dataRetFromReq = singleton->endInstrAddr; +#ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + Dependency newd; + newd.from_vp = singleton->executingVp; + newd.from_task = singleton->executingTask; + newd.to_vp = resumingSlv->slaveID; + newd.to_task = resumingSlv->assignCount + 1; + addToListOfArrays(Dependency, newd, semEnv->singletonDependenciesList); +#endif + resume_slaveVP(resumingSlv, semEnv); } - resume_slaveVP( requestingSlv, semEnv ); + resume_slaveVP(requestingSlv, semEnv); } + void inline -handleEndFnSingleton( VSsSemReq *semReq, SlaveVP *requestingSlv, - VSsSemEnv *semEnv ) - { - VSsSingleton *singleton; +handleEndFnSingleton(VSsSemReq *semReq, SlaveVP *requestingSlv, + VSsSemEnv *semEnv) { + VSsSingleton *singleton; - DEBUG__printf1(dbgRqstHdlr,"EndFnSingleton request from processor %d",requestingSlv->slaveID) - - singleton = &(semEnv->fnSingletons[ semReq->singletonID ]); - handleEndSingleton_helper( singleton, requestingSlv, semEnv ); - } + DEBUG__printf1(dbgRqstHdlr, "EndFnSingleton request from processor %d", requestingSlv->slaveID) + + singleton = &(semEnv->fnSingletons[ semReq->singletonID ]); + handleEndSingleton_helper(singleton, requestingSlv, semEnv); +} + void inline -handleEndDataSingleton( VSsSemReq *semReq, SlaveVP *requestingSlv, - VSsSemEnv *semEnv ) - { - VSsSingleton *singleton; +handleEndDataSingleton(VSsSemReq *semReq, SlaveVP *requestingSlv, + VSsSemEnv *semEnv) { + VSsSingleton *singleton; - DEBUG__printf1(dbgRqstHdlr,"EndDataSingleton request from processor %d",requestingSlv->slaveID) - - singleton = *(semReq->singletonPtrAddr); - handleEndSingleton_helper( singleton, requestingSlv, semEnv ); - } + DEBUG__printf1(dbgRqstHdlr, "EndDataSingleton request from processor %d", requestingSlv->slaveID) + singleton = *(semReq->singletonPtrAddr); + handleEndSingleton_helper(singleton, requestingSlv, semEnv); +} /*This executes the function in the masterVP, take the function * pointer out of the request and call it, then resume the VP. */ void -handleAtomic( VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv ) - { - DEBUG__printf1(dbgRqstHdlr,"Atomic request from processor %d",requestingSlv->slaveID) - semReq->fnToExecInMaster( semReq->dataForFn ); - resume_slaveVP( requestingSlv, semEnv ); - } +handleAtomic(VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv) { + DEBUG__printf1(dbgRqstHdlr, "Atomic request from processor %d", requestingSlv->slaveID) + semReq->fnToExecInMaster(semReq->dataForFn); + resume_slaveVP(requestingSlv, semEnv); +} /*First, it looks at the VP's semantic data, to see the highest transactionID * that VP @@ -1123,44 +1132,39 @@ *If NULL, then write requesting into the field and resume. */ void -handleTransStart( VSsSemReq *semReq, SlaveVP *requestingSlv, - VSsSemEnv *semEnv ) - { VSsSemData *semData; - TransListElem *nextTransElem; +handleTransStart(VSsSemReq *semReq, SlaveVP *requestingSlv, + VSsSemEnv *semEnv) { + VSsSemData *semData; + TransListElem *nextTransElem; - DEBUG__printf1(dbgRqstHdlr,"TransStart request from processor %d",requestingSlv->slaveID) - - //check ordering of entering transactions is correct - semData = requestingSlv->semanticData; - if( semData->highestTransEntered > semReq->transID ) - { //throw VMS exception, which shuts down VMS. - VMS_PI__throw_exception( "transID smaller than prev", requestingSlv, NULL); + DEBUG__printf1(dbgRqstHdlr, "TransStart request from processor %d", requestingSlv->slaveID) + + //check ordering of entering transactions is correct + semData = requestingSlv->semanticData; + if (semData->highestTransEntered > semReq->transID) { //throw VMS exception, which shuts down VMS. + VMS_PI__throw_exception("transID smaller than prev", requestingSlv, NULL); } - //add this trans ID to the list of transactions entered -- check when - // end a transaction - semData->highestTransEntered = semReq->transID; - nextTransElem = VMS_PI__malloc( sizeof(TransListElem) ); - nextTransElem->transID = semReq->transID; - nextTransElem->nextTrans = semData->lastTransEntered; - semData->lastTransEntered = nextTransElem; + //add this trans ID to the list of transactions entered -- check when + // end a transaction + semData->highestTransEntered = semReq->transID; + nextTransElem = VMS_PI__malloc(sizeof (TransListElem)); + nextTransElem->transID = semReq->transID; + nextTransElem->nextTrans = semData->lastTransEntered; + semData->lastTransEntered = nextTransElem; - //get the structure for this transaction ID - VSsTrans * - transStruc = &(semEnv->transactionStrucs[ semReq->transID ]); + //get the structure for this transaction ID + VSsTrans * + transStruc = &(semEnv->transactionStrucs[ semReq->transID ]); - if( transStruc->VPCurrentlyExecuting == NULL ) - { - transStruc->VPCurrentlyExecuting = requestingSlv; - resume_slaveVP( requestingSlv, semEnv ); + if (transStruc->VPCurrentlyExecuting == NULL) { + transStruc->VPCurrentlyExecuting = requestingSlv; + resume_slaveVP(requestingSlv, semEnv); + } else { //note, might make future things cleaner if save request with VP and + // add this trans ID to the linked list when gets out of queue. + // but don't need for now, and lazy.. + writePrivQ(requestingSlv, transStruc->waitingVPQ); } - else - { //note, might make future things cleaner if save request with VP and - // add this trans ID to the linked list when gets out of queue. - // but don't need for now, and lazy.. - writePrivQ( requestingSlv, transStruc->waitingVPQ ); - } - } - +} /*Use the trans ID to get the transaction structure from the array. *Look at VP_currently_executing to be sure it's same as requesting VP. @@ -1176,38 +1180,36 @@ * resume both. */ void -handleTransEnd(VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv) - { VSsSemData *semData; - SlaveVP *waitingSlv; - VSsTrans *transStruc; - TransListElem *lastTrans; - - DEBUG__printf1(dbgRqstHdlr,"TransEnd request from processor %d",requestingSlv->slaveID) - - transStruc = &(semEnv->transactionStrucs[ semReq->transID ]); +handleTransEnd(VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv) { + VSsSemData *semData; + SlaveVP *waitingSlv; + VSsTrans *transStruc; + TransListElem *lastTrans; - //make sure transaction ended in same VP as started it. - if( transStruc->VPCurrentlyExecuting != requestingSlv ) - { - VMS_PI__throw_exception( "trans ended in diff VP", requestingSlv, NULL ); + DEBUG__printf1(dbgRqstHdlr, "TransEnd request from processor %d", requestingSlv->slaveID) + + transStruc = &(semEnv->transactionStrucs[ semReq->transID ]); + + //make sure transaction ended in same VP as started it. + if (transStruc->VPCurrentlyExecuting != requestingSlv) { + VMS_PI__throw_exception("trans ended in diff VP", requestingSlv, NULL); } - //make sure nesting is correct -- last ID entered should == this ID - semData = requestingSlv->semanticData; - lastTrans = semData->lastTransEntered; - if( lastTrans->transID != semReq->transID ) - { - VMS_PI__throw_exception( "trans incorrectly nested", requestingSlv, NULL ); + //make sure nesting is correct -- last ID entered should == this ID + semData = requestingSlv->semanticData; + lastTrans = semData->lastTransEntered; + if (lastTrans->transID != semReq->transID) { + VMS_PI__throw_exception("trans incorrectly nested", requestingSlv, NULL); } - semData->lastTransEntered = semData->lastTransEntered->nextTrans; + semData->lastTransEntered = semData->lastTransEntered->nextTrans; - waitingSlv = readPrivQ( transStruc->waitingVPQ ); - transStruc->VPCurrentlyExecuting = waitingSlv; + waitingSlv = readPrivQ(transStruc->waitingVPQ); + transStruc->VPCurrentlyExecuting = waitingSlv; - if( waitingSlv != NULL ) - resume_slaveVP( waitingSlv, semEnv ); + if (waitingSlv != NULL) + resume_slaveVP(waitingSlv, semEnv); - resume_slaveVP( requestingSlv, semEnv ); - } + resume_slaveVP(requestingSlv, semEnv); +}