# HG changeset patch # User Nina Engelhardt # Date 1370277296 -7200 # Node ID 0715109abb082e77c8b9a9b283af6c8de6dc792c # Parent a951b38d2cfc27bcd12f071548c9b4b66e71af7d make wrapper lib for linking against files produced by mercurium (ompss preprocessor) -- ! separates args and dependencies diff -r a951b38d2cfc -r 0715109abb08 VSs.c --- a/VSs.c Fri May 17 17:49:49 2013 +0200 +++ b/VSs.c Mon Jun 03 18:34:56 2013 +0200 @@ -94,7 +94,7 @@ // the parent be already ended, and have one child (the seed). This // will make the dissipate handler do the right thing when the seed // is dissipated. - threadTaskStub = create_thread_task_stub( initData ); + threadTaskStub = create_thread_task_stub( initData); parentTaskStub = create_thread_task_stub( NULL ); parentTaskStub->isEnded = TRUE; parentTaskStub->numLiveChildThreads = 1; //so dissipate works for seed @@ -248,6 +248,7 @@ semanticEnv->argPtrHashTbl = makeHashTable32( 20, &free_pointer_entry ); semanticEnv->commHashTbl = makeHashTable32( 16, &VMS_int__free ); + semanticEnv->criticalHashTbl = makeHashTable32( 16, &VMS_int__free ); semanticEnv->nextCoreToGetNewSlv = 0; @@ -266,12 +267,6 @@ semanticEnv->fnSingletons[i].hasFinished = FALSE; semanticEnv->fnSingletons[i].waitQ = makeVMSQ(); semanticEnv->transactionStrucs[i].waitingVPQ = makeVMSQ(); - semanticEnv->criticalSection[i].isOccupied = FALSE; - semanticEnv->criticalSection[i].waitQ = makeVMSQ(); -#ifdef HOLISTIC__TURN_ON_PERF_COUNTERS - semanticEnv->criticalSection[i].previous.vp = 0; - semanticEnv->criticalSection[i].previous.task = 0; -#endif } semanticEnv->numLiveExtraTaskSlvs = 0; //must be last @@ -444,7 +439,6 @@ for (i = 0; i < NUM_STRUCS_IN_SEM_ENV; i++) { freePrivQ(semanticEnv->fnSingletons[i].waitQ); freePrivQ(semanticEnv->transactionStrucs[i].waitingVPQ); - freePrivQ(semanticEnv->criticalSection[i].waitQ); } freePrivQ(semanticEnv->freeExtraTaskSlvQ); @@ -453,6 +447,7 @@ freePrivQ(semanticEnv->deferredSubmitsQ); freeHashTable(semanticEnv->argPtrHashTbl); freeHashTable(semanticEnv->commHashTbl); + freeHashTable(semanticEnv->criticalHashTbl); VMS_int__free(semanticEnv->coreIsDone); VMS_int__free(_VMSMasterEnv->semanticEnv); @@ -503,22 +498,23 @@ //======================= task submit and end ============================== + /* */ -void -VSs__submit_task( VSsTaskType *taskType, void *args) - { VSsSemReq reqData; +void VSs__submit_task(VSsTaskType *taskType, void *args, void* deps) { + VSsSemReq reqData; - reqData.reqType = submit_task; - - reqData.taskType = taskType; - reqData.args = args; - reqData.callingSlv = currVP; - - reqData.taskID = NULL; - - VMS_WL__send_sem_request( &reqData, currVP ); - } + reqData.reqType = submit_task; + + reqData.taskType = taskType; + reqData.args = args; + reqData.deps = deps; + reqData.callingSlv = currVP; + + reqData.taskID = NULL; + + VMS_WL__send_sem_request(&reqData, currVP); +} int32 * VSs__create_taskID_of_size( int32 numInts) @@ -527,21 +523,21 @@ taskID = VMS_WL__malloc( sizeof(int32) + numInts * sizeof(int32) ); taskID[0] = numInts; return taskID; - } +} -void -VSs__submit_task_with_ID( VSsTaskType *taskType, void *args, int32 *taskID) - { VSsSemReq reqData; +void VSs__submit_task_with_ID(VSsTaskType *taskType, void *args, void* deps, int32 *taskID) { + VSsSemReq reqData; - reqData.reqType = submit_task; - - reqData.taskType = taskType; - reqData.args = args; - reqData.taskID = taskID; - reqData.callingSlv = currVP; - - VMS_WL__send_sem_request( &reqData, currVP ); - } + reqData.reqType = submit_task; + + reqData.taskType = taskType; + reqData.args = args; + reqData.deps = deps; + reqData.taskID = taskID; + reqData.callingSlv = currVP; + + VMS_WL__send_sem_request(&reqData, currVP); +} /*This call is the last to happen in every task. It causes the slave to @@ -600,25 +596,25 @@ } void -VSs__start_critical(int32 name){ +VSs__start_critical(void* lock){ VSsSemReq reqData; reqData.reqType = critical_start; reqData.callingSlv = currVP; - reqData.criticalID = name; + reqData.criticalID = lock; VMS_WL__send_sem_request( &reqData, currVP ); } void -VSs__end_critical(int32 name){ +VSs__end_critical(void* lock){ VSsSemReq reqData; reqData.reqType = critical_end; reqData.callingSlv = currVP; - reqData.criticalID = name; + reqData.criticalID = lock; VMS_WL__send_sem_request( &reqData, currVP ); } diff -r a951b38d2cfc -r 0715109abb08 VSs.h --- a/VSs.h Fri May 17 17:49:49 2013 +0200 +++ b/VSs.h Mon Jun 03 18:34:56 2013 +0200 @@ -58,10 +58,9 @@ typedef struct { VSsTaskFnPtr fn; - 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 numDeps;//how many of args have dependencies + int32 *depsTypes; //says reader, writer, or non-ctld + size_t *depsSizes; //for detecting overlap int32 sizeOfArgs; //for memcpy of args struct } VSsTaskType; @@ -80,7 +79,8 @@ VSsPointerEntry; typedef struct { - void **args; //ctld args must come first, as ptrs + void **args; //for calling only, can contain values + void** depsAddrs; //pointers only VSsTaskType *taskType; int32 *taskID; int32 numBlockingProp; @@ -92,7 +92,7 @@ bool32 isWaitingForChildTasksToEnd; bool32 isWaitingForChildThreadsToEnd; bool32 isEnded; - int *argsMask; + int *depsMask; #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC Unit parentUnit; Unit firstOfTask; @@ -179,6 +179,7 @@ SlaveVP *callingSlv; VSsTaskType *taskType; void *args; + void *deps; VSsTaskStub *taskStub; SlaveVP *senderSlv; @@ -204,7 +205,7 @@ void *dataForFn; int32 transID; - int32 criticalID; + void* criticalID; } /* VSsSemReq */; @@ -217,6 +218,7 @@ SlaveVP *slotTaskSlvs[NUM_CORES][NUM_ANIM_SLOTS]; HashTable *argPtrHashTbl; HashTable *commHashTbl; + HashTable *criticalHashTbl; int32 numLiveExtraTaskSlvs; int32 numLiveThreadSlvs; int32 nextCoreToGetNewSlv; @@ -225,7 +227,7 @@ //fix limit on num with dynArray VSsSingleton fnSingletons[NUM_STRUCS_IN_SEM_ENV]; VSsTrans transactionStrucs[NUM_STRUCS_IN_SEM_ENV]; - VSsCritical criticalSection[NUM_STRUCS_IN_SEM_ENV]; + bool32 *coreIsDone; int32 numCoresDone; @@ -331,13 +333,13 @@ //======================= void -VSs__submit_task( VSsTaskType *taskType, void *args); +VSs__submit_task( VSsTaskType *taskType, void *args, void* deps); int32 * VSs__create_taskID_of_size( int32 numInts); void -VSs__submit_task_with_ID( VSsTaskType *taskType, void *args, int32 *taskID); +VSs__submit_task_with_ID( VSsTaskType *taskType, void *args, void* deps, int32 *taskID); void VSs__run_task(TopLevelFnPtr fnPtr, void *initData); @@ -352,10 +354,10 @@ VSs__taskwait_on(void* ptr); void -VSs__start_critical(int32 name); +VSs__start_critical(void* name); void -VSs__end_critical(int32 name); +VSs__end_critical(void* name); int32 * VSs__give_self_taskID(); diff -r a951b38d2cfc -r 0715109abb08 VSs_PluginFns.c --- a/VSs_PluginFns.c Fri May 17 17:49:49 2013 +0200 +++ b/VSs_PluginFns.c Mon Jun 03 18:34:56 2013 +0200 @@ -413,8 +413,9 @@ newStub->slaveAssignedTo = NULL; //set later newStub->taskType = IS_A_THREAD; newStub->ptrEntries = NULL; - newStub->argsMask = NULL; + newStub->depsMask = NULL; newStub->args = initData; + newStub->depsAddrs = NULL; newStub->numLiveChildTasks = 0; newStub->numLiveChildThreads = 0; newStub->parentTaskStub = NULL; diff -r a951b38d2cfc -r 0715109abb08 VSs_Request_Handlers.c --- a/VSs_Request_Handlers.c Fri May 17 17:49:49 2013 +0200 +++ b/VSs_Request_Handlers.c Mon Jun 03 18:34:56 2013 +0200 @@ -98,16 +98,17 @@ * to new space */ VSsTaskStub * -create_task_stub(VSsTaskType *taskType, void **args) { +create_task_stub(VSsTaskType *taskType, void** deps, void **args) { void **newArgs; VSsTaskStub* newStub = VMS_int__malloc(sizeof (VSsTaskStub) + taskType->sizeOfArgs); - newStub->numBlockingProp = taskType->numCtldArgs; + newStub->numBlockingProp = taskType->numDeps; newStub->slaveAssignedTo = NULL; newStub->taskType = taskType; newStub->ptrEntries = - VMS_int__malloc(taskType->numCtldArgs * sizeof (VSsPointerEntry *)); + VMS_int__malloc(taskType->numDeps * sizeof (VSsPointerEntry *)); newArgs = (void **) ((uint8 *) newStub + sizeof (VSsTaskStub)); newStub->args = newArgs; + newStub->depsAddrs = deps; newStub->numLiveChildTasks = 0; newStub->numLiveChildThreads = 0; newStub->isWaitingForChildTasksToEnd = FALSE; @@ -115,8 +116,8 @@ newStub->isEnded = FALSE; newStub->taskID = NULL; newStub->parentTaskStub = NULL; - newStub->argsMask = VMS_int__malloc(sizeof(int) * taskType->numCtldArgs); - memset(newStub->argsMask, 0, sizeof(int) * taskType->numCtldArgs); + newStub->depsMask = VMS_int__malloc(sizeof(int) * taskType->numDeps); + memset(newStub->depsMask, 0, sizeof(int) * taskType->numDeps); //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); @@ -140,39 +141,39 @@ //check for identical pointers in args -- mask all but one copy //if one of pointers is writer, non-masked arg must be writer int mask_duplicates(VSsTaskStub *taskStub){ - int argNum, i; - int numUniqueArgs = 0; + int depNum, i; + int numUniqueDeps = 0; VSsTaskType* taskType = taskStub->taskType; - void **args = taskStub->args; + void **deps = taskStub->depsAddrs; - for(argNum = 0; argNum < taskType->numCtldArgs; argNum++){ + for(depNum = 0; depNum < taskType->numDeps; depNum++){ //if already masked, don't need to check again - if(taskStub->argsMask[argNum]) continue; + if(taskStub->depsMask[depNum]) continue; - int unmasked = argNum; - for(i=argNum+1; inumCtldArgs; i++){ - if(args[argNum] == args[i]){ - if(taskType->argTypes[i] == WRITER){ - taskStub->argsMask[unmasked] = TRUE; + int unmasked = depNum; + for(i=depNum+1; inumDeps; i++){ + if(deps[depNum] == deps[i]){ + if(taskType->depsTypes[i] == WRITER){ + taskStub->depsMask[unmasked] = TRUE; unmasked = i; } else { - taskStub->argsMask[i] = TRUE; + taskStub->depsMask[i] = TRUE; } } } } - for(i=0; inumCtldArgs; i++){ - if(!taskStub->argsMask[i]) numUniqueArgs++; + for(i=0; inumDeps; i++){ + if(!taskStub->depsMask[i]) numUniqueDeps++; } - return numUniqueArgs; + return numUniqueDeps; } void do_submit(VSsSemReq *semReq, VSsSemEnv *semEnv){ uint32 key[5]; HashEntry *rawHashEntry; //has char *, but use with uint32 * VSsPointerEntry *ptrEntry; //contents of hash table entry for an arg pointer - void **args; + void **depsAddrs; VSsTaskStub *taskStub; VSsTaskType *taskType; VSsTaskStubCarrier *taskCarrier; @@ -180,7 +181,7 @@ HashTable * argPtrHashTbl = semEnv->argPtrHashTbl; - int32 argNum; + int32 depNum; if(!semReq) { DEBUG__printf(dbgRqstHdlr,"***submitted Req is null***\n") @@ -195,9 +196,9 @@ * inputs from the sequential portion. Note that all controlled arguments * are pointers, and marked as controlled in the application code). */ - args = semReq->args; + depsAddrs = semReq->deps; taskType = semReq->taskType; - taskStub = create_task_stub(taskType, args); //copies arg ptrs + taskStub = create_task_stub(taskType, depsAddrs, semReq->args); //copies arg ptrs //check for identical pointers in args -- mask all but one copy //if one of pointers is writer, non-masked arg must be writer int numUniqueArgs = mask_duplicates(taskStub); @@ -225,12 +226,12 @@ * looking up the hash entry. (If none, create one). */ - for (argNum = 0; argNum < taskType->numCtldArgs; argNum++) { + for (depNum = 0; depNum < taskType->numDeps; depNum++) { //only process unmasked args - if(taskStub->argsMask[argNum]) continue; + if(taskStub->depsMask[depNum]) continue; key[0] = 4; //two 32b values in key - *((uint64*) & key[1]) = (uint64) args[argNum]; //write 64b into two 32b + *((uint64*) & key[1]) = (uint64) depsAddrs[depNum]; //write 64b into two 32b *((uint64*) & key[3]) = (uint64) taskStub->parentTaskStub ; /*If the hash entry was chained, put it at the @@ -247,12 +248,12 @@ rawHashEntry = addValueIntoTable32(key, ptrEntry, argPtrHashTbl); } } - taskStub->ptrEntries[argNum] = ptrEntry; + taskStub->ptrEntries[depNum] = 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 (taskType->depsTypes[depNum] == 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 @@ -268,7 +269,7 @@ } else { /*Otherwise, the reader is put into the hash-entry's Q of * waiters*/ DEBUG__printf_w_task(dbgSS, taskStub, "getting in line for ptrEntry %p (read)", ptrEntry); - taskCarrier = create_task_carrier(taskStub, argNum, READER); + taskCarrier = create_task_carrier(taskStub, depNum, READER); writePrivQ(taskCarrier, ptrEntry->waitersQ); } } else //arg is a writer @@ -289,7 +290,7 @@ ptrEntry->hasEnabledNonFinishedWriter = TRUE; } else {/*Otherwise, put the writer into the entry's Q of waiters.*/ DEBUG__printf_w_task(dbgSS,taskStub,"getting in line for ptrEntry %p (write)",ptrEntry); - taskCarrier = create_task_carrier(taskStub, argNum, WRITER); + taskCarrier = create_task_carrier(taskStub, depNum, WRITER); writePrivQ(taskCarrier, ptrEntry->waitersQ); } } @@ -484,7 +485,7 @@ void handleEndTask(VSsSemReq *semReq, VSsSemEnv *semEnv) { VSsPointerEntry *ptrEntry; //contents of hash table entry for an arg pointer - void **args; + void **depsAddrs; VSsSemData *endingSlvSemData; VSsTaskStub *endingTaskStub, *waitingTaskStub, *parent; VSsTaskType *endingTaskType; @@ -495,7 +496,7 @@ endingSlvSemData = (VSsSemData *) semReq->callingSlv->semanticData; endingTaskStub = endingSlvSemData->taskStub; - args = endingTaskStub->args; + depsAddrs = endingTaskStub->depsAddrs; endingTaskType = endingTaskStub->taskType; ptrEntries = endingTaskStub->ptrEntries; //saved in stub when create @@ -534,15 +535,15 @@ /*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++) { + int32 depNum; + for (depNum = 0; depNum < endingTaskType->numDeps; depNum++) { //only process unmasked args - if(endingTaskStub->argsMask[argNum]) continue; + if(endingTaskStub->depsMask[depNum]) continue; - ptrEntry = ptrEntries[argNum]; + ptrEntry = ptrEntries[depNum]; /*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 + if (endingTaskType->depsTypes[depNum] == READER) { /*then decrement the enabled and non-finished reader-count in * the hash-entry. */ ptrEntry->numEnabledNonDoneReaders -= 1; DEBUG__printf(dbgSS,"Releasing read on ptrEntry %p",ptrEntry) @@ -737,8 +738,8 @@ { VMS_PI__free(stubToFree->ptrEntries); } - if (stubToFree->argsMask != NULL) { - VMS_PI__free(stubToFree->argsMask); + if (stubToFree->depsMask != NULL) { + VMS_PI__free(stubToFree->depsMask); } if(stubToFree->taskID != NULL) { //TaskID is handed from user most of the time, not sure if overreaching (but why would you want to keep it?) VMS_PI__free(stubToFree->taskID); @@ -1216,9 +1217,23 @@ } } +VSsCritical* create_critical_section(){ + VSsCritical* criticalSection = (VSsCritical*) malloc(sizeof(VSsCritical)); + + criticalSection->isOccupied = FALSE; + criticalSection->previous.vp = 0; + criticalSection->previous.task = 0; + criticalSection->waitQ = makeVMSQ(); + + return criticalSection; +} + void handleCriticalStart(VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv) { VSsSemData* semData; - int32 criticalID; + void* criticalID; + VSsCritical* criticalSection; + HashEntry *rawHashEntry; //has char *, but use with uint32 * + uint32 key[3]; DEBUG__printf1(dbgRqstHdlr, "CriticalStart request from processor %d", requestingSlv->slaveID); @@ -1227,18 +1242,40 @@ semData = (VSsSemData *) semReq->callingSlv->semanticData; criticalID = semReq->criticalID; - if (!semEnv->criticalSection[criticalID].isOccupied) { - semEnv->criticalSection[criticalID].isOccupied = TRUE; + + key[0] = 2; //two 32b values in key + *((uint64*) & key[1]) = (uint64) criticalID; //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, semEnv->criticalHashTbl); + if (rawHashEntry == NULL) { //adding a value auto-creates the hash-entry + criticalSection = create_critical_section(); + rawHashEntry = addValueIntoTable32(key, criticalSection, semEnv->criticalHashTbl); + } else { + criticalSection = (VSsCritical *) rawHashEntry->content; + if (criticalSection == NULL) { + criticalSection = create_critical_section(); + rawHashEntry = addValueIntoTable32(key, criticalSection, semEnv->criticalHashTbl); + } + } + + if (criticalSection->isOccupied) { + criticalSection->isOccupied = TRUE; resume_slaveVP(requestingSlv, semEnv); } else { - writePrivQ(requestingSlv, semEnv->criticalSection[criticalID].waitQ); + writePrivQ(requestingSlv, criticalSection->waitQ); } } void handleCriticalEnd(VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv){ VSsSemData* semData; SlaveVP *waitingSlv; - int32 criticalID; + void* criticalID; + VSsCritical* criticalSection; + HashEntry *rawHashEntry; //has char *, but use with uint32 * + uint32 key[3]; DEBUG__printf1(dbgRqstHdlr, "CriticalEnd request from processor %d", requestingSlv->slaveID); @@ -1247,10 +1284,32 @@ semData = (VSsSemData *) semReq->callingSlv->semanticData; criticalID = semReq->criticalID; - semEnv->criticalSection[criticalID].isOccupied = FALSE; - waitingSlv = readPrivQ(semEnv->criticalSection[criticalID].waitQ); + + + key[0] = 2; //two 32b values in key + *((uint64*) & key[1]) = (uint64) criticalID; //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, semEnv->criticalHashTbl); + if (rawHashEntry == NULL) { //adding a value auto-creates the hash-entry + criticalSection = create_critical_section(); + rawHashEntry = addValueIntoTable32(key, criticalSection, semEnv->criticalHashTbl); + } else { + criticalSection = (VSsCritical *) rawHashEntry->content; + if (criticalSection == NULL) { + criticalSection = create_critical_section(); + rawHashEntry = addValueIntoTable32(key, criticalSection, semEnv->criticalHashTbl); + } + } + + + + criticalSection->isOccupied = FALSE; + waitingSlv = readPrivQ(criticalSection->waitQ); if(waitingSlv!=NULL){ - semEnv->criticalSection[criticalID].isOccupied = TRUE; + criticalSection->isOccupied = TRUE; resume_slaveVP(waitingSlv, semEnv); } resume_slaveVP(requestingSlv, semEnv);