ack/lang/m2/libm2/Semaphores.mod

119 lines
2.2 KiB
Modula-2
Raw Permalink Normal View History

1988-02-19 15:54:01 +00:00
(*
(c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
See the copyright notice in the ACK home directory, in the file "Copyright".
*)
1987-08-19 18:07:01 +00:00
(*$R-*)
1987-05-13 14:36:45 +00:00
IMPLEMENTATION MODULE Semaphores [1];
1988-02-19 15:54:01 +00:00
(*
Module: Processes with semaphores
Author: Ceriel J.H. Jacobs
1994-06-24 14:02:31 +00:00
Version: $Id$
1988-02-19 15:54:01 +00:00
Quasi-concurrency implementation
*)
1987-05-13 14:36:45 +00:00
FROM SYSTEM IMPORT ADDRESS, NEWPROCESS, TRANSFER;
FROM Storage IMPORT Allocate;
FROM random IMPORT Uniform;
FROM Traps IMPORT Message;
1987-05-13 14:36:45 +00:00
TYPE Sema = POINTER TO Semaphore;
Processes = POINTER TO Process;
Semaphore =
RECORD
level: CARDINAL;
END;
Process =
RECORD next: Processes;
proc: ADDRESS;
waiting: Sema;
END;
VAR cp: Processes; (* current process *)
PROCEDURE StartProcess(P: PROC; n: CARDINAL);
VAR s0: Processes;
wsp: ADDRESS;
BEGIN
s0 := cp;
Allocate(wsp, n);
Allocate(cp, SIZE(Process));
1987-05-13 14:36:45 +00:00
WITH cp^ DO
next := s0^.next;
s0^.next := cp;
waiting := NIL;
END;
NEWPROCESS(P, wsp, n, cp^.proc);
TRANSFER(s0^.proc, cp^.proc);
END StartProcess;
PROCEDURE Up(VAR s: Sema);
BEGIN
s^.level := s^.level + 1;
ReSchedule;
END Up;
PROCEDURE Down(VAR s: Sema);
BEGIN
IF s^.level = 0 THEN
cp^.waiting := s;
ELSE
s^.level := s^.level - 1;
END;
ReSchedule;
END Down;
PROCEDURE NewSema(n: CARDINAL): Sema;
VAR s: Sema;
BEGIN
Allocate(s, SIZE(Semaphore));
1987-05-13 14:36:45 +00:00
s^.level := n;
RETURN s;
END NewSema;
PROCEDURE Level(s: Sema): CARDINAL;
BEGIN
RETURN s^.level;
END Level;
PROCEDURE ReSchedule;
VAR s0: Processes;
i, j: CARDINAL;
BEGIN
s0 := cp;
i := Uniform(1, 5);
j := i;
LOOP
cp := cp^.next;
IF Runnable(cp) THEN
DEC(i);
IF i = 0 THEN EXIT END;
END;
1987-06-26 15:59:52 +00:00
IF (cp = s0) AND (j = i) THEN
(* deadlock *)
Message("deadlock");
HALT
END;
1987-05-13 14:36:45 +00:00
END;
IF cp # s0 THEN TRANSFER(s0^.proc, cp^.proc); END;
END ReSchedule;
PROCEDURE Runnable(p: Processes): BOOLEAN;
BEGIN
IF p^.waiting = NIL THEN RETURN TRUE; END;
IF p^.waiting^.level > 0 THEN
p^.waiting^.level := p^.waiting^.level - 1;
p^.waiting := NIL;
RETURN TRUE;
END;
RETURN FALSE;
END Runnable;
BEGIN
Allocate(cp, SIZE(Process));
1987-05-13 14:36:45 +00:00
WITH cp^ DO
next := cp;
waiting := NIL;
END
END Semaphores.