# HG changeset patch # User Me # Date 1289687913 28800 # Node ID ad29ff7a02095401d12127bdb0f72beade34ea75 # Parent 562e68094af7f81e8d2f22a73b4d62da8e4407d7 Buggy version of singltons -- data plus Fn singletons now -- about to fix diff -r 562e68094af7 -r ad29ff7a0209 SSR.h --- a/SSR.h Fri Nov 12 08:43:20 2010 -0800 +++ b/SSR.h Sat Nov 13 14:38:33 2010 -0800 @@ -27,6 +27,23 @@ /*Semantic layer-specific data sent inside a request from lib called in app * to request handler called in MasterLoop */ + +typedef struct + { + VirtProcr *VPCurrentlyExecuting; + PrivQueueStruc *waitingVPQ; + } +SSRTrans; + +typedef struct + { + int32 hasBeenStarted; + int32 hasFinished; + void *endInstrAddr; + PrivQueueStruc *waitQ; + } +SSRSingleton; + enum SSRReqType { send_type = 1, @@ -38,7 +55,10 @@ transfer_out, malloc_req, free_req, - singleton, + singleton_fn_start, + singleton_fn_end, + singleton_data_start, + singleton_data_end, atomic, trans_start, trans_end @@ -60,7 +80,7 @@ void *ptrToFree; int32 singletonID; - void *endJumpPt; + SSRSingleton **singletonAddr; PtrToAtomicFn fnToExecInMaster; void *dataForFn; @@ -72,13 +92,6 @@ typedef struct { - VirtProcr *VPCurrentlyExecuting; - PrivQueueStruc *waitingVPQ; - } -SSRTrans; - -typedef struct - { PrivQueueStruc **readyVPQs; HashTable *commHashTbl; int32 numVirtPr; @@ -86,7 +99,7 @@ int32 primitiveStartTime; //fix limit on num with dynArray - int32 singletonHasBeenExecutedFlags[NUM_STRUCS_IN_SEM_ENV]; + SSRSingleton fnSingletons[NUM_STRUCS_IN_SEM_ENV]; SSRTrans transactionStrucs[NUM_STRUCS_IN_SEM_ENV]; } SSRSemEnv; @@ -187,8 +200,16 @@ //======================= Concurrency Stuff ====================== void -SSR__start_singleton( int32 singletonID, void *endSingletonLabelAddr, - VirtProcr *animPr ); +SSR__start_fn_singleton( int32 singletonID, VirtProcr *animPr ); + +void +SSR__end_fn_singleton( int32 singletonID, VirtProcr *animPr ); + +void +SSR__start_data_singleton( SSRSingleton **singeltonAddr, VirtProcr *animPr ); + +void +SSR__end_data_singleton( SSRSingleton **singletonAddr, VirtProcr *animPr ); void SSR__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster, diff -r 562e68094af7 -r ad29ff7a0209 SSR_PluginFns.c --- a/SSR_PluginFns.c Fri Nov 12 08:43:20 2010 -0800 +++ b/SSR_PluginFns.c Sat Nov 13 14:38:33 2010 -0800 @@ -114,7 +114,13 @@ break; case free_req: handleFree( semReq, reqPr, semEnv); break; - case singleton: handleSingleton( semReq, reqPr, semEnv); + case singleton_fn_start: handleStartFnSingleton(semReq, reqPr, semEnv); + break; + case singleton_fn_end: handleEndFnSingleton( semReq, reqPr, semEnv); + break; + case singleton_data_start:handleStartDataSingleton(semReq,reqPr,semEnv); + break; + case singleton_data_end: handleEndDataSingleton(semReq, reqPr, semEnv); break; case atomic: handleAtomic( semReq, reqPr, semEnv); break; diff -r 562e68094af7 -r ad29ff7a0209 SSR_Request_Handlers.c --- a/SSR_Request_Handlers.c Fri Nov 12 08:43:20 2010 -0800 +++ b/SSR_Request_Handlers.c Sat Nov 13 14:38:33 2010 -0800 @@ -371,17 +371,100 @@ /*Uses ID as index into array of flags. If flag already set, resumes from * end-label. Else, sets flag and resumes normally. */ -void -handleSingleton( SSRSemReq *semReq, VirtProcr *requestingPr, - SSRSemEnv *semEnv ) +void inline +handleStartSingleton_helper( SSRSingleton *singleton, VirtProcr *reqstingPr, + SSRSemEnv *semEnv ) { - if( semEnv->singletonHasBeenExecutedFlags[ semReq->singletonID ] ) - requestingPr->nextInstrPt = semReq->endJumpPt; + if( singleton->hasFinished ) + { //the code that sets the flag to true first sets the end instr addr + reqstingPr->dataRetFromReq = singleton->endInstrAddr; + resume_procr( reqstingPr, semEnv ); + return; + } + else if( singleton->hasBeenStarted ) + { //singleton is in-progress in a diff slave, so wait for it to finish + writePrivQ(reqstingPr, singleton->waitQ ); + return; + } else - semEnv->singletonHasBeenExecutedFlags[ semReq->singletonID ] = TRUE; + { //hasn't been started, so this is the first attempt at the singleton + singleton->hasBeenStarted = TRUE; + reqstingPr->dataRetFromReq = 0x0; + resume_procr( reqstingPr, semEnv ); + return; + } + } +void inline +handleStartFnSingleton( SSRSemReq *semReq, VirtProcr *requestingPr, + SSRSemEnv *semEnv ) + { SSRSingleton *singleton; + + singleton = &(semEnv->fnSingletons[ semReq->singletonID ]); + handleStartSingleton_helper( singleton, requestingPr, semEnv ); + } +void inline +handleStartDataSingleton( SSRSemReq *semReq, VirtProcr *requestingPr, + SSRSemEnv *semEnv ) + { SSRSingleton *singleton; + + if( *(semReq->singletonAddr) == NULL ) + { singleton = VMS__malloc( sizeof(SSRSingleton) ); + singleton->waitQ = makeVMSPrivQ(); + singleton->endInstrAddr = 0x0; + singleton->hasBeenStarted = FALSE; + singleton->hasFinished = FALSE; + *(semReq->singletonAddr) = singleton; + } + else + singleton = *(semReq->singletonAddr); + handleStartSingleton_helper( singleton, requestingPr, semEnv ); + } + + +void inline +handleEndSingleton_helper( SSRSingleton *singleton, VirtProcr *requestingPr, + SSRSemEnv *semEnv ) + { PrivQueueStruc *waitQ; + int32 numWaiting, i; + VirtProcr *resumingPr; + + if( singleton->hasFinished ) + { //by definition, only one slave should ever be able to run end singleton + // so if this is true, is an error + //VMS__throw_exception( "singleton code ran twice", requestingPr, NULL); + } + + singleton->hasFinished = TRUE; + waitQ = singleton->waitQ; + numWaiting = numInPrivQ( waitQ ); + for( i = 0; i < numWaiting; i++ ) + { //they will resume inside start singleton, then jmp to end singleton + resumingPr = readPrivQ( waitQ ); + resumingPr->dataRetFromReq = singleton->endInstrAddr; + resume_procr( resumingPr, semEnv ); + } resume_procr( requestingPr, semEnv ); - } + +} +void inline +handleEndFnSingleton( SSRSemReq *semReq, VirtProcr *requestingPr, + SSRSemEnv *semEnv ) + { + SSRSingleton *singleton; + + singleton = &(semEnv->fnSingletons[ semReq->singletonID ]); + handleEndSingleton_helper( singleton, requestingPr, semEnv ); + } +void inline +handleEndDataSingleton( SSRSemReq *semReq, VirtProcr *requestingPr, + SSRSemEnv *semEnv ) + { + SSRSingleton *singleton; + + singleton = *(semReq->singletonAddr); + handleEndSingleton_helper( singleton, requestingPr, semEnv ); + } /*This executes the function in the masterVP, take the function diff -r 562e68094af7 -r ad29ff7a0209 SSR_Request_Handlers.h --- a/SSR_Request_Handlers.h Fri Nov 12 08:43:20 2010 -0800 +++ b/SSR_Request_Handlers.h Sat Nov 13 14:38:33 2010 -0800 @@ -40,8 +40,17 @@ void handleAtomic( SSRSemReq *semReq, VirtProcr *requestingPr, SSRSemEnv *semEnv); void -handleSingleton( SSRSemReq *semReq, VirtProcr *requestingPr, - SSRSemEnv *semEnv ); +handleStartFnSingleton( SSRSemReq *semReq, VirtProcr *reqstingPr, + SSRSemEnv *semEnv ); +void +handleEndFnSingleton( SSRSemReq *semReq, VirtProcr *requestingPr, + SSRSemEnv *semEnv ); +void +handleStartDataSingleton( SSRSemReq *semReq, VirtProcr *reqstingPr, + SSRSemEnv *semEnv ); +void +handleEndDataSingleton( SSRSemReq *semReq, VirtProcr *requestingPr, + SSRSemEnv *semEnv ); #endif /* _SSR_REQ_H */ diff -r 562e68094af7 -r ad29ff7a0209 SSR_lib.c --- a/SSR_lib.c Fri Nov 12 08:43:20 2010 -0800 +++ b/SSR_lib.c Sat Nov 13 14:38:33 2010 -0800 @@ -213,7 +213,7 @@ for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) { - readyVPQs[ coreIdx ] = makePrivQ(); + readyVPQs[ coreIdx ] = makeVMSPrivQ(); } semanticEnv->readyVPQs = readyVPQs; @@ -228,8 +228,11 @@ //semanticEnv->transactionStrucs = makeDynArrayInfo( ); for( i = 0; i < NUM_STRUCS_IN_SEM_ENV; i++ ) { - semanticEnv->singletonHasBeenExecutedFlags[i] = FALSE; - semanticEnv->transactionStrucs[i].waitingVPQ = makePrivQ(); + semanticEnv->fnSingletons[i].hasBeenStarted = FALSE; + semanticEnv->fnSingletons[i].hasFinished = FALSE; + semanticEnv->fnSingletons[i].endInstrAddr = NULL; + semanticEnv->fnSingletons[i].waitQ = makeVMSPrivQ(); + semanticEnv->transactionStrucs[i].waitingVPQ = makeVMSPrivQ(); } } @@ -285,7 +288,7 @@ VirtProcr * SSR__create_procr_with_affinity( VirtProcrFnPtr fnPtr, void *initData, VirtProcr *creatingPr, int32 coreToScheduleOnto ) - { SSRSemReq reqData; + { SSRSemReq 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 @@ -297,6 +300,8 @@ reqData.sendPr = creatingPr; VMS__send_create_procr_req( &reqData, creatingPr ); + + return creatingPr->dataRetFromReq; } @@ -476,21 +481,110 @@ //=========================================================================== -/*Uses ID as index into array of flags. If flag already set, resumes from - * end-label. Else, sets flag and resumes normally. +/*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 + * matter how many cores or the timing of cores calling it. + * + *A data singleton is a ticket attached to data. That ticket can be used + * to get the data through the function exactly once, no matter how many + * times the data is given to the function, and no matter the timing of + * trying to get the data through from different cores. + */ + +/*Fn singleton uses ID as index into array of singleton structs held in the + * semantic environment. */ void -SSR__start_singleton( int32 singletonID, void *endSingletonLabelAddr, - VirtProcr *animPr ) +SSR__start_fn_singleton( int32 singletonID, VirtProcr *animPr ) { SSRSemReq reqData; // - reqData.reqType = singleton; + reqData.reqType = singleton_fn_start; reqData.singletonID = singletonID; - reqData.endJumpPt = endSingletonLabelAddr; VMS__send_sem_request( &reqData, animPr ); + if( animPr->dataRetFromReq ) //will be 0 or addr of label in end singleton + { + asm volatile("movl %0, %%eax; \ + jmp *%%eax" \ + /* outputs */ : \ + /* inputs */ : "g"(animPr->dataRetFromReq) \ + /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx","%edi","%esi"\ + ); + } + } + +/*Data singleton hands addr of loc holding a pointer to a singleton struct. + * The start_data_singleton makes the structure and puts its addr into the + * location. + */ +void +SSR__start_data_singleton( SSRSingleton **singletonAddr, VirtProcr *animPr ) + { + SSRSemReq reqData; + + // + reqData.reqType = singleton_data_start; + reqData.singletonAddr = singletonAddr; + + VMS__send_sem_request( &reqData, animPr ); + if( animPr->dataRetFromReq ) //either 0 or addr of label in end singleton + { animPr->procrID += 10000; + asm volatile("movl %0, %%eax; \ + jmp *%%eax" \ + /* outputs */ : \ + /* inputs */ : "m"(animPr->dataRetFromReq) \ + /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx","%edi","%esi"\ + ); + } + } + +/*Uses ID as index into array of flags. If flag already set, resumes from + * end-label. Else, sets flag and resumes normally. + * + *Note, this call cannot be inlined because the instr addr at the label + * inside is shared by all invocations of a given singleton ID. + */ +void +SSR__end_fn_singleton( int32 singletonID, VirtProcr *animPr ) + { + SSRSemReq reqData; + + //don't need this addr until after at least one singleton has reached + // this function + SSRSemEnv *semEnv = VMS__give_sem_env_for( animPr ); + semEnv->fnSingletons[ singletonID].endInstrAddr = &&EndSingletonInstrAddr; + + reqData.reqType = singleton_fn_end; + reqData.singletonID = singletonID; + + VMS__send_sem_request( &reqData, animPr ); + +EndSingletonInstrAddr: + return; + } + +void +SSR__end_data_singleton( SSRSingleton **singletonAddr, VirtProcr *animPr ) + { + SSRSemReq reqData; + + //don't need this addr until after singleton struct has reached + // this function for first time +// write_return_addr_into_singleton( (*(singletonAddr))->endInstrAddr ); + (*(singletonAddr))->endInstrAddr = &&EndDataSingletonInstrAddr; + + reqData.reqType = singleton_data_end; + reqData.singletonAddr = singletonAddr; + + VMS__send_sem_request( &reqData, animPr ); + printf("foo"); + return; +EndDataSingletonInstrAddr: + printf("bar"); + animPr->procrID += 2000; + return; } /*This executes the function in the masterVP, so it executes in isolation