ui/src/winvbt/WinLL.m3


Copyright (C) 1994, Digital Equipment Corp.
Digital Internal Use Only
                                                                           
       Created on Thu Feb  2 13:46:25 PST 1995 by najork                   

MODULE WinLL;

IMPORT Thread;

TYPE
  List = REF RECORD
    mu  : MUTEX;
    th  : Thread.T;
    ctr : CARDINAL;
    next: List;
  END;

VAR
  list : List := NIL;
  monitor := NEW (MUTEX);

PROCEDURE Assert (mu: MUTEX) =
  VAR
    tmp := list;
    th  := Thread.Self();
  BEGIN
    LOCK monitor DO
      WHILE tmp # NIL DO
        IF tmp.mu = mu THEN
          <* ASSERT (tmp.th = NIL AND tmp.ctr = 0) OR
                    (tmp.th = th AND tmp.ctr > 0) *>
          tmp.th := th;
          INC (tmp.ctr);
          RETURN;
        END;
        tmp := tmp.next;
      END;
      list := NEW (List, mu := mu, th := th, ctr := 1, next := list);
    END;
  END Assert;

PROCEDURE Retract (mu: MUTEX) =
  VAR
    tmp := list;
  BEGIN
    LOCK monitor DO
      WHILE tmp # NIL DO
        IF tmp.mu = mu THEN
          <* ASSERT tmp.th = Thread.Self() AND tmp.ctr > 0 *>
          DEC (tmp.ctr);
          IF tmp.ctr = 0 THEN
            tmp.th := NIL;
          END;
          RETURN;
        END;
        tmp := tmp.next;
      END;
      <* ASSERT FALSE *>
    END;
  END Retract;

PROCEDURE Holds (mu: MUTEX): BOOLEAN =
  VAR
    tmp := list;
  BEGIN
    WHILE tmp # NIL DO
      IF list.mu = mu THEN
        RETURN tmp.th = Thread.Self();
      END;
      list := list.next;
    END;
    RETURN FALSE;
  END Holds;

PROCEDURE Acquire (m: MUTEX) =
  BEGIN
    LOCK monitor DO
      IF NOT Holds (m) THEN
        Thread.Acquire (m);
      END;
    END;
  END Acquire;

PROCEDURE Release (m: MUTEX) =
  BEGIN
    LOCK monitor DO
      IF NOT Holds (m) THEN
        Thread.Release (m);
      END;
    END;
  END Release;

BEGIN
END WinLL.