(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* Last Modified On Mon Jun 29 22:11:02 PDT 1992 by muller *) (* Modified On Fri Sep 29 09:38:18 1989 by kalsow *) (* Modified on Thu Mar 30 18:30:10 1989 by hisgen *) (* Modified on Thu Dec 22 16:01:24 1988 by swart *) (* Modified On Tue Jan 19 11:18:19 PST 1988 by denning *) (* Modified On Mon Oct 13 17:01:19 1986 by levin *) (* Modified On Wed Dec 5 13:10:00 1984 by Andrew Birrell *) UNSAFE MODULE UID; IMPORT Thread, Time, Unix, Random; PROCEDURE Get (VAR(*OUT*) t: T) RAISES {} = BEGIN GetConstant (t.machine); GetFineCounter (t.counter); END Get; PROCEDURE GetID (VAR(*OUT*) id: ID) RAISES {} = BEGIN GetConstant (id.machine); id.counter := GetCounter (); END GetID; VAR counterLock: Thread.Mutex; VAR counter: Counter; PROCEDURE GetCounter (): Counter = BEGIN LOCK counterLock DO Time.PauseUntil (Time.T {counter, 0}); INC (counter); RETURN counter - 1 END; END GetCounter; VAR fineCounterLock: Thread.Mutex; VAR fineCounter: FineCounter; PROCEDURE GetFineCounter (VAR c: FineCounter) = BEGIN LOCK fineCounterLock DO LOOP c.coarse := Time.Now().seconds; IF fineCounter.coarse # c.coarse THEN c.fine := 0; fineCounter := c; EXIT ELSIF fineCounter.fine # 65535 THEN INC (fineCounter.fine); c.fine := fineCounter.fine; EXIT ELSE Thread.Release (fineCounterLock); TRY Time.PauseUntil (Time.T { fineCounter.coarse + 1, 0}); FINALLY Thread.Acquire (fineCounterLock); END; END; END; END(*LOCK*); END GetFineCounter; VAR hostname: Constant; PROCEDURE GetConstant (VAR c: Constant) = (* Returns the first six characters of the hostname. MAY NOT BE UNIQUE!!!! *) BEGIN c := hostname; END GetConstant; VAR capLock: Thread.Mutex; VAR seed: Random.T; PROCEDURE GetCapability (VAR (* OUT *) cap: Capability) RAISES {} = BEGIN Get (cap.id); LOCK capLock DO IF seed = NIL THEN seed := Random.New ( -1); END; cap.random1 := Random.Integer (seed); cap.random2 := Random.Integer (seed); END; END GetCapability; PROCEDURE EqualT (READONLY t1, t2: T): BOOLEAN RAISES {} = BEGIN RETURN (t1.counter = t2.counter) AND EqualConstant (t1.machine, t2.machine); END EqualT; PROCEDURE EqualID (READONLY id1, id2: ID): BOOLEAN RAISES {} = BEGIN RETURN (id1.counter = id2.counter) AND EqualConstant (id1.machine, id2.machine); END EqualID; PROCEDURE EqualConstant (READONLY c1, c2: Constant): BOOLEAN RAISES {} = (*It's better to compare bytes 4 and 5 first, since with DECnet bytes 0..4 are the same for all machines.*) BEGIN RETURN (c1[4] = c2[4]) AND (c1[5] = c2[5]) AND (c1[0] = c2[0]) AND (c1[1] = c2[1]) AND (c1[2] = c2[2]) AND (c1[3] = c2[3]); END EqualConstant; PROCEDURE EqualFineCounter (READONLY c1, c2: FineCounter): BOOLEAN RAISES {} = BEGIN RETURN (c1.fine = c2.fine) AND (c1.coarse = c2.coarse); END EqualFineCounter; PROCEDURE EqualCapability (READONLY c1, c2: Capability): BOOLEAN RAISES {} = BEGIN RETURN (c1.random1 = c2.random1) AND (c1.random2 = c2.random2) AND EqualT (c1.id, c2.id); END EqualCapability; PROCEDURE CompareCounter (a, b: Counter): INTEGER RAISES {} = BEGIN RETURN (a - b); END CompareCounter; PROCEDURE CompareFineCounter (a, b: FineCounter): INTEGER RAISES {} = VAR i: INTEGER; BEGIN i := (a.coarse - b.coarse); IF (i # 0) THEN RETURN i END; RETURN (a.fine - b.fine); END CompareFineCounter; PROCEDURE CompareConstant (a, b: Constant): INTEGER RAISES {} = VAR i, j: INTEGER; BEGIN FOR z := 0 TO LAST (a) DO j := z; i := a[j] - b[j]; IF (i # 0) THEN RETURN i END; END; RETURN i; END CompareConstant; PROCEDURE CompareT (a, b: T): INTEGER RAISES {} = VAR i: INTEGER; BEGIN i := CompareFineCounter (a.counter, b.counter); IF (i # 0) THEN RETURN i END; RETURN CompareConstant (a.machine, b.machine); END CompareT; PROCEDURE CompareID (a, b: ID): INTEGER RAISES {} = VAR i: INTEGER; BEGIN i := a.counter - b.counter; IF (i # 0) THEN RETURN i END; RETURN CompareConstant (a.machine, b.machine); END CompareID; PROCEDURE CompareCapability (a, b: Capability): INTEGER RAISES {} = VAR i: INTEGER; BEGIN i := CompareFineCounter (a.id.counter, b.id.counter); IF (i # 0) THEN RETURN i; END; i := CompareConstant (a.id.machine, b.id.machine); IF (i # 0) THEN RETURN i; END; i := a.random1 - b.random1; IF (i # 0) THEN RETURN i; END; RETURN (a.random2 - b.random2); END CompareCapability; PROCEDURE CompareInteger (a, b: INTEGER): INTEGER RAISES {} = BEGIN RETURN (a - b); END CompareInteger; BEGIN counterLock := NEW (Thread.Mutex); fineCounterLock := NEW (Thread.Mutex); capLock := NEW (Thread.Mutex); seed := NIL; counter := Time.Now().seconds; fineCounter.coarse := counter; fineCounter.fine := 0; FOR i := 0 TO 5 DO hostname[i] := 0 END; EVAL (Unix.gethostname (ADR (hostname), 6)); END UID. (* History: Tue Dec 27 20:27:45 1988 hisgen: Changed order of various comparisons so that the bits that are most-likely to be different will be checked first. Thu Mar 30 17:55:45 1989 hisgen: Added comparison procedures defined in UIDExtras1.def *)