# HG changeset patch # User Sean Halle # Date 1338415358 25200 # Node ID f2ed1c379fe74f6f3d329cb90f253a1b24209e57 # Parent 5ed4d833506ee143f180ac283b9be43093a5c8dd code nearly complete.. about to begin debugging diff -r 5ed4d833506e -r f2ed1c379fe7 Measurement/VSs_Counter_Recording.c --- a/Measurement/VSs_Counter_Recording.c Thu May 24 07:34:21 2012 -0700 +++ b/Measurement/VSs_Counter_Recording.c Wed May 30 15:02:38 2012 -0700 @@ -3,14 +3,14 @@ * author: Nina Engelhardt */ -#include "VOMP_Counter_Recording.h" +#include "VSs_Counter_Recording.h" #include "VMS_impl/VMS.h" -#include "VOMP.h" +#include "VSs.h" #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS -void VOMP__init_counter_data_structs(){ - VOMPSemEnv *semanticEnv = _VMSMasterEnv->semanticEnv; +void VSs__init_counter_data_structs(){ + VSsSemEnv *semanticEnv = _VMSMasterEnv->semanticEnv; int i; for(i=0;icounterList[i] = makeListOfArrays(sizeof(CounterEvent), 128); @@ -28,7 +28,7 @@ list->next_free_index++; } -void VOMP__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) { if (pr->typeOfVP == Master || pr->typeOfVP == Shutdown) @@ -36,7 +36,7 @@ return; } - VOMPSemEnv *semanticEnv = _VMSMasterEnv->semanticEnv; + VSsSemEnv *semanticEnv = _VMSMasterEnv->semanticEnv; CounterEvent e; e.event_type = evt_type; diff -r 5ed4d833506e -r f2ed1c379fe7 Measurement/VSs_Counter_Recording.h --- a/Measurement/VSs_Counter_Recording.h Thu May 24 07:34:21 2012 -0700 +++ b/Measurement/VSs_Counter_Recording.h Wed May 30 15:02:38 2012 -0700 @@ -1,12 +1,12 @@ /* - * File: VOMP_Counter_Recording.h + * File: VSs_Counter_Recording.h * Author: nengel * * Created on January 11, 2012, 3:03 PM */ -#ifndef VOMP_COUNTER_RECORDING_H -#define VOMP_COUNTER_RECORDING_H +#ifndef VSs_COUNTER_RECORDING_H +#define VSs_COUNTER_RECORDING_H #include "VMS_impl/VMS.h" @@ -22,12 +22,12 @@ FILE* counterfile; -void VOMP__init_counter_data_structs(); +void VSs__init_counter_data_structs(); -void VOMP__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); void set_counter_file(FILE* f); void print_counter_events_to_file(void* _e); -#endif /* VOMP_COUNTER_RECORDING_H */ +#endif /* VSs_COUNTER_RECORDING_H */ diff -r 5ed4d833506e -r f2ed1c379fe7 Measurement/VSs_Measurement.h --- a/Measurement/VSs_Measurement.h Thu May 24 07:34:21 2012 -0700 +++ b/Measurement/VSs_Measurement.h Wed May 30 15:02:38 2012 -0700 @@ -6,8 +6,8 @@ * */ -#ifndef _VOMP_MEAS_H -#define _VOMP_MEAS_H +#ifndef _VSs_MEAS_H +#define _VSs_MEAS_H #ifdef MEAS__TURN_ON_LANG_MEAS diff -r 5ed4d833506e -r f2ed1c379fe7 VSs.c --- a/VSs.c Thu May 24 07:34:21 2012 -0700 +++ b/VSs.c Wed May 30 15:02:38 2012 -0700 @@ -11,16 +11,16 @@ #include "Queue_impl/PrivateQueue.h" #include "Hash_impl/PrivateHash.h" -#include "VOMP.h" -#include "VOMP_Counter_Recording.h" +#include "VSs.h" +#include "VSs_Counter_Recording.h" //========================================================================== void -VOMP__init(); +VSs__init(); void -VOMP__init_Helper(); +VSs__init_Helper(); //========================================================================== @@ -32,24 +32,24 @@ * *There's a pattern for the outside sequential code to interact with the * VMS_HW code. - *The VMS_HW system is inside a boundary.. every VOMP system is in its + *The VMS_HW system is inside a boundary.. every VSs system is in its * own directory that contains the functions for each of the processor types. * One of the processor types is the "seed" processor that starts the * cascade of creating all the processors that do the work. *So, in the directory is a file called "EntryPoint.c" that contains the * function, named appropriately to the work performed, that the outside * sequential code calls. This function follows a pattern: - *1) it calls VOMP__init() + *1) it calls VSs__init() *2) it creates the initial data for the seed processor, which is passed * in to the function - *3) it creates the seed VOMP processor, with the data to start it with. - *4) it calls startVOMPThenWaitUntilWorkDone + *3) it creates the seed VSs processor, with the data to start it with. + *4) it calls startVSsThenWaitUntilWorkDone *5) it gets the returnValue from the transfer struc and returns that * from the function * - *For now, a new VOMP system has to be created via VOMP__init every + *For now, a new VSs system has to be created via VSs__init every * time an entry point function is called -- later, might add letting the - * VOMP system be created once, and let all the entry points just reuse + * VSs system be created once, and let all the entry points just reuse * it -- want to be as simple as possible now, and see by using what makes * sense for later.. */ @@ -72,41 +72,41 @@ * any of the data reachable from initData passed in to here */ void -VOMP__create_seed_procr_and_do_work( TopLevelFnPtr fnPtr, void *initData ) - { VOMPSemEnv *semEnv; +VSs__create_seed_slave_and_do_work( TopLevelFnPtr fnPtr, void *initData ) + { VSsSemEnv *semEnv; SlaveVP *seedPr; - VOMP__init(); //normal multi-thd + VSs__init(); //normal multi-thd semEnv = _VMSMasterEnv->semanticEnv; - //VOMP starts with one processor, which is put into initial environ, + //VSs starts with one processor, which is put into initial environ, // and which then calls create() to create more, thereby expanding work - seedPr = VOMP__create_procr_helper( fnPtr, initData, + seedPr = VSs__create_slave_helper( fnPtr, initData, semEnv, semEnv->nextCoreToGetNewPr++ ); resume_slaveVP( seedPr, semEnv ); VMS_SS__start_the_work_then_wait_until_done(); //normal multi-thd - VOMP__cleanup_after_shutdown(); + VSs__cleanup_after_shutdown(); } int32 -VOMP__giveMinWorkUnitCycles( float32 percentOverhead ) +VSs__giveMinWorkUnitCycles( float32 percentOverhead ) { return MIN_WORK_UNIT_CYCLES; } int32 -VOMP__giveIdealNumWorkUnits() +VSs__giveIdealNumWorkUnits() { return NUM_ANIM_SLOTS * NUM_CORES; } int32 -VOMP__give_number_of_cores_to_schedule_onto() +VSs__give_number_of_cores_to_schedule_onto() { return NUM_CORES; } @@ -115,8 +115,8 @@ * saves jump point, and second jumps back several times to get reliable time */ void -VOMP__start_primitive() - { saveLowTimeStampCountInto( ((VOMPSemEnv *)(_VMSMasterEnv->semanticEnv))-> +VSs__start_primitive() + { saveLowTimeStampCountInto( ((VSsSemEnv *)(_VMSMasterEnv->semanticEnv))-> primitiveStartTime ); } @@ -126,17 +126,17 @@ * also to throw out any "weird" values due to OS interrupt or TSC rollover */ int32 -VOMP__end_primitive_and_give_cycles() +VSs__end_primitive_and_give_cycles() { int32 endTime, startTime; //TODO: fix by repeating time-measurement saveLowTimeStampCountInto( endTime ); - startTime =((VOMPSemEnv*)(_VMSMasterEnv->semanticEnv))->primitiveStartTime; + startTime =((VSsSemEnv*)(_VMSMasterEnv->semanticEnv))->primitiveStartTime; return (endTime - startTime); } //=========================================================================== -/*Initializes all the data-structures for a VOMP system -- but doesn't +/*Initializes all the data-structures for a VSs system -- but doesn't * start it running yet! * *This runs in the main thread -- before VMS starts up @@ -147,13 +147,13 @@ * for creating the seed processor and then starting the work. */ void -VOMP__init() +VSs__init() { VMS_SS__init(); //masterEnv, a global var, now is partially set up by init_VMS // after this, have VMS_int__malloc and VMS_int__free available - VOMP__init_Helper(); + VSs__init_Helper(); } @@ -164,25 +164,25 @@ } void -VOMP__init_Helper() - { VOMPSemEnv *semanticEnv; +VSs__init_Helper() + { VSsSemEnv *semanticEnv; PrivQueueStruc **readyVPQs; int coreIdx, i, j; //Hook up the semantic layer's plug-ins to the Master virt procr - _VMSMasterEnv->requestHandler = &VOMP__Request_Handler; - _VMSMasterEnv->slaveAssigner = &VOMP__assign_slaveVP_to_slot; + _VMSMasterEnv->requestHandler = &VSs__Request_Handler; + _VMSMasterEnv->slaveAssigner = &VSs__assign_slaveVP_to_slot; #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS - _VMSMasterEnv->counterHandler = &VOMP__counter_handler; + _VMSMasterEnv->counterHandler = &VSs__counter_handler; #endif //create the semantic layer's environment (all its data) and add to // the master environment - semanticEnv = VMS_int__malloc( sizeof( VOMPSemEnv ) ); + semanticEnv = VMS_int__malloc( sizeof( VSsSemEnv ) ); _VMSMasterEnv->semanticEnv = semanticEnv; #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS - VOMP__init_counter_data_structs(); + VSs__init_counter_data_structs(); #endif semanticEnv->shutdownInitiated = FALSE; for(i=0;inextCoreToGetNewPr = 0; semanticEnv->numSlaveVP = 0; - semanticEnv->commHashTbl = makeHashTable( 1<<16, &VMS_int__free );//start big + semanticEnv->argPtrHashTbl = makeHashTable( 1<<16, &VMS_int__free );//start big //TODO: bug -- turn these arrays into dyn arrays to eliminate limit //semanticEnv->singletonHasBeenExecutedFlags = makeDynArrayInfo( ); @@ -235,11 +235,11 @@ } -/*Frees any memory allocated by VOMP__init() then calls VMS_int__shutdown +/*Frees any memory allocated by VSs__init() then calls VMS_int__shutdown */ void -VOMP__cleanup_after_shutdown() - { VOMPSemEnv *semanticEnv; +VSs__cleanup_after_shutdown() + { VSsSemEnv *semanticEnv; semanticEnv = _VMSMasterEnv->semanticEnv; @@ -374,10 +374,10 @@ /* */ - SlaveVP * -VOMP__create_procr_with( TopLevelFnPtr fnPtr, void *initData, +SlaveVP * +VSs__create_slave_with( TopLevelFnPtr fnPtr, void *initData, SlaveVP *creatingPr ) - { VOMPSemReq reqData; + { VSsSemReq reqData; //the semantic request data is on the stack and disappears when this // call returns -- it's guaranteed to remain in the VP's stack for as @@ -386,26 +386,26 @@ reqData.coreToAssignOnto = -1; //means round-robin assign reqData.fnPtr = fnPtr; reqData.initData = initData; - reqData.sendPr = creatingPr; + reqData.callingSlv = creatingPr; VMS_WL__send_create_slaveVP_req( &reqData, creatingPr ); return creatingPr->dataRetFromReq; } - SlaveVP * -VOMP__create_procr_with_affinity( TopLevelFnPtr fnPtr, void *initData, +SlaveVP * +VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData, SlaveVP *creatingPr, int32 coreToAssignOnto ) - { VOMPSemReq reqData; + { VSsSemReq reqData; //the semantic request data is on the stack and disappears when this // call returns -- it's guaranteed to remain in the VP's stack for as // long as the VP is suspended. - reqData.reqType = 0; //know type because in a VMS create req - reqData.coreToAssignOnto = coreToAssignOnto; + reqData.reqType = create_slave; + reqData.coreToAssignOnto = coreToAssignOnto; reqData.fnPtr = fnPtr; reqData.initData = initData; - reqData.sendPr = creatingPr; + reqData.callingSlv = creatingPr; VMS_WL__send_create_slaveVP_req( &reqData, creatingPr ); @@ -413,182 +413,62 @@ } - void -VOMP__dissipate_procr( SlaveVP *procrToDissipate ) +void +VSs__dissipate_slave( SlaveVP *slaveToDissipate ) { - VMS_WL__send_dissipate_req( procrToDissipate ); + VMS_WL__send_dissipate_req( slaveToDissipate ); } //=========================================================================== -void * -VOMP__malloc_to( int32 sizeToMalloc, SlaveVP *owningPr ) - { VOMPSemReq reqData; - reqData.reqType = malloc_req; - reqData.sendPr = owningPr; - reqData.sizeToMalloc = sizeToMalloc; +//=========================================================================== +/*Returns a taskID, which can be used to communicate between tasks with + * send-receive, or to use other kinds of constructs with tasks. + */ +int32 +VSs__submit_task( VSsTaskType *taskType, void *args, SlaveVP *animSlv) + { VSsSemReq reqData; - VMS_WL__send_sem_request( &reqData, owningPr ); - - return owningPr->dataRetFromReq; + reqData.reqType = submit_task; + reqData.callingSlv = animSlv; + reqData.taskType = taskType; + reqData.args = args; + + + VMS_WL__send_sem_request( &reqData, animSlv ); + return animSlv->dataRetFromReq; } - -/*Sends request to Master, which does the work of freeing +/*NOTE: if want, don't need to send the animating SlaveVP around.. + * instead, can make a single slave per core, and coreCtrlr looks up the + * slave from having the core number. + * + *But, to stay compatible with all the other VMS languages, leave it in.. + * + *This call is the last to happen in every task. It causes the slave to + * suspend and get the next task out of the task-queue. Notice there is no + * assigner here.. only one slave, no slave ReadyQ, and so on.. + *Can either make the assigner take the next task out of the taskQ, or can + * leave all as it is, and make task-end take the next task. + *Note: this fits the case in the new VMS for no-context tasks, so will use + * the built-in taskQ of new VMS, and should be local and much faster. + * + *The task-stub is saved in the animSlv, so the request handler will get it + * from there, along with the task-type which has arg types, and so on.. */ void -VOMP__free( void *ptrToFree, SlaveVP *owningPr ) - { VOMPSemReq reqData; +VSs__end_task( SlaveVP *animSlv ) + { VSsSemReq reqData; - reqData.reqType = free_req; - reqData.sendPr = owningPr; - reqData.ptrToFree = ptrToFree; - - VMS_WL__send_sem_request( &reqData, owningPr ); + reqData.reqType = end_task; + reqData.callingSlv = animSlv; + + VMS_WL__send_sem_request( &reqData, animSlv ); } - -void -VOMP__transfer_ownership_of_from_to( void *data, SlaveVP *oldOwnerSlv, - SlaveVP *newOwnerPr ) - { - //TODO: put in the ownership system that automatically frees when no - // owners of data left -- will need keeper for keeping data around when - // future created processors might need it but don't exist yet - } - - -void -VOMP__add_ownership_by_to( SlaveVP *newOwnerSlv, void *data ) - { - - } - - -void -VOMP__remove_ownership_by_from( SlaveVP *loserSlv, void *dataLosing ) - { - - } - - -/*Causes the VOMP system to remove internal ownership, so data won't be - * freed when VOMP shuts down, and will persist in the external program. - * - *Must be called from the processor that currently owns the data. - * - *IMPL: Transferring ownership touches two different virtual processor's - * state -- which means it has to be done carefully -- the VMS rules for - * semantic layers say that a work-unit is only allowed to touch the - * virtual processor it is part of, and that only a single work-unit per - * virtual processor be assigned to a slave at a time. So, this has to - * modify the virtual processor that owns the work-unit that called this - * function, then create a request to have the other processor modified. - *However, in this case, the TO processor is the outside, and transfers - * are only allowed to be called by the giver-upper, so can mark caller of - * this function as no longer owner, and return -- done. - */ -void -VOMP__transfer_ownership_to_outside( void *data ) - { - //TODO: removeAllOwnersFrom( data ); - } - - -//=========================================================================== - -void -VOMP__send_of_type_to( SlaveVP *sendPr, void *msg, const int type, - SlaveVP *receivePr) - { VOMPSemReq reqData; - - reqData.receivePr = receivePr; - reqData.sendPr = sendPr; - reqData.reqType = send_type; - reqData.msgType = type; - reqData.msg = msg; - reqData.nextReqInHashEntry = NULL; - - //On ownership -- remove inside the send and let ownership sit in limbo - // as a potential in an entry in the hash table, when this receive msg - // gets paired to a send, the ownership gets added to the receivePr -- - // the next work-unit in the receivePr's trace will have ownership. - VMS_WL__send_sem_request( &reqData, sendPr ); - - //When come back from suspend, no longer own data reachable from msg - //TODO: release ownership here - } - -void -VOMP__send_from_to( void *msg, SlaveVP *sendPr, SlaveVP *receivePr ) - { VOMPSemReq reqData; - - //hash on the receiver, 'cause always know it, but sometimes want to - // receive from anonymous sender - - reqData.receivePr = receivePr; - reqData.sendPr = sendPr; - reqData.reqType = send_from_to; - reqData.msg = msg; - reqData.nextReqInHashEntry = NULL; - - VMS_WL__send_sem_request( &reqData, sendPr ); - } - - -//=========================================================================== - -void * -VOMP__receive_any_to( SlaveVP *receivePr ) - { - - } - -void * -VOMP__receive_type_to( const int type, SlaveVP *receivePr ) - { DEBUG__printf1(dbgRqstHdlr,"WL: receive type to: %d", receivePr->slaveID); - VOMPSemReq reqData; - - reqData.receivePr = receivePr; - reqData.reqType = receive_type; - reqData.msgType = type; - reqData.nextReqInHashEntry = NULL; - - VMS_WL__send_sem_request( &reqData, receivePr ); - - return receivePr->dataRetFromReq; - } - - - -/*Call this at point receiving virt pr wants in-coming data. - * - *The reason receivePr must call this is that it modifies the receivPr - * loc structure directly -- and the VMS rules state a virtual processor - * loc structure can only be modified by itself. - */ -void * -VOMP__receive_from_to( SlaveVP *sendPr, SlaveVP *receivePr ) - { DEBUG__printf2(dbgRqstHdlr,"WL: receive from %d to: %d", sendPr->slaveID, receivePr->slaveID); - VOMPSemReq reqData; - - //hash on the receiver, 'cause always know it, but sometimes want to - // receive from anonymous sender - - reqData.receivePr = receivePr; - reqData.sendPr = sendPr; - reqData.reqType = receive_from_to; - reqData.nextReqInHashEntry = NULL; - - VMS_WL__send_sem_request( &reqData, receivePr ); - - return receivePr->dataRetFromReq; - } - - -//=========================================================================== +//========================================================================== // /*A function singleton is a function whose body executes exactly once, on a * single core, no matter how many times the fuction is called and no @@ -601,16 +481,16 @@ */ /*asm function declarations*/ -void asm_save_ret_to_singleton(VOMPSingleton *singletonPtrAddr); -void asm_write_ret_from_singleton(VOMPSingleton *singletonPtrAddr); +void asm_save_ret_to_singleton(VSsSingleton *singletonPtrAddr); +void asm_write_ret_from_singleton(VSsSingleton *singletonPtrAddr); /*Fn singleton uses ID as index into array of singleton structs held in the * semantic environment. */ void -VOMP__start_fn_singleton( int32 singletonID, SlaveVP *animPr ) +VSs__start_fn_singleton( int32 singletonID, SlaveVP *animPr ) { - VOMPSemReq reqData; + VSsSemReq reqData; // reqData.reqType = singleton_fn_start; @@ -619,7 +499,7 @@ VMS_WL__send_sem_request( &reqData, animPr ); if( animPr->dataRetFromReq ) //will be 0 or addr of label in end singleton { - VOMPSemEnv *semEnv = VMS_int__give_sem_env_for( animPr ); + VSsSemEnv *semEnv = VMS_int__give_sem_env_for( animPr ); asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID])); } } @@ -629,9 +509,9 @@ * location. */ void -VOMP__start_data_singleton( VOMPSingleton **singletonAddr, SlaveVP *animPr ) +VSs__start_data_singleton( VSsSingleton **singletonAddr, SlaveVP *animPr ) { - VOMPSemReq reqData; + VSsSemReq reqData; if( *singletonAddr && (*singletonAddr)->hasFinished ) goto JmpToEndSingleton; @@ -658,13 +538,13 @@ * inside is shared by all invocations of a given singleton ID. */ void -VOMP__end_fn_singleton( int32 singletonID, SlaveVP *animPr ) +VSs__end_fn_singleton( int32 singletonID, SlaveVP *animPr ) { - VOMPSemReq reqData; + VSsSemReq reqData; //don't need this addr until after at least one singleton has reached // this function - VOMPSemEnv *semEnv = VMS_int__give_sem_env_for( animPr ); + VSsSemEnv *semEnv = VMS_int__give_sem_env_for( animPr ); asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID])); reqData.reqType = singleton_fn_end; @@ -677,9 +557,9 @@ } void -VOMP__end_data_singleton( VOMPSingleton **singletonPtrAddr, SlaveVP *animPr ) +VSs__end_data_singleton( VSsSingleton **singletonPtrAddr, SlaveVP *animPr ) { - VOMPSemReq reqData; + VSsSemReq reqData; //don't need this addr until after singleton struct has reached // this function for first time @@ -709,10 +589,10 @@ * between as work-code. */ void -VOMP__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster, +VSs__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster, void *data, SlaveVP *animPr ) { - VOMPSemReq reqData; + VSsSemReq reqData; // reqData.reqType = atomic; @@ -737,12 +617,12 @@ *If NULL, then write requesting into the field and resume. */ void -VOMP__start_transaction( int32 transactionID, SlaveVP *animPr ) +VSs__start_transaction( int32 transactionID, SlaveVP *animPr ) { - VOMPSemReq reqData; + VSsSemReq reqData; // - reqData.sendPr = animPr; + reqData.callingSlv = animPr; reqData.reqType = trans_start; reqData.transID = transactionID; @@ -759,12 +639,12 @@ * resumes both. */ void -VOMP__end_transaction( int32 transactionID, SlaveVP *animPr ) +VSs__end_transaction( int32 transactionID, SlaveVP *animPr ) { - VOMPSemReq reqData; + VSsSemReq reqData; // - reqData.sendPr = animPr; + reqData.callingSlv = animPr; reqData.reqType = trans_end; reqData.transID = transactionID; diff -r 5ed4d833506e -r f2ed1c379fe7 VSs.h --- a/VSs.h Thu May 24 07:34:21 2012 -0700 +++ b/VSs.h Wed May 30 15:02:38 2012 -0700 @@ -6,8 +6,8 @@ * */ -#ifndef _VOMP_H -#define _VOMP_H +#ifndef _VSs_H +#define _VSs_H #include "Queue_impl/PrivateQueue.h" #include "Hash_impl/PrivateHash.h" @@ -21,31 +21,69 @@ //This is hardware dependent -- it's the number of cycles of scheduling // overhead -- if a work unit is fewer than this, it is better being // combined sequentially with other work - //This value depends on both VMS overhead and VOMP's plugin. At some point - // it will be derived by perf-counter measurements during init of VOMP + //This value depends on both VMS overhead and VSs's plugin. At some point + // it will be derived by perf-counter measurements during init of VSs #define MIN_WORK_UNIT_CYCLES 20000 //=========================================================================== -/*This header defines everything specific to the VOMP semantic plug-in +/*This header defines everything specific to the VSs semantic plug-in */ -typedef struct _VOMPSemReq VOMPSemReq; +typedef struct _VSsSemReq VSsSemReq; typedef void (*VSsTaskFnPtr ) ( void * ); //executed atomically in master +typedef void (*PtrToAtomicFn ) ( void * ); //executed atomically in master //=========================================================================== -#define IN 1; -#define OUT 2; -#define INOUT 3; +#define IN 1 +#define OUT 2 +#define INOUT 3 + +#define READER 1 +#define WRITER 2 typedef struct { VSsTaskFnPtr fn; - int32 numArgs; - int32 *argTypes; - int32 *argSizes; + int32 numTotalArgs;//the number of inputs to function + int32 numCtldArgs;//how many of args have dependencies + int32 *argTypes; //says reader, writer, or non-ctld + int32 *argSizes; //for detecting overlap + int32 sizeOfArgs; //for memcpy of args struct } VSsTaskType; +typedef struct + { + void **args; //ctld args must come first, as ptrs + VSsTaskType *taskType; + int32 numBlockingProp; + SlaveVP *slaveAssignedTo; + } +VSsTaskStub; + +typedef struct + { + VSsTaskStub *taskStub; + int32 argNum; + int32 isReader; + } +VSsTaskStubCarrier; + +typedef struct + { + bool32 hasEnabledNonFinishedWriter; + int32 numEnabledNonDoneReaders; + PrivQStruct *waitersQ; + } +VSsPointerEntry; + + +typedef struct + { + int32 type; + VSsTaskStub *taskStub; + } +VSsWaiterCarrier; /*Semantic layer-specific data sent inside a request from lib called in app * to request handler called in AnimationMaster @@ -56,7 +94,7 @@ SlaveVP *VPCurrentlyExecuting; PrivQueueStruc *waitingVPQ; } -VOMPTrans; +VSsTrans; /*WARNING: assembly hard-codes position of endInstrAddr as first field */ @@ -67,17 +105,16 @@ int32 hasFinished; PrivQueueStruc *waitQ; } -VOMPSingleton; +VSsSingleton; -enum VOMPReqType +enum VSsReqType { - send_type = 1, - send_from_to, - receive_any, //order and grouping matter -- send before receive - receive_type, // and receive_any first of the receives -- Handlers - receive_from_to,// rely upon this ordering of enum - transfer_to, - transfer_out, + submit_task = 1, + end_task, + create_slave, + create_slave_w_aff, + dissipate_slave, + //=============================== malloc_req, free_req, singleton_fn_start, @@ -89,43 +126,43 @@ trans_end }; -struct _VOMPSemReq - { enum VOMPReqType reqType; - SlaveVP *sendPr; - SlaveVP *receivePr; - int32 msgType; - void *msg; - VOMPSemReq *nextReqInHashEntry; - +struct _VSsSemReq + { enum VSsReqType reqType; + SlaveVP *callingSlv; + VSsTaskType *taskType; + void *args; + VSsTaskStub *taskStub; + + TopLevelFnPtr fnPtr; void *initData; - TopLevelFnPtr fnPtr; int32 coreToAssignOnto; int32 sizeToMalloc; void *ptrToFree; int32 singletonID; - VOMPSingleton **singletonPtrAddr; + VSsSingleton **singletonPtrAddr; PtrToAtomicFn fnToExecInMaster; void *dataForFn; int32 transID; } -/* VOMPSemReq */; +/* VSsSemReq */; typedef struct { PrivQueueStruc **readyVPQs; - HashTable *commHashTbl; + PrivQueueStruc *taskReadyQ; //Q: shared or local? + HashTable *argPtrHashTbl; int32 numSlaveVP; int32 nextCoreToGetNewPr; int32 primitiveStartTime; //fix limit on num with dynArray - VOMPSingleton fnSingletons[NUM_STRUCS_IN_SEM_ENV]; - VOMPTrans transactionStrucs[NUM_STRUCS_IN_SEM_ENV]; + VSsSingleton fnSingletons[NUM_STRUCS_IN_SEM_ENV]; + VSsTrans transactionStrucs[NUM_STRUCS_IN_SEM_ENV]; #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC ListOfArrays* unitList; @@ -144,7 +181,7 @@ SlaveVP* idlePr[NUM_CORES][NUM_ANIM_SLOTS]; int shutdownInitiated; } -VOMPSemEnv; +VSsSemEnv; typedef struct _TransListElem TransListElem; @@ -159,125 +196,106 @@ { int32 highestTransEntered; TransListElem *lastTransEntered; + bool32 needsTaskAssigned; + VSsTaskStub *taskStub; } -VOMPSemData; +VSsSemData; //=========================================================================== void -VOMP__create_seed_procr_and_do_work( TopLevelFnPtr fn, void *initData ); +VSs__create_seed_slave_and_do_work( TopLevelFnPtr fn, void *initData ); int32 -VOMP__giveMinWorkUnitCycles( float32 percentOverhead ); +VSs__giveMinWorkUnitCycles( float32 percentOverhead ); void -VOMP__start_primitive(); +VSs__start_primitive(); int32 -VOMP__end_primitive_and_give_cycles(); +VSs__end_primitive_and_give_cycles(); int32 -VOMP__giveIdealNumWorkUnits(); +VSs__giveIdealNumWorkUnits(); int32 -VOMP__give_number_of_cores_to_schedule_onto(); +VSs__give_number_of_cores_to_schedule_onto(); //======================= void -VOMP__init(); +VSs__init(); void -VOMP__cleanup_after_shutdown(); +VSs__cleanup_after_shutdown(); //======================= SlaveVP * -VOMP__create_procr_with( TopLevelFnPtr fnPtr, void *initData, +VSs__create_slave_with( TopLevelFnPtr fnPtr, void *initData, SlaveVP *creatingSlv ); SlaveVP * -VOMP__create_procr_with_affinity( TopLevelFnPtr fnPtr, void *initData, +VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData, SlaveVP *creatingPr, int32 coreToAssignOnto); void -VOMP__dissipate_procr( SlaveVP *procrToDissipate ); +VSs__dissipate_slave( SlaveVP *slaveToDissipate ); //======================= -void * -VOMP__malloc_to( int numBytes, SlaveVP *ownerSlv ); + +#define VSs__malloc( numBytes, callingSlave ) VMS_App__malloc( numBytes, callingSlave) + +#define VSs__free(ptrToFree, callingSlave ) VMS_App__free( ptrToFree, callingSlave ) + + +//======================= +int32 +VSs__submit_task( VSsTaskType *taskType, void **args, SlaveVP *animSlv); + void -VOMP__free( void *ptrToFree, SlaveVP *owningSlv ); - -void -VOMP__transfer_ownership_of_from_to( void *data, SlaveVP *oldOwnerPr, - SlaveVP *newOwnerSlv ); - -void -VOMP__add_ownership_by_to( SlaveVP *newOwnerPr, void *data ); - -void -VOMP__remove_ownership_by_from( SlaveVP *loserPr, void *dataLosing ); - -void -VOMP__transfer_ownership_to_outside( void *dataToTransferOwnershipOf ); - - - -//======================= -void -VOMP__send_of_type_to( SlaveVP *sendPr, void *msg, const int type, - SlaveVP *receivePr); - -void -VOMP__send_from_to( void *msg, SlaveVP *sendPr, SlaveVP *receivePr); - -void * -VOMP__receive_type_to( const int type, SlaveVP *receiveSlv ); - -void * -VOMP__receive_from_to( SlaveVP *sendPr, SlaveVP *receiveSlv ); +VSs__end_task( SlaveVP *animSlv ); //======================= Concurrency Stuff ====================== void -VOMP__start_fn_singleton( int32 singletonID, SlaveVP *animSlv ); +VSs__start_fn_singleton( int32 singletonID, SlaveVP *animSlv ); void -VOMP__end_fn_singleton( int32 singletonID, SlaveVP *animSlv ); +VSs__end_fn_singleton( int32 singletonID, SlaveVP *animSlv ); void -VOMP__start_data_singleton( VOMPSingleton **singeltonAddr, SlaveVP *animSlv ); +VSs__start_data_singleton( VSsSingleton **singeltonAddr, SlaveVP *animSlv ); void -VOMP__end_data_singleton( VOMPSingleton **singletonAddr, SlaveVP *animSlv ); +VSs__end_data_singleton( VSsSingleton **singletonAddr, SlaveVP *animSlv ); void -VOMP__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster, +VSs__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster, void *data, SlaveVP *animSlv ); void -VOMP__start_transaction( int32 transactionID, SlaveVP *animSlv ); +VSs__start_transaction( int32 transactionID, SlaveVP *animSlv ); void -VOMP__end_transaction( int32 transactionID, SlaveVP *animSlv ); +VSs__end_transaction( int32 transactionID, SlaveVP *animSlv ); //========================= Internal use only ============================= void -VOMP__Request_Handler( SlaveVP *requestingPr, void *_semEnv ); +VSs__Request_Handler( SlaveVP *requestingPr, void *_semEnv ); SlaveVP * -VOMP__assign_slaveVP_to_slot( void *_semEnv, AnimSlot *slot ); +VSs__assign_slaveVP_to_slot( void *_semEnv, AnimSlot *slot ); SlaveVP* -VOMP__create_procr_helper( TopLevelFnPtr fnPtr, void *initData, - VOMPSemEnv *semEnv, int32 coreToAssignOnto ); +VSs__create_slave_helper( TopLevelFnPtr fnPtr, void *initData, + VSsSemEnv *semEnv, int32 coreToAssignOnto ); //===================== Measurement of Lang Overheads ===================== -#include "VOMP_Measurement.h" +#include "VSs_Measurement.h" //=========================================================================== -#endif /* _VOMP_H */ +#endif /* _VSs_H */ diff -r 5ed4d833506e -r f2ed1c379fe7 VSs_PluginFns.c --- a/VSs_PluginFns.c Thu May 24 07:34:21 2012 -0700 +++ b/VSs_PluginFns.c Wed May 30 15:02:38 2012 -0700 @@ -8,107 +8,135 @@ #include #include "Queue_impl/PrivateQueue.h" -#include "VOMP.h" -#include "VOMP_Request_Handlers.h" +#include "VSs.h" +#include "VSs_Request_Handlers.h" //=========================== Local Fn Prototypes =========================== void -resume_slaveVP( SlaveVP *procr, VOMPSemEnv *semEnv ); +resume_slaveVP( SlaveVP *slave, VSsSemEnv *semEnv ); void -handleSemReq( VMSReqst *req, SlaveVP *requestingPr, VOMPSemEnv *semEnv ); +handleSemReq( VMSReqst *req, SlaveVP *requestingPr, VSsSemEnv *semEnv ); void -handleDissipate( SlaveVP *requestingPr, VOMPSemEnv *semEnv ); +handleDissipate( SlaveVP *requestingPr, VSsSemEnv *semEnv ); void -handleCreate( VMSReqst *req, SlaveVP *requestingPr, VOMPSemEnv *semEnv ); - +handleCreate( VMSReqst *req, SlaveVP *requestingPr, VSsSemEnv *semEnv ); //============================== Assigner ================================== // -/*For VOMP, assigning a slave simply takes the next work-unit off the +/*For VSs, assigning a slave simply takes the next work-unit off the * ready-to-go work-unit queue and assigns it to the offered slot. *If the ready-to-go work-unit queue is empty, then nothing to assign * to the animation slot -- return FALSE to let Master loop know assigning * that slot failed. */ SlaveVP * -VOMP__assign_slaveVP_to_slot( void *_semEnv, AnimSlot *slot ) +VSs__assign_slaveVP_to_slot( void *_semEnv, AnimSlot *slot ) { SlaveVP *assignPr; - VOMPSemEnv *semEnv; + VSsSemEnv *semEnv; int32 coreNum, slotNum; coreNum = slot->coreSlotIsOn; slotNum = slot->slotIdx; - semEnv = (VOMPSemEnv *)_semEnv; + semEnv = (VSsSemEnv *)_semEnv; + /*At this point, could do an optimization -- have one slave for each slot + * and make it ALWAYS the one to assign to that slot -- so there is no + * read fromQ. However, going to keep this compatible with other + * languages, like VOMP and SSR. So, leave the normal slave fetch + * from readyQ. For example, allows SSR constructs, to create extra + * slaves, and send communications direction between them, while still + * having the StarSs-style spawning of tasks.. so one of the tasks + * can now suspend and do more interesting things.. means keep a pool + * of slaves, and take one from pool when a task suspends. + */ + //TODO: fix false sharing in array assignPr = readPrivQ( semEnv->readyVPQs[coreNum] ); + if( assignPr == NULL ) + { //if there are tasks ready to go, then make a new slave to animate + // This only happens when all available slaves are blocked by + // constructs like send, or mutex, and so on.. + VMS_PI__throw_exception( "no slaves in readyQ", NULL, NULL ); + } + if( assignPr != NULL ) //could still be NULL, if no tasks avail + { + if( ((VSsSemData *)assignPr->semanticData)->needsTaskAssigned ) + { VSsTaskStub * + newTaskStub = readQ( semEnv->taskReadyQ ); + if( newTaskStub == NULL ) + { //No task, so slave unused, so put it back and return "no-slave" + writeQ( assignPr, semEnv->readyVPQs[coreNum] ); + return NULL; + } + //point slave to the task's function, and mark slave as having task + VMS_int__reset_slaveVP_to_TopLvlFn( assignPr, + newTaskStub->taskType->fn, newTaskStub->args ); + ((VSsSemData *)assignPr->semanticData)->taskStub = newTaskStub; + newTaskStub->slaveAssignedTo = assignPr; + ((VSsSemData *)assignPr->semanticData)->needsTaskAssigned = FALSE; + } + #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC + } //Note, using a non-blocking queue -- it returns NULL if queue empty - if(!assignPr){ - assignPr = semEnv->idlePr[coreNum][slotNum]; - - if(semEnv->shutdownInitiated) { - assignPr = VMS_SS__create_shutdown_slave(); - } - //things that would normally happen in resume(), but these VPs never go there - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC - assignPr->assignCount++; //Somewhere here! - Unit newu; - newu.vp = assignPr->slaveID; - newu.task = assignPr->assignCount; - addToListOfArrays(Unit,newu,semEnv->unitList); - - if (assignPr->assignCount > 1){ - Dependency newd; - newd.from_vp = assignPr->slaveID; - newd.from_task = assignPr->assignCount - 1; - newd.to_vp = assignPr->slaveID; - newd.to_task = assignPr->assignCount; - addToListOfArrays(Dependency, newd ,semEnv->ctlDependenciesList); - } + else //assignPr is indeed NULL + { assignPr = semEnv->idlePr[coreNum][slotNum]; + if(semEnv->shutdownInitiated) + { assignPr = VMS_SS__create_shutdown_slave(); + } + //things that would normally happen in resume(), but these VPs + // never go there + assignPr->assignCount++; //Somewhere here! + Unit newu; + newu.vp = assignPr->slaveID; + newu.task = assignPr->assignCount; + addToListOfArrays(Unit,newu,semEnv->unitList); + + if (assignPr->assignCount > 1) + { Dependency newd; + newd.from_vp = assignPr->slaveID; + newd.from_task = assignPr->assignCount - 1; + newd.to_vp = assignPr->slaveID; + newd.to_task = assignPr->assignCount; + addToListOfArrays(Dependency, newd ,semEnv->ctlDependenciesList); + } #endif - } + } #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC - if (assignPr) { - //assignPr->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 = assignPr->slaveID; - newd.to_task = assignPr->assignCount; - addToListOfArrays(Dependency,newd,semEnv->hwArcs); - } - prev_in_slot.vp = assignPr->slaveID; - prev_in_slot.task = assignPr->assignCount; - semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum] = prev_in_slot; - } + if( assignPr != NULL ) + { //assignPr->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 = assignPr->slaveID; + newd.to_task = assignPr->assignCount; + addToListOfArrays(Dependency,newd,semEnv->hwArcs); + } + prev_in_slot.vp = assignPr->slaveID; + prev_in_slot.task = assignPr->assignCount; + semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum] = + prev_in_slot; + } #endif return( assignPr ); } -//=========================== Request Handler ============================= +//=========================== Request Handler ============================ // -/*Will get requests to send, to receive, and to create new processors. - * Upon send, check the hash to see if a receive is waiting. - * Upon receive, check hash to see if a send has already happened. - * When other is not there, put in. When other is there, the comm. - * completes, which means the receiver P gets assigned and - * picks up right after the receive request. So make the work-unit - * and put it into the queue of work-units ready to go. - * Other request is create a new Processor, with the function to run in the - * Processor, and initial data. +/* */ void -VOMP__Request_Handler( SlaveVP *requestingPr, void *_semEnv ) - { VOMPSemEnv *semEnv; - VMSReqst *req; +VSs__Request_Handler( SlaveVP *requestingPr, void *_semEnv ) + { VSsSemEnv *semEnv; + VMSReqst *req; - semEnv = (VOMPSemEnv *)_semEnv; + semEnv = (VSsSemEnv *)_semEnv; req = VMS_PI__take_next_request_out_of( requestingPr ); @@ -119,7 +147,7 @@ break; case createReq: handleCreate( req, requestingPr, semEnv); break; - case dissipate: handleDissipate( requestingPr, semEnv); + case dissipate: handleDissipate( req, requestingPr, semEnv); break; case VMSSemantic: VMS_PI__handle_VMSSemReq(req, requestingPr, semEnv, (ResumeSlvFnPtr) &resume_slaveVP); @@ -135,25 +163,18 @@ void -handleSemReq( VMSReqst *req, SlaveVP *reqPr, VOMPSemEnv *semEnv ) - { VOMPSemReq *semReq; +handleSemReq( VMSReqst *req, SlaveVP *reqPr, 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 { - case send_type: handleSendType( semReq, semEnv); + case submit_task: handleSubmitTask( semReq, semEnv); break; - case send_from_to: handleSendFromTo( semReq, semEnv); + case end_task: handleEndTask( semReq, semEnv); break; - case receive_type: handleReceiveType( semReq, semEnv); - break; - case receive_from_to: handleReceiveFromTo(semReq, semEnv); - break; - case transfer_to: handleTransferTo( semReq, semEnv); - break; - case transfer_out: handleTransferOut( semReq, semEnv); - break; + //==================================================================== case malloc_req: handleMalloc( semReq, reqPr, semEnv); break; case free_req: handleFree( semReq, reqPr, semEnv); @@ -178,9 +199,10 @@ //=========================== VMS Request Handlers ============================== -// +/*SlaveVP dissipate (NOT task-end!) + */ void -handleDissipate( SlaveVP *requestingPr, VOMPSemEnv *semEnv ) +handleDissipate( SlaveVP *requestingPr, VSsSemEnv *semEnv ) { DEBUG__printf1(dbgRqstHdlr,"Dissipate request from processor %d",requestingPr->slaveID) //free any semantic data allocated to the virt procr @@ -200,17 +222,17 @@ /*Re-use this in the entry-point fn */ SlaveVP * -VOMP__create_procr_helper( TopLevelFnPtr fnPtr, void *initData, - VOMPSemEnv *semEnv, int32 coreToAssignOnto ) +VSs__create_slave_helper( TopLevelFnPtr fnPtr, void *initData, + VSsSemEnv *semEnv, int32 coreToAssignOnto ) { SlaveVP *newPr; - VOMPSemData *semData; + VSsSemData *semData; //This is running in master, so use internal version newPr = VMS_PI__create_slaveVP( fnPtr, initData ); semEnv->numSlaveVP += 1; - semData = VMS_PI__malloc( sizeof(VOMPSemData) ); + semData = VMS_PI__malloc( sizeof(VSsSemData) ); semData->highestTransEntered = -1; semData->lastTransEntered = NULL; @@ -240,15 +262,17 @@ return newPr; } +/*SlaveVP create (NOT task create!) + */ void -handleCreate( VMSReqst *req, SlaveVP *requestingPr, VOMPSemEnv *semEnv ) - { VOMPSemReq *semReq; +handleCreate( VMSReqst *req, SlaveVP *requestingPr, VSsSemEnv *semEnv ) + { VSsSemReq *semReq; SlaveVP *newPr; semReq = VMS_PI__take_sem_reqst_from( req ); - newPr = VOMP__create_procr_helper( semReq->fnPtr, semReq->initData, semEnv, + newPr = VSs__create_slave_helper( semReq->fnPtr, semReq->initData, semEnv, semReq->coreToAssignOnto ); DEBUG__printf2(dbgRqstHdlr,"Create from: %d, new VP: %d", requestingPr->slaveID, newPr->slaveID) @@ -263,7 +287,7 @@ addToListOfArrays(Dependency,newd,semEnv->commDependenciesList); #endif - //For VOMP, caller needs ptr to created processor returned to it + //For VSs, caller needs ptr to created processor returned to it requestingPr->dataRetFromReq = newPr; resume_slaveVP( newPr, semEnv ); @@ -273,30 +297,30 @@ //=========================== Helper ============================== void -resume_slaveVP( SlaveVP *procr, VOMPSemEnv *semEnv ) +resume_slaveVP( SlaveVP *slave, VSsSemEnv *semEnv ) { #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS /* - int lastRecordIdx = procr->counter_history_array_info->numInArray -1; - CounterRecord* lastRecord = procr->counter_history[lastRecordIdx]; + 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 - procr->assignCount++; //Somewhere here! + slave->assignCount++; //Somewhere here! Unit newu; - newu.vp = procr->slaveID; - newu.task = procr->assignCount; + newu.vp = slave->slaveID; + newu.task = slave->assignCount; addToListOfArrays(Unit,newu,semEnv->unitList); - if (procr->assignCount > 1){ + if (slave->assignCount > 1){ Dependency newd; - newd.from_vp = procr->slaveID; - newd.from_task = procr->assignCount - 1; - newd.to_vp = procr->slaveID; - newd.to_task = procr->assignCount; + 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 - writePrivQ( procr, semEnv->readyVPQs[ procr->coreAnimatedBy] ); + writePrivQ( slave, semEnv->readyVPQs[ slave->coreAnimatedBy] ); } diff -r 5ed4d833506e -r f2ed1c379fe7 VSs_Request_Handlers.c --- a/VSs_Request_Handlers.c Thu May 24 07:34:21 2012 -0700 +++ b/VSs_Request_Handlers.c Wed May 30 15:02:38 2012 -0700 @@ -10,28 +10,29 @@ #include "VMS_impl/VMS.h" #include "Queue_impl/PrivateQueue.h" #include "Hash_impl/PrivateHash.h" -#include "VOMP.h" +#include "VSs.h" //=========================== Local Fn Prototypes =========================== void -resume_slaveVP( SlaveVP *procr, VOMPSemEnv *semEnv ); +resume_slaveVP( SlaveVP *slave, VSsSemEnv *semEnv ); -//=========================================================================== +//========================================================================== // Helpers +// /*Only clone the elements of req used in these reqst handlers */ - VOMPSemReq * -cloneReq( VOMPSemReq *semReq ) - { VOMPSemReq *clonedReq; + VSsSemReq * +cloneReq( VSsSemReq *semReq ) + { VSsSemReq *clonedReq; - clonedReq = VMS_PI__malloc( sizeof(VOMPSemReq) ); + clonedReq = VMS_PI__malloc( sizeof(VSsSemReq) ); clonedReq->reqType = semReq->reqType; - clonedReq->sendPr = semReq->sendPr; + clonedReq->callingSlv = semReq->callingSlv; clonedReq->msg = semReq->msg; clonedReq->nextReqInHashEntry = NULL; @@ -39,10 +40,10 @@ } HashEntry * -giveEntryElseInsertReqst( char *key, VOMPSemReq *semReq, +giveEntryElseInsertReqst( char *key, VSsSemReq *semReq, HashTable *commHashTbl ) { HashEntry *entry; - VOMPSemReq *waitingReq; + VSsSemReq *waitingReq; entry = getEntryFromTable( (char *)key, commHashTbl ); if( entry == NULL ) @@ -51,7 +52,7 @@ addValueIntoTable( key, cloneReq( semReq ), commHashTbl ); return NULL; } - waitingReq = (VOMPSemReq *)entry->content; + 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; @@ -60,356 +61,411 @@ return entry; } +inline VSsPointerEntry * +create_pointer_entry_and_insert( void *argPtr ) + { VSsPointerEntry newEntry; + + newEntry = VMS_PI__malloc( sizeof(VSsPointerEntry) ); + newEntry->hasEnabledNonFinishedWriter = FALSE; + newEntry->numEnabledNonDoneReaders = 0; + newEntry->waitersQ = makePrivQ(); + } +/*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; + int32 i, numArgs; + VSsTaskStub * + newStub = malloc( sizeof(VSsTaskStub) + taskType->sizeOfArgs ); + newStub->numBlockingProp = taskType->numCtldArgs; + newStub->slaveAssignedTo = NULL; + newStub->taskType = taskType; + newArgs = (void **)((uint8 *)newStub) + sizeof(VSsTaskStub); + newStub->args = newArgs; + + //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 ); + } +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; + } -//=========================================================================== +//========================================================================== +// +// +/*Submit Task + * + *Uses a hash table to match the arg-pointers to each other. So, an + * argument-pointer is one-to-one with a hash-table entry. + * + *If overlapping region detection is enabled, then a hash entry is one + * link in a ring of all entries that overlap each other. For example, + * say region A shared common addresses with region B, but the pointers + * to them are different, then the hash entries for the two would be + * linked in a ring. When a pointer is processed, all the pointers in + * the ring are processed (Doesn't differentiate independent siblings + * from parent-child or conjoined twins overlap..) + * NOT ENABLED AS OF MAY 25 2012 + * + *A hash entry has a queue of tasks that are waiting to access the + * pointed-to region. The queue goes in the order of creation of + * the tasks. Each entry in the queue has a pointer to the task-stub + * and whether the task reads-only vs writes to the hash-entry's region. + * + *A hash entry also has a count of the enabled but not yet finished readers + * of the region. It also has a flag that says whether a writer has been + * enabled and is not yet finished. + * + *There are two kinds of events that access a hash entry: creation of a + * task and end of a task. + * + * + * ========================== 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). + * + *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). + *With 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 (could be prev readers, + * then a writer that got queued and now new readers that have to also be + * queued). + *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. + * + *Otherwise, the reader is put into the hash-entry's Q of waiters + * + *If the arg is a writer, plus the entry does not have a current writer, + * plus the number of enabled non-finished readers is zero, plus the Q is + * empty, then the writer is free. Mark the entry has having an + * enabled and non-finished writer. Decrement the blocking-propendent + * count in the writer's task-stub. If the count is zero, then put the + * task-stub into the readyQ. + * + *Otherwise, put the writer into the entry's Q of waiters. + * + *No matter what, 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 of no-longer-used pointers later) + * + * + * ========================== end of task =========================== + * + *At the end of a task, + *The task's controlled arguments are processed one by one. + *Processing an argument means getting the hash of the pointer. Then, + * looking up the hash entry (and putting the entry at the start of the + * chain, if there was a chain). + *With the hash entry: + * + *If the arg is a reader, then decrement the enabled and non-finished + * reader-count in the hash-entry. 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. + *Set the hash-entry to have an enabled non-finished writer. 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. + * + *If the arg is a writer, then clear the enabled non-finished writer flag + * of the hash-entry. Take the next entry from the Q. + *If it is a writer, then turn the flag back on. Decrement the writer's + * blocking-propendent-count in its task-stub. If it becomes zero, then + * put the task-stub into the readyQ. + * + *If it is a reader, then increment the hash-entry's count of enabled + * non-finished readers. Decrement the blocking propendents count of the + * reader's task-stub. If it reaches zero, then put the task-stub into the + * readyQ. + *Then repeat until encounter a writer -- put that writer back into the Q. + * + *That should be it -- that should work. + */ +void +handleSubmitTask( VSsSemReq *semReq, VSsSemEnv *semEnv ) + { int64 key[] = {0,0,0}; + HashEntry *rawHashEntry; + VSsPointerEntry *ptrEntry; //contents of hash table entry for an arg pointer + void **args; + VSsTaskStub *taskStub; + VSsTaskType *taskType; + VSsTaskStubCarrier *taskCarrier; + + HashTable * + argPtrHashTbl = semEnv->argPtrHashTbl; + + DEBUG__printf1(dbgRqstHdlr,"SendType request from processor %d",semReq->callingSlv->slaveID) + + /* ========================== 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; + + /*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] = (int64)args[argNum]; + + //key[2] acts as the 0 that terminates the string +//BUG! need new hash function that works on *pointers with zeros in* + /*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 = getEntryFromTable( (char *)key, argPtrHashTbl ); + ptrEntry = (VSsPointerEntry *)rawHashEntry->content; + if( ptrEntry == NULL ) + { ptrEntry = create_pointer_entry_and_insert( args[argNum] ); + } + + /*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 ) + { writeQ( 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 ); + writeQ( 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. + * 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 ) + { writeQ( 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 ); + writeQ( taskCarrier, ptrEntry->waitersQ ); + } + } + } //for argNum + + + resume_slaveVP( semReq->callingSlv, semEnv ); + + return; + } + + + +/* ========================== end of task =========================== + * + *At the end of a task, + *The task's controlled arguments are processed one by one. + *Processing an argument means getting the hash of the pointer. Then, + * looking up the hash entry (and putting the entry at the start of the + * chain, if there was a chain). + *With the hash entry: + * + *If the arg is a reader, then decrement the enabled and non-finished + * reader-count in the hash-entry. 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. + *Set the hash-entry to have an enabled non-finished writer. 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. + * + *If the arg is a writer, then clear the enabled non-finished writer flag + * of the hash-entry. Take the next entry from the waiters Q. + *If it is a writer, then turn the flag back on. Decrement the writer's + * blocking-propendent-count in its task-stub. If it becomes zero, then + * put the task-stub into the readyQ. + * + *If waiter is a reader, then do a loop, getting all waiting readers. + * For each, increment the hash-entry's count of enabled + * non-finished readers. Decrement the blocking propendents count of the + * reader's task-stub. If it reaches zero, then put the task-stub into the + * readyQ. + *Repeat until encounter a writer -- put that writer back into the Q. + */ +void +handleEndTask( VSsSemReq *semReq, VSsSemEnv *semEnv ) + { int64 key[] = {0,0,0}; + HashEntry *rawHashEntry; + VSsPointerEntry *entry; //contents of hash table entry for an arg pointer + void **args; + VSsTaskStub *endingTaskStub, *waitingTaskStub; + VSsTaskType *endingTaskType; + VSsWaiterCarrier *waitingTaskCarrier; + + HashTable * + ptrHashTbl = semEnv->argPtrHashTbl; + + DEBUG__printf1(dbgRqstHdlr,"SendType request from processor %d",semReq->callingSlv->slaveID) + + /* ========================== end of task =========================== + *At the end of a task, the task-stub is sent in the request. + */ + endingTaskStub = + ((VSsSemData *)semReq->callingSlv->semanticData)->taskStub; + args = endingTaskStub->args; + endingTaskType = endingTaskStub->taskType; + + /*The task's controlled arguments are processed one by one. + *Processing an argument means getting the hash of the pointer. + */ + int32 argNum; + for( argNum = 0; argNum < endingTaskType->numCtldArgs; argNum++ ) + { + key[0] = (int64)args[argNum]; + + //key[2] acts as the 0 that terminates the string +//BUG! need new hash function that works on *pointers with zeros in* + /*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: could put pointer directly to hash entry into task-stub + * when do lookup during task creation.*/ + rawHashEntry = getEntryFromTable( (char *)key, ptrHashTbl ); + entry = (VSsPointerEntry *)rawHashEntry->content; + if( entry == NULL ) + VMS_App__throw_exception("hash entry NULL", NULL, NULL); + + /*With the hash entry: 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. */ + entry->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( entry->numEnabledNonDoneReaders == 0 ) + { waitingTaskCarrier = readQ( entry->waitersQ ); + waitingTaskStub = waitingTaskCarrier->taskStub; + + if( !waitingTaskCarrier->type == READER ) + VMS_App__throw_exception(); + + /*Set the hash-entry to have an enabled non-finished writer.*/ + entry->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 ) + { writeQ( waitingTaskStub, semEnv->taskReadyQ ); + } + } + } + else /*the ending task is a writer of this arg*/ + { /*clear the enabled non-finished writer flag of the hash-entry.*/ + entry->hasEnabledNonFinishedWriter = FALSE; + + /*Take the next waiter from the hash-entry's Q.*/ + waitingTaskCarrier = readQ( entry->waitersQ ); + waitingTaskStub = waitingTaskCarrier->taskStub; + + /*If task is a writer of this hash-entry's pointer*/ + if( waitingTaskCarrier->type == WRITER ) + { /* then turn the flag back on.*/ + entry->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 ) + { writeQ( 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 + * readers.*/ + entry->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 ) + { writeQ( waitingTaskStub, semEnv->taskReadyQ ); + } + /*Get next waiting task*/ + waitingTaskCarrier = peekQ( entry->waitersQ ); + if( waitingTaskCarrier == NULL ) break; + if( waitingTaskCarrier->type == WRITER ) break; + waitingTaskCarrier = readQ( entry->waitersQ ); + waitingTaskStub = waitingTaskCarrier->taskStub; + }//while waiter is a reader + }//first waiting task is a reader + }//check of ending task, whether writer or reader + }//for argnum in ending task + + //done ending the task, now free the stub + args copy + VMS_PI__free( endingTaskStub ); + + //Resume the slave that animated the task -- assigner will give new task + ((VSsSemData *)semReq->callingSlv->semanticData)->needsTaskAssigned = + TRUE; + resume_slaveVP( semReq->callingSlv, semEnv ); + + return; + } + + +//========================================================================== /* */ void -handleSubmitTask( VOMPSemReq *semReq, VOMPSemEnv *semEnv ) - { SlaveVP *sendPr; - int key[] = {0,0,0}; - VOMPSemReq *waitingReq; - HashEntry *entry; - HashTable *commHashTbl = semEnv->commHashTbl; - - DEBUG__printf1(dbgRqstHdlr,"SendType request from processor %d",semReq->sendPr->slaveID) - - receivePr = semReq->receivePr; //For "send", know both send & recv procrs - sendPr = semReq->sendPr; - - //TODO: handle transfer of msg-locs ownership - //TODO: hash table implemented such that using "addEntry" or - // "addValue" to table causes the *value* in old entry to be - // *freed* -- this is bad. Want to stack up values in a linked - // list when multiple have the same key. - - //TODO: use a faster hash function -- see notes in intelligence gather - key[0] = (int)receivePr->slaveID; - key[1] = (int)(semReq->msgType); - //key[2] acts as the 0 that terminates the string - - entry = giveEntryElseInsertReqst( (char *)key, semReq, commHashTbl); - if( entry == NULL ) return; //was just inserted - - waitingReq = (VOMPSemReq *)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 ) - { //waiting request is another send, so stack this up on list - // but first clone the sending request so it persists. - VOMPSemReq *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 - Dependency newd; - newd.from_vp = sendPr->slaveID; - newd.from_task = sendPr->assignCount; - newd.to_vp = receivePr->slaveID; - newd.to_task = receivePr->assignCount +1; - //(newd,semEnv->commDependenciesList); - addToListOfArrays(Dependency,newd,semEnv->dynDependenciesList); - int32 groupId = semReq->msgType; - if(semEnv->ntonGroupsInfo->numInArray <= groupId){ - makeHighestDynArrayIndexBeAtLeast(semEnv->ntonGroupsInfo, groupId); - } - 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 - - //waiting request is a receive, 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 - deleteEntryFromTable( 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 - receivePr->dataRetFromReq = semReq->msg; - - //bring both processors back from suspend - resume_slaveVP( sendPr, semEnv ); - resume_slaveVP( receivePr, semEnv ); - - return; - } - } - - -/*Looks like can make single handler for both sends.. - */ -//TODO: combine both send handlers into single handler -void -handleSendFromTo( VOMPSemReq *semReq, VOMPSemEnv *semEnv) - { SlaveVP *sendPr, *receivePr; - int key[] = {0,0,0}; - VOMPSemReq *waitingReq; - HashEntry *entry; - HashTable *commHashTbl = semEnv->commHashTbl; - - DEBUG__printf2(dbgRqstHdlr,"SendFromTo request from processor %d to %d",semReq->sendPr->slaveID,semReq->receivePr->slaveID) - - receivePr = semReq->receivePr; //For "send", know both send & recv procrs - sendPr = semReq->sendPr; - - - key[0] = (int)receivePr->slaveID; - key[1] = (int)sendPr->slaveID; - //key[2] acts at the 0 that terminates the string - - entry = giveEntryElseInsertReqst( (char *)key, semReq, commHashTbl); - if( entry == NULL ) return; //was just inserted - - waitingReq = (VOMPSemReq *)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"); - } - 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 - //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"); - } - deleteEntryFromTable( 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 - receivePr->dataRetFromReq = semReq->msg; - - //bring both processors back from suspend - resume_slaveVP( sendPr, semEnv ); - resume_slaveVP( receivePr, semEnv ); - - return; - } - } - - - -//============================== Receives =========================== -// -/*Removed this one for now, because forces either a search or going to a - * two-level hash table, where one level the key is the receivePr, in the - * other level, the key is the type. - *So, each dest procr that either does a receive_type or that a send_type - * targets it, would have a hash table created just for it and placed - * into the first-level hash table entry for that receive procr. - *Then, doing a receive_type first looks up entry for receive procr in first - * table, gets the type-table out of that entry, and does a second lookup - * in the type-table. - *Doing a receive from-to looks up in the first table, gets the second table - * hashed on "from" procr. - *Doing a receive_any looks up in the first table, then looks to see if - * either of the hash tables have any entries -- would then have to do a - * linear search through the hash-table's array for the first non-empty - * spot - *Yuck. - * - *Alternatively, could keep two hash tables updated all the time -- one that - * does the receive_type and receive_from_to and a second that does - * receive_any -- would only hash the second table by the receive procr. - * When remove from one table, keep back-links to both tables, so can also - * quickly remove from other table. - *Cost is doing two hash-table lookups for every insert. - * If ever add receive_any, looking like this second option easier and even - * less costly. - */ -void -handleReceiveAny( VOMPSemReq *semReq, VOMPSemEnv *semEnv) - { - - } - - -void -handleReceiveType( VOMPSemReq *semReq, VOMPSemEnv *semEnv) - { SlaveVP *sendPr, *receivePr; - int key[] = {0,0,0}; - VOMPSemReq *waitingReq; - HashEntry *entry; - HashTable *commHashTbl = semEnv->commHashTbl; - - receivePr = semReq->receivePr; - - DEBUG__printf1(dbgRqstHdlr,"ReceiveType request from processor %d",receivePr->slaveID) - - key[0] = (int)receivePr->slaveID; - key[1] = (int)(semReq->msgType); - //key[2] acts as the 0 that terminates the string - - - entry = giveEntryElseInsertReqst((char*)key, semReq, commHashTbl);//clones - if( entry == NULL ) return; //was just inserted - - waitingReq = (VOMPSemReq *)entry->content; //previously cloned by insert - - //At this point, know have waiting request(s) -- should be send(s) - if( waitingReq->reqType == send_type ) - { //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 ) - { deleteEntryFromTable( 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 - receivePr->dataRetFromReq = waitingReq->msg; - - //bring both processors back from suspend - sendPr = waitingReq->sendPr; - 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; - //addToListOfArraysDependency(newd,semEnv->commDependenciesList); - addToListOfArrays(Dependency,newd,semEnv->dynDependenciesList); - int32 groupId = semReq->msgType; - if(semEnv->ntonGroupsInfo->numInArray <= groupId){ - makeHighestDynArrayIndexBeAtLeast(semEnv->ntonGroupsInfo, groupId); - } - 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( sendPr, semEnv ); - resume_slaveVP( receivePr, semEnv ); - - return; - } - printf("\nLang Impl Error: Should never be two waiting receives!\n"); - } - - -/* - */ -void -handleReceiveFromTo( VOMPSemReq *semReq, VOMPSemEnv *semEnv) - { SlaveVP *sendPr, *receivePr; - int key[] = {0,0,0}; - VOMPSemReq *waitingReq; - HashEntry *entry; - HashTable *commHashTbl = semEnv->commHashTbl; - - DEBUG__printf2(dbgRqstHdlr,"ReceiveFromTo %d : %d",semReq->sendPr->slaveID,semReq->receivePr->slaveID) - - receivePr = semReq->receivePr; - sendPr = semReq->sendPr; //for receive from-to, know send procr - - key[0] = (int)receivePr->slaveID; - key[1] = (int)sendPr->slaveID; - //key[2] acts at the 0 that terminates the string - - entry = giveEntryElseInsertReqst( (char *)key, semReq, commHashTbl); - if( entry == NULL ) return; //was just inserted - - waitingReq = (VOMPSemReq *)entry->content; - - //At this point, know have waiting request(s) -- should be send(s) - 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; - //addToListOfArraysDependency(newd,semEnv->commDependenciesList); - addToListOfArrays(Dependency,newd,semEnv->commDependenciesList); - #endif - //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"); - deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too - - //attach msg that's in the send request to receiving procr - // when comes back from suspend, will have msg in dataRetFromReq - receivePr->dataRetFromReq = waitingReq->msg; - - //bring both processors back from suspend - sendPr = waitingReq->sendPr; - VMS_PI__free( waitingReq ); - - resume_slaveVP( sendPr, semEnv ); - resume_slaveVP( receivePr, semEnv ); - - return; - } - printf("\nLang Impl Error: Should never be two waiting receives!\n"); - } - - - -//=============================================== -void -handleTransferTo( VOMPSemReq *semReq, VOMPSemEnv *semEnv) - { - - } - -void -handleTransferOut( VOMPSemReq *semReq, VOMPSemEnv *semEnv) - { - - } - - -/* - */ -void -handleMalloc( VOMPSemReq *semReq, SlaveVP *requestingPr, VOMPSemEnv *semEnv ) +handleMalloc( VSsSemReq *semReq, SlaveVP *requestingPr, VSsSemEnv *semEnv ) { void *ptr; DEBUG__printf1(dbgRqstHdlr,"Malloc request from processor %d",requestingPr->slaveID) @@ -422,7 +478,7 @@ /* */ void -handleFree( VOMPSemReq *semReq, SlaveVP *requestingPr, VOMPSemEnv *semEnv ) +handleFree( VSsSemReq *semReq, SlaveVP *requestingPr, VSsSemEnv *semEnv ) { DEBUG__printf1(dbgRqstHdlr,"Free request from processor %d",requestingPr->slaveID) VMS_PI__free( semReq->ptrToFree ); @@ -436,8 +492,8 @@ * end-label. Else, sets flag and resumes normally. */ void inline -handleStartSingleton_helper( VOMPSingleton *singleton, SlaveVP *reqstingPr, - VOMPSemEnv *semEnv ) +handleStartSingleton_helper( VSsSingleton *singleton, SlaveVP *reqstingPr, + VSsSemEnv *semEnv ) { if( singleton->hasFinished ) { //the code that sets the flag to true first sets the end instr addr @@ -459,22 +515,22 @@ } } void inline -handleStartFnSingleton( VOMPSemReq *semReq, SlaveVP *requestingPr, - VOMPSemEnv *semEnv ) - { VOMPSingleton *singleton; +handleStartFnSingleton( VSsSemReq *semReq, SlaveVP *requestingPr, + VSsSemEnv *semEnv ) + { VSsSingleton *singleton; DEBUG__printf1(dbgRqstHdlr,"StartFnSingleton request from processor %d",requestingPr->slaveID) singleton = &(semEnv->fnSingletons[ semReq->singletonID ]); handleStartSingleton_helper( singleton, requestingPr, semEnv ); } void inline -handleStartDataSingleton( VOMPSemReq *semReq, SlaveVP *requestingPr, - VOMPSemEnv *semEnv ) - { VOMPSingleton *singleton; +handleStartDataSingleton( VSsSemReq *semReq, SlaveVP *requestingPr, + VSsSemEnv *semEnv ) + { VSsSingleton *singleton; DEBUG__printf1(dbgRqstHdlr,"StartDataSingleton request from processor %d",requestingPr->slaveID) if( *(semReq->singletonPtrAddr) == NULL ) - { singleton = VMS_PI__malloc( sizeof(VOMPSingleton) ); + { singleton = VMS_PI__malloc( sizeof(VSsSingleton) ); singleton->waitQ = makeVMSQ(); singleton->endInstrAddr = 0x0; singleton->hasBeenStarted = FALSE; @@ -488,8 +544,8 @@ void inline -handleEndSingleton_helper( VOMPSingleton *singleton, SlaveVP *requestingPr, - VOMPSemEnv *semEnv ) +handleEndSingleton_helper( VSsSingleton *singleton, SlaveVP *requestingPr, + VSsSemEnv *semEnv ) { PrivQueueStruc *waitQ; int32 numWaiting, i; SlaveVP *resumingPr; @@ -514,10 +570,10 @@ } void inline -handleEndFnSingleton( VOMPSemReq *semReq, SlaveVP *requestingPr, - VOMPSemEnv *semEnv ) +handleEndFnSingleton( VSsSemReq *semReq, SlaveVP *requestingPr, + VSsSemEnv *semEnv ) { - VOMPSingleton *singleton; + VSsSingleton *singleton; DEBUG__printf1(dbgRqstHdlr,"EndFnSingleton request from processor %d",requestingPr->slaveID) @@ -525,10 +581,10 @@ handleEndSingleton_helper( singleton, requestingPr, semEnv ); } void inline -handleEndDataSingleton( VOMPSemReq *semReq, SlaveVP *requestingPr, - VOMPSemEnv *semEnv ) +handleEndDataSingleton( VSsSemReq *semReq, SlaveVP *requestingPr, + VSsSemEnv *semEnv ) { - VOMPSingleton *singleton; + VSsSingleton *singleton; DEBUG__printf1(dbgRqstHdlr,"EndDataSingleton request from processor %d",requestingPr->slaveID) @@ -541,7 +597,7 @@ * pointer out of the request and call it, then resume the VP. */ void -handleAtomic( VOMPSemReq *semReq, SlaveVP *requestingPr, VOMPSemEnv *semEnv ) +handleAtomic( VSsSemReq *semReq, SlaveVP *requestingPr, VSsSemEnv *semEnv ) { DEBUG__printf1(dbgRqstHdlr,"Atomic request from processor %d",requestingPr->slaveID) semReq->fnToExecInMaster( semReq->dataForFn ); @@ -563,9 +619,9 @@ *If NULL, then write requesting into the field and resume. */ void -handleTransStart( VOMPSemReq *semReq, SlaveVP *requestingPr, - VOMPSemEnv *semEnv ) - { VOMPSemData *semData; +handleTransStart( VSsSemReq *semReq, SlaveVP *requestingPr, + VSsSemEnv *semEnv ) + { VSsSemData *semData; TransListElem *nextTransElem; DEBUG__printf1(dbgRqstHdlr,"TransStart request from processor %d",requestingPr->slaveID) @@ -585,7 +641,7 @@ semData->lastTransEntered = nextTransElem; //get the structure for this transaction ID - VOMPTrans * + VSsTrans * transStruc = &(semEnv->transactionStrucs[ semReq->transID ]); if( transStruc->VPCurrentlyExecuting == NULL ) @@ -616,10 +672,10 @@ * resume both. */ void -handleTransEnd(VOMPSemReq *semReq, SlaveVP *requestingPr, VOMPSemEnv *semEnv) - { VOMPSemData *semData; +handleTransEnd(VSsSemReq *semReq, SlaveVP *requestingPr, VSsSemEnv *semEnv) + { VSsSemData *semData; SlaveVP *waitingPr; - VOMPTrans *transStruc; + VSsTrans *transStruc; TransListElem *lastTrans; DEBUG__printf1(dbgRqstHdlr,"TransEnd request from processor %d",requestingPr->slaveID) diff -r 5ed4d833506e -r f2ed1c379fe7 VSs_Request_Handlers.h --- a/VSs_Request_Handlers.h Thu May 24 07:34:21 2012 -0700 +++ b/VSs_Request_Handlers.h Wed May 30 15:02:38 2012 -0700 @@ -6,51 +6,41 @@ * */ -#ifndef _VOMP_REQ_H -#define _VOMP_REQ_H +#ifndef _VSs_REQ_H +#define _VSs_REQ_H -#include "VOMP.h" +#include "VSs.h" -/*This header defines everything specific to the VOMP semantic plug-in +/*This header defines everything specific to the VSs semantic plug-in */ inline void -handleSendType( VOMPSemReq *semReq, VOMPSemEnv *semEnv); +handleSubmitTask( VSsSemReq *semReq, VSsSemEnv *semEnv); inline void -handleSendFromTo( VOMPSemReq *semReq, VOMPSemEnv *semEnv); +handleEndTask( VSsSemReq *semReq, VSsSemEnv *semEnv); inline void -handleReceiveAny( VOMPSemReq *semReq, VOMPSemEnv *semEnv); +handleMalloc( VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv); inline void -handleReceiveType( VOMPSemReq *semReq, VOMPSemEnv *semEnv); +handleFree( VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv ); inline void -handleReceiveFromTo( VOMPSemReq *semReq, VOMPSemEnv *semEnv); +handleTransEnd(VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv*semEnv); inline void -handleTransferTo( VOMPSemReq *semReq, VOMPSemEnv *semEnv); +handleTransStart( VSsSemReq *semReq, SlaveVP *requestingSlv, + VSsSemEnv *semEnv ); inline void -handleTransferOut( VOMPSemReq *semReq, VOMPSemEnv *semEnv); +handleAtomic( VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv); inline void -handleMalloc( VOMPSemReq *semReq, SlaveVP *requestingSlv, VOMPSemEnv *semEnv); +handleStartFnSingleton( VSsSemReq *semReq, SlaveVP *reqstingSlv, + VSsSemEnv *semEnv ); inline void -handleFree( VOMPSemReq *semReq, SlaveVP *requestingSlv, VOMPSemEnv *semEnv ); +handleEndFnSingleton( VSsSemReq *semReq, SlaveVP *requestingSlv, + VSsSemEnv *semEnv ); inline void -handleTransEnd(VOMPSemReq *semReq, SlaveVP *requestingSlv, VOMPSemEnv*semEnv); +handleStartDataSingleton( VSsSemReq *semReq, SlaveVP *reqstingSlv, + VSsSemEnv *semEnv ); inline void -handleTransStart( VOMPSemReq *semReq, SlaveVP *requestingSlv, - VOMPSemEnv *semEnv ); -inline void -handleAtomic( VOMPSemReq *semReq, SlaveVP *requestingSlv, VOMPSemEnv *semEnv); -inline void -handleStartFnSingleton( VOMPSemReq *semReq, SlaveVP *reqstingSlv, - VOMPSemEnv *semEnv ); -inline void -handleEndFnSingleton( VOMPSemReq *semReq, SlaveVP *requestingSlv, - VOMPSemEnv *semEnv ); -inline void -handleStartDataSingleton( VOMPSemReq *semReq, SlaveVP *reqstingSlv, - VOMPSemEnv *semEnv ); -inline void -handleEndDataSingleton( VOMPSemReq *semReq, SlaveVP *requestingSlv, - VOMPSemEnv *semEnv ); +handleEndDataSingleton( VSsSemReq *semReq, SlaveVP *requestingSlv, + VSsSemEnv *semEnv ); -#endif /* _VOMP_REQ_H */ +#endif /* _VSs_REQ_H */