/* these routines are called by TupleDSM application programs list of tuple types: ("var",name of variable,array index,value of variable,# of readers) ("mutex",mutexID) ("bar",barrierID,even or odd value,# remaining) */ /* concerned with command-line arguments: */ #define DSM_MAX_ARGS 20 #define DSM_MAX_ARG_LENGTH 20 int DSMArgc; /* command-line argument count */ char DSMArgv[DSM_MAX_ARGS][DSM_MAX_ARG_LENGTH]; /* command-line arguments */ /* concerned with node numbers and total number of nodes: */ int DSMNodeNum, /* i.d. number of this node */ DSMTotNodes; /* total number of nodes */ /* concerned with cleanup at exit: */ /* used only by node 0: */ int DSMNVars = 0, /* number of "var" tuples */ DSMNMutexs = 0, /* number of "mutex" tuples */ DSMNBars = 0; /* number of "bar" tuples */ /* note: tuples created by the front end program will be removed by that program */ /* ********************* DSMEnvInit() ********************* external view: must be called by all nodes at the outset of an application program; gets node number, number of workers, number of command-line arguments, and those arguments themselves internal operation: does rd() (except for the use of in() in the case of DSMNodeNum) on tuples set by the front-end program */ DSMEnvInit() { int I,TmpI; char *TmpS; in(lstring("whoami"),qlint(&DSMNodeNum)); rd(lstring("number of workers"),qlint(&DSMTotNodes)); rd(lstring("number of arguments"),qlint(&DSMArgc)); for (I = 1; I <= DSMArgc; I++) { rd(lstring("argument"),lint(I),qlnchar(&TmpS,&TmpI)); strcpy(DSMArgv[I],TmpS); } if (DSMNodeNum == 0) DSMBarrierCreate("DSM exit barrier"); } /* ********************* DSMVarInit(S,N) ********************* external view: must be called, by node 0, for each shared variable (scalar or array); called AFTER DSMEnvInit() S is a string containing the name of the shared variable set N = 1 for a scalar; for arrays, N = array length internal operation: uses out() to create tuples ("var",S,I,0,0), I = 0,1,2,...,N-1 (see tuple type list at top of this file) */ DSMVarInit(S,N) char *S; int N; { int I; if (DSMNodeNum != 0) { printf("vars may be created only by node 0\n"); exit(1); } for (I = 0; I < N; I++) { out(lstring("var"),lstring(S),lint(I),lint(0),lint(0)); DSMNVars++; } } /* ********************* DSMNonExclWriteRequest() ********************* external view: request permisson for nonexclusive write access to a shared variable; no new reads or other writes allowed, but old ones could be in progress (they will continue to use the old value of the variable) access is to the I-th element of the array named in S (or in the case of a scalar (I = 0), the scalar named in S); P is a pointer giving the address in the application program of the array/scalar named in S; returns the current number of readers internal operation: search through tuple space for a match on "var", S, I; assign the value to *(P+I) */ int DSMNonExclWriteRequest(S,P,I) char *S; int *P,I; { int NR; in(lstring("var"),lstring(S),lint(I),qlint(P+I),qlint(&NR)); return NR; } /* ********************* DSMNonExclWriteRelease() ********************* external view: release exclusive write access; last argument is the number of readers internal operation: write out the tuple, including its new value for the variable */ DSMNonExclWriteRelease(S,P,I,NR) char *S; int *P,I,NR; { out(lstring("var"),lstring(S),lint(I),lint(*(P+I)),lint(NR)); } /* ********************* DSMReadRequest() ********************* external view: request permission for read access to a variable note: there is no corresponding release call internal operation: does rd() to read the tuple */ DSMReadRequest(S,P,I) char *S; int *P,I; { int NReaders; rd(lstring("var"),lstring(S),lint(I),qlint(P+I),qlint(&NReaders)); } /* ********************* DSMExclWriteRequest() ********************* external view: request permisson for exclusive write access to a variable; no reads or other writes allowed access is to the I-th element of the array named in S (or in the case of a scalar (I = 0), the scalar named in S); P is a pointer giving the address in the application program of the array/scalar named in S internal operation: search through tuple space for a match on "var", S, I and a 0-readers condition; assign the value to *(P+I) */ DSMExclWriteRequest(S,P,I) char *S; int *P,I; { in(lstring("var"),lstring(S),lint(I),qlint(P+I),lint(0)); } /* ********************* DSMExclWriteRelease() ********************* external view: release exclusive write access internal operation: write out the tuple, including its new value for the variable */ DSMExclWriteRelease(S,P,I) char *S; int *P,I; { out(lstring("var"),lstring(S),lint(I),lint(*(P+I)),lint(0)); } /* ********************* DSMSharedReadRequest() ********************* external view: request permission for shared read access to a variable; return value is (new) number of readers internal operation: does in() to remove the tuple, increment the number of readers, and then out() to replace it */ int DSMSharedReadRequest(S,P,I) char *S; int *P,I; { int NReaders; in(lstring("var"),lstring(S),lint(I),qlint(P+I),qlint(&NReaders)); NReaders++; out(lstring("var"),lstring(S),lint(I),lint(*(P+I)),lint(NReaders)); return NReaders; } /* ********************* DSMSharedReadRelease() ********************* external view: release shared read access internal operation: do in() to get current number of readers, decrement, out() */ DSMSharedReadRelease(S,P,I) char *S; int *P,I; { int NReaders; in(lstring("var"),lstring(S),lint(I),qlint(P+I),qlint(&NReaders)); NReaders--; out(lstring("var"),lstring(S),lint(I),lint(*(P+I)),lint(NReaders)); } /* ********************* DSMMutexCreate() *********************** external view: sets up a mutex internal operation: does out() to create a mutex tuple, unlocked */ DSMMutexCreate(MutexID) char MutexID[]; { if (DSMNodeNum != 0) { printf("mutexes may be created only by node 0\n"); exit(1); } out(lstring("mutex"),lstring(MutexID)); DSMNMutexs++; } /* ********************* DSMMutexBegin() *********************** external view: waits for and acquires exclusive access to a critical section internal operation: does in() to remove the associated lock tuple, requiring a 0 in the lock component of the tuple */ DSMMutexBegin(MutexID) char MutexID[]; { in(lstring("mutex"),lstring(MutexID)); } /* ********************* DSMMutexEnd() *********************** external view: waits for and acquires exclusive access to a critical section internal operation: does in() to remove the associated lock tuple, requiring a 0 in the lock component of the tuple */ DSMMutexEnd(MutexID) char MutexID[]; { out(lstring("mutex"),lstring(MutexID)); } /* ********************* DSMBarrierCreate() *********************** external view: sets up a barrier internal operation: does out() to create a barrier tuple, initialized to NPartic; the last component is the number of nodes which have NOT reached the barrier yet */ DSMBarrierCreate(BarrierID) char BarrierID[]; { if (DSMNodeNum != 0) { printf("barriers may be created only by node 0\n"); exit(1); } out(lstring("bar"),lstring(BarrierID),lint(0),lint(0)); out(lstring("bar"),lstring(BarrierID),lint(1),lint(0)); DSMNBars++; } /* ********************* DSMBarrier() *********************** external view: waits until all required nodes have reached this point in the code internal operation: does in() to get the specified barrier tuple, increments the barrier count, and does out() back to the tuple space; checks to see whether done */ DSMBarrier(BarrierID) char BarrierID[]; { int NHit; static int EvenOdd = 0; in(lstring("bar"),lstring(BarrierID),lint(EvenOdd),qlint(&NHit)); NHit++; if (NHit == DSMTotNodes+1) NHit = 1; out(lstring("bar"),lstring(BarrierID),lint(EvenOdd),lint(NHit)); if (NHit < DSMTotNodes) rd(lstring("bar"),lstring(BarrierID),lint(EvenOdd),lint(DSMTotNodes)); EvenOdd = 1 - EvenOdd; } /* ********************* DSMExit() ********************* external view: required call for all nodes, the last-executed line in the application source code internal operation: does out() of the string "front end may exit"; when the front-end program receives this from all nodes, it will exit; */ DSMExit() { int I,A[10]; if (DSMNodeNum != 0) out(lstring("front end may exit")); DSMBarrier("DSM exit barrier"); if (DSMNodeNum == 0) { for (I = 0; I < DSMNVars; I++) in(lstring("var"), qlstring(&A[0]),qlint(&A[1]),qlint(&A[2]),qlint(&A[3])); for (I = 0; I < DSMNMutexs; I++) in(lstring("mutex"),qlstring(&A[0])); for (I = 0; I < DSMNBars; I++) { in(lstring("bar"),qlstring(&A[0]),lint(0),qlint(&A[1])); in(lstring("bar"),qlstring(&A[0]),lint(1),qlint(&A[1])); } out(lstring("front end may exit")); } }