[9] | 1 | (*
|
---|
| 2 | (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
---|
| 3 | See the copyright notice in the ACK home directory, in the file "Copyright".
|
---|
| 4 | *)
|
---|
| 5 |
|
---|
| 6 | (*$R-*)
|
---|
| 7 | IMPLEMENTATION MODULE Semaphores [1];
|
---|
| 8 | (*
|
---|
| 9 | Module: Processes with semaphores
|
---|
| 10 | Author: Ceriel J.H. Jacobs
|
---|
| 11 | Version: $Header: /cvsup/minix/src/lib/ack/libm2/Semaphores.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
|
---|
| 12 |
|
---|
| 13 | Quasi-concurrency implementation
|
---|
| 14 | *)
|
---|
| 15 |
|
---|
| 16 | FROM SYSTEM IMPORT ADDRESS, NEWPROCESS, TRANSFER;
|
---|
| 17 | FROM Storage IMPORT Allocate;
|
---|
| 18 | FROM random IMPORT Uniform;
|
---|
| 19 | FROM Traps IMPORT Message;
|
---|
| 20 |
|
---|
| 21 | TYPE Sema = POINTER TO Semaphore;
|
---|
| 22 | Processes = POINTER TO Process;
|
---|
| 23 | Semaphore =
|
---|
| 24 | RECORD
|
---|
| 25 | level: CARDINAL;
|
---|
| 26 | END;
|
---|
| 27 | Process =
|
---|
| 28 | RECORD next: Processes;
|
---|
| 29 | proc: ADDRESS;
|
---|
| 30 | waiting: Sema;
|
---|
| 31 | END;
|
---|
| 32 |
|
---|
| 33 | VAR cp: Processes; (* current process *)
|
---|
| 34 |
|
---|
| 35 | PROCEDURE StartProcess(P: PROC; n: CARDINAL);
|
---|
| 36 | VAR s0: Processes;
|
---|
| 37 | wsp: ADDRESS;
|
---|
| 38 | BEGIN
|
---|
| 39 | s0 := cp;
|
---|
| 40 | Allocate(wsp, n);
|
---|
| 41 | Allocate(cp, SIZE(Process));
|
---|
| 42 | WITH cp^ DO
|
---|
| 43 | next := s0^.next;
|
---|
| 44 | s0^.next := cp;
|
---|
| 45 | waiting := NIL;
|
---|
| 46 | END;
|
---|
| 47 | NEWPROCESS(P, wsp, n, cp^.proc);
|
---|
| 48 | TRANSFER(s0^.proc, cp^.proc);
|
---|
| 49 | END StartProcess;
|
---|
| 50 |
|
---|
| 51 | PROCEDURE Up(VAR s: Sema);
|
---|
| 52 | BEGIN
|
---|
| 53 | s^.level := s^.level + 1;
|
---|
| 54 | ReSchedule;
|
---|
| 55 | END Up;
|
---|
| 56 |
|
---|
| 57 | PROCEDURE Down(VAR s: Sema);
|
---|
| 58 | BEGIN
|
---|
| 59 | IF s^.level = 0 THEN
|
---|
| 60 | cp^.waiting := s;
|
---|
| 61 | ELSE
|
---|
| 62 | s^.level := s^.level - 1;
|
---|
| 63 | END;
|
---|
| 64 | ReSchedule;
|
---|
| 65 | END Down;
|
---|
| 66 |
|
---|
| 67 | PROCEDURE NewSema(n: CARDINAL): Sema;
|
---|
| 68 | VAR s: Sema;
|
---|
| 69 | BEGIN
|
---|
| 70 | Allocate(s, SIZE(Semaphore));
|
---|
| 71 | s^.level := n;
|
---|
| 72 | RETURN s;
|
---|
| 73 | END NewSema;
|
---|
| 74 |
|
---|
| 75 | PROCEDURE Level(s: Sema): CARDINAL;
|
---|
| 76 | BEGIN
|
---|
| 77 | RETURN s^.level;
|
---|
| 78 | END Level;
|
---|
| 79 |
|
---|
| 80 | PROCEDURE ReSchedule;
|
---|
| 81 | VAR s0: Processes;
|
---|
| 82 | i, j: CARDINAL;
|
---|
| 83 | BEGIN
|
---|
| 84 | s0 := cp;
|
---|
| 85 | i := Uniform(1, 5);
|
---|
| 86 | j := i;
|
---|
| 87 | LOOP
|
---|
| 88 | cp := cp^.next;
|
---|
| 89 | IF Runnable(cp) THEN
|
---|
| 90 | DEC(i);
|
---|
| 91 | IF i = 0 THEN EXIT END;
|
---|
| 92 | END;
|
---|
| 93 | IF (cp = s0) AND (j = i) THEN
|
---|
| 94 | (* deadlock *)
|
---|
| 95 | Message("deadlock");
|
---|
| 96 | HALT
|
---|
| 97 | END;
|
---|
| 98 | END;
|
---|
| 99 | IF cp # s0 THEN TRANSFER(s0^.proc, cp^.proc); END;
|
---|
| 100 | END ReSchedule;
|
---|
| 101 |
|
---|
| 102 | PROCEDURE Runnable(p: Processes): BOOLEAN;
|
---|
| 103 | BEGIN
|
---|
| 104 | IF p^.waiting = NIL THEN RETURN TRUE; END;
|
---|
| 105 | IF p^.waiting^.level > 0 THEN
|
---|
| 106 | p^.waiting^.level := p^.waiting^.level - 1;
|
---|
| 107 | p^.waiting := NIL;
|
---|
| 108 | RETURN TRUE;
|
---|
| 109 | END;
|
---|
| 110 | RETURN FALSE;
|
---|
| 111 | END Runnable;
|
---|
| 112 | BEGIN
|
---|
| 113 | Allocate(cp, SIZE(Process));
|
---|
| 114 | WITH cp^ DO
|
---|
| 115 | next := cp;
|
---|
| 116 | waiting := NIL;
|
---|
| 117 | END
|
---|
| 118 | END Semaphores.
|
---|