119 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Modula-2
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Modula-2
		
	
	
		
			Executable File
		
	
	
	
	
| (*
 | |
|   (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | |
|   See the copyright notice in the ACK home directory, in the file "Copyright".
 | |
| *)
 | |
| 
 | |
| (*$R-*)
 | |
| IMPLEMENTATION MODULE Semaphores [1];
 | |
| (*
 | |
|   Module:       Processes with semaphores
 | |
|   Author:       Ceriel J.H. Jacobs
 | |
|   Version:      $Header$
 | |
| 
 | |
|   Quasi-concurrency implementation
 | |
| *)
 | |
| 
 | |
|   FROM	SYSTEM IMPORT	ADDRESS, NEWPROCESS, TRANSFER;
 | |
|   FROM	Storage IMPORT	Allocate;
 | |
|   FROM	random IMPORT	Uniform;
 | |
|   FROM	Traps IMPORT	Message;
 | |
| 
 | |
|   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));
 | |
| 	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));
 | |
| 	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;
 | |
| 		IF (cp = s0) AND (j = i) THEN
 | |
| 			(* deadlock *)
 | |
| 			Message("deadlock");
 | |
| 			HALT
 | |
| 		END;
 | |
| 	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));
 | |
| 	WITH cp^ DO
 | |
| 		next := cp;
 | |
| 		waiting := NIL;
 | |
| 	END
 | |
| END Semaphores.
 | 
