1 (* Semaphores.mod implement the ISO Semaphores specification.
3 Copyright (C) 2010-2024 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6 This file is part of GNU Modula-2.
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. *)
27 IMPLEMENTATION MODULE Semaphores
;
29 (* Provides mutual exclusion facilities for use by processes. *)
31 FROM Storage
IMPORT ALLOCATE
;
32 FROM Processes
IMPORT ProcessId
, Me
, SuspendMe
, Activate
, UrgencyOf
;
36 SEMAPHORE
= POINTER TO RECORD
42 ProcessList
= POINTER TO RECORD
50 freeProcessList
: ProcessList
;
54 Create - creates and returns s as the identity of a new
55 semaphore that has its associated count initialized
56 to initialCount, and has no processes yet waiting on it.
59 PROCEDURE Create (VAR s
: SEMAPHORE
; initialCount
: CARDINAL) ;
61 s
:= newSemaphore () ;
63 value
:= initialCount
;
71 Destroy - recovers the resources used to implement the semaphore s,
72 provided that no process is waiting for s to become free.
75 PROCEDURE Destroy (VAR s
: SEMAPHORE
) ;
83 (* raise exception? *)
93 PROCEDURE newSemaphore () : SEMAPHORE
;
102 freeSem
:= freeSem^.next
109 newProcessList - returns a new ProcessList.
112 PROCEDURE newProcessList () : ProcessList
;
116 IF freeProcessList
=NIL
120 l
:= freeProcessList
;
121 freeProcessList
:= freeProcessList^.right
128 add - adds process, p, to queue, head.
131 PROCEDURE add (VAR head
: ProcessList
; p
: ProcessList
) ;
140 p^.left
:= head^.left
;
141 head^.left^.right
:= p
;
148 sub - subtracts process, p, from queue, head.
151 PROCEDURE sub (VAR head
: ProcessList
; p
: ProcessList
) ;
153 IF (p^.left
=head
) AND (p
=head
)
161 p^.left^.right
:= p^.right
;
162 p^.right^.left
:= p^.left
168 addProcess - adds the current process to the semaphore list.
169 Remove the current process from the ready queue.
172 PROCEDURE addProcess (VAR head
: ProcessList
) ;
176 l
:= newProcessList() ;
191 PROCEDURE chooseProcess (head
: ProcessList
) : ProcessList
;
193 best
, l
: ProcessList
;
198 IF UrgencyOf (l^.waiting
) > UrgencyOf (best^.waiting
)
209 removeProcess - removes process, l, from the list and adds it to the
213 PROCEDURE removeProcess (VAR head
: ProcessList
; l
: ProcessList
) ;
217 right
:= freeProcessList
;
218 freeProcessList
:= l
;
225 Claim - if the count associated with the semaphore s is non-zero,
226 decrements this count and allows the calling process to
227 continue; otherwise suspends the calling process until
231 PROCEDURE Claim (s
: SEMAPHORE
) ;
245 Release - if there are any processes waiting on the semaphore s,
246 allows one of them to enter the ready state; otherwise
247 increments the count associated with s.
250 PROCEDURE Release (s
: SEMAPHORE
) ;
257 removeProcess (head
, chooseProcess (head
))
264 CondClaim - returns FALSE if the call Claim(s) would cause the calling
265 process to be suspended; in this case the count associated
266 with s is not changed. Otherwise returns TRUE and the
267 associated count is decremented.
270 PROCEDURE CondClaim (s
: SEMAPHORE
) : BOOLEAN ;
286 freeProcessList
:= NIL