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.
|
---|