# HG changeset patch # User Me@portablequad # Date 1323045807 28800 # Node ID 82bc4acc33b48bfbf4b7e9739dd36af3b2f375c2 # Parent cd2d0a81e3f79b595f5d14e15ecb9c4535ddb44e Added NtoN construct -- but details of struct updates, aso not done yet diff -r cd2d0a81e3f7 -r 82bc4acc33b4 SSR_Request_Handlers.c --- a/SSR_Request_Handlers.c Thu Jun 02 14:35:03 2011 +0200 +++ b/SSR_Request_Handlers.c Sun Dec 04 16:43:27 2011 -0800 @@ -64,7 +64,8 @@ //=========================================================================== -/*The semantic request has the receiving processor and the message type +/*SendType + *The semantic request has the receiving processor and the message type * *Note one value in this approach: without the extra VMS layer, * the send and receive would happen in real time instead of virtual time, @@ -146,6 +147,81 @@ } } +/*Send NtoN + * + *For NtoN, the sender only specifies the setID, there is no receiving + * procr stated. + * + *The semantic request has the SetID and ptr to message + * + *Each setID has its own entry in a circular buffer. Collect the sends in + * a linked list inside the entry. + *Waiting receives also collect inside the entry -- if one there, pair + * it with this send. + *Sends can either be send-and-go or wait-for-receive. But receives must + * wait for a send to pair with. + * + *Q: how know when done with particular setID? + *A: requires info from app -- either register the ID w/num in set, or do a + * start-end to bound it. + * try first with register the number in set -- means have to decr + * number of sends remaining, and if has a waiting receive, incr number of + * receives. + * + *When register a setID, state num in set, and state whether sends to that + * set wait to be paired with receive, or just resume right away + */ +void +handleSendNtoN( SSRSemReq *semReq, SSRSemEnv *semEnv ) + { SSRSemReq *sendingReq, receiveReq; + int32 setID; + NtoNEntry *entry; + MovingWindow *movingWindow = semEnv->movingWindow; + + setID = semReq->setID; + + entry = (NtoNEntry *)giveWindowEntry( setID, movingWindow ); + if( entry == NULL ) ERROR(); //prints this file & line + + //safety check: make sure number of sends not greater than expected + entry->numSent += 1; + if( entry->numSend > entry->numInSet ) ERROR(); //prints this file & line + + //check for waiting receivers + receiveReq = entry->waitingReceives; + if( receiveReq != NULL ) + { entry->waitingReceives = entry->waitingReceives->nextWaitingReq; + entry->numReceived += 1; + if( entry->numReceived == entry->numInSet ) + retireSet( setID, movingWindow ); //mark unused so can adv window + + //bring both processors back from suspend + resume_procr( sendingReq->sendPr, semEnv ); + resume_procr( receiveReq->receivePr, semEnv ); + + //done + return; + } + + //Were no waiting receivers, so add this send to list + // but how deps on whether sender waits or goes + if( entry->senderDoesWait ) + { sendingReq->nextWaitingReq = entry->waitingSends; + entry->waitingSends = sendingReq; + return; //sender waits, so it stays suspended, so nothing left to do + } + else + { //sender doesn't wait, so semReq, which is on stack, will disappear + // so clone it before adding it to list, then resume sender + SSRSemReq *clonedReq = cloneReq( semReq ); + clonedReq->nextWaitingReq = entry->waitingSends; + entry->waitingSends = clonedReq; + resume_procr( sendingReq->sendPr, semEnv ); + return; + } +// DEBUG2( dbgRqstHdlr, ": %d, %d | ", , ) + } + /*Looks like can make single handler for both sends.. */ @@ -235,6 +311,75 @@ } +/*Receive NtoN + * + *For NtoN, the receiver only specifies the setID + * + *The semantic request has the SetID and returns with ptr to message + * + *Each setID has its own entry in a circular buffer. Collect the receives in + * a linked list inside the entry. + *Waiting sends also collect inside the entry -- if one there, pair + * it with this receive. + *Receives must wait for a send to pair with. + * + *Q: how know when done with particular setID? + *A: requires info from app -- either register the ID w/num in set, or do a + * start-end to bound it. + * try first with register the number in set -- means have to decr + * number of sends remaining, and if has a waiting receive, incr number of + * receives. + * + *When register a setID, state num in set, and state whether sends to that + * set wait to be paired with receive, or just resume right away + * + *So, in this receive, if has a waiting send, check if it's the last + * receive of set. + *Also, either way, if the sending VPs don't wait to be paired, then any + * send-request that's waiting was cloned, so has to be freed. + */ +void +handleReceiveNtoN( SSRSemReq *semReq, SSRSemEnv *semEnv ) + { SSRSemReq *sendReq, receiveReq = semReq; + int32 setID; + NtoNEntry *entry; + MovingWindow *movingWindow = semEnv->movingWindow; + + setID = semReq->setID; + + entry = (NtoNEntry *)giveWindowEntry( setID, movingWindow ); + if( entry == NULL ) ERROR(); //prints this file & line + + //check for waiting sends + sendReq = entry->waitingSends; + if( sendReq != NULL ) + { //remove the waiting send from list + entry->waitingSends = sendReq->nextWaitingReq; + //means this receive matched, so check if last in set + entry->numReceived += 1; + if( entry->numReceived == entry->numInSet ) + retireSet( setID, movingWindow ); //mark unused so can adv window + + //check whether sending VP is waiting or not + if( entry->senderDoesWait ) + { //bring both processors back from suspend + resume_procr( sendReq->sendPr, semEnv ); + resume_procr( receiveReq->receivePr, semEnv ); + } + else + { VMSPlugin__free( sendReq ); + resume_procr( receiveReq->receivePr, semEnv ); + } + //done + return; + } + + //Was no waiting send, so add this to waiting receive list + receiveReq->nextWaitingReq = entry->waitingReceives; + entry->waitingReceives = receiveReq; + return; +// DEBUG2( dbgRqstHdlr, ": %d, %d | ", , ) + } void handleReceiveType( SSRSemReq *semReq, SSRSemEnv *semEnv) diff -r cd2d0a81e3f7 -r 82bc4acc33b4 SSR_lib.c --- a/SSR_lib.c Thu Jun 02 14:35:03 2011 +0200 +++ b/SSR_lib.c Sun Dec 04 16:43:27 2011 -0800 @@ -269,7 +269,7 @@ /* */ - VirtProcr * +VirtProcr * SSR__create_procr_with( VirtProcrFnPtr fnPtr, void *initData, VirtProcr *creatingPr ) { SSRSemReq reqData; @@ -288,7 +288,7 @@ return creatingPr->dataRetFromReq; } - VirtProcr * +VirtProcr * SSR__create_procr_with_affinity( VirtProcrFnPtr fnPtr, void *initData, VirtProcr *creatingPr, int32 coreToScheduleOnto ) { SSRSemReq reqData; @@ -394,6 +394,69 @@ //=========================================================================== +/*NtoN register a new set + * + *Have to know when safe to retire a given setID, and also easier if make the + * wait-vs-go behavior of sender be defined by the set. So, before doing + * and sends, perform this call to 'register' the set's ID. + * + *Give the call the setID, the number in the set, and TRUE if senders wait + * for a receive, else FALSE + */ +void +SSR__register_NtoN_set( int32 setID, int32 numInSet, bool32 doesWait, + VirtProcr *animPr ) + { SSRSemReq reqData; + + reqData.sendPr = animPr; //reuse field + reqData.reqType = register_NtoN; + reqData.setID = setID; + reqData.numInSet = numInSet; + reqData.doesWait = doesWait; + + VMS__send_sem_request( &reqData, animPr ); + } + +/*NtoN send + *This construct doesn't specify a receiving processor, nor does it have the + * concept of a virtual physical communication channel. Instead, the concept + * is of a set of things being sent, which are all received. The set is + * unique within the computation. The same line of code can be reused for + * multiple sets, by making the setID be a variable. + * + *The benefit is in portability. This construct specifies true + * non-determinism in a logically safe way, and with a pattern that exists + * directly in the problem being solved. + *For example, accumulation of results in + * matrix multiply has N result sends for a particular input pair, which all + * are accumulated into a particular result matrix. Each input pair + * is a different set. + *The results gathering can be split amongst a variable + * number of processors, each owning a portion of the results matrix) + * + * At some point, the setID can be made hierarchical. Also, the + * creation of processors can be put under scheduler control with query- + * answer pattern for number to create. + * + *The sending VP either waits to be matched to a receiver, or else just + * resumes right away. The behavior is fixed when the setID is registered. + */ +void +SSR__send_one_of_NtoN_set( VirtProcr *sendPr, void *msg, int setID ) + { SSRSemReq reqData; + + reqData.sendPr = sendPr; + reqData.reqType = send_NtoN; + reqData.setID = setID; + reqData.msg = msg; + reqData.nextWaitingReq = NULL; + + VMS__send_sem_request( &reqData, sendPr ); + + //When come back from suspend, no longer own data reachable from msg + } + + void SSR__send_of_type_to( VirtProcr *sendPr, void *msg, const int type, VirtProcr *receivePr)