Oberon || Library || Module Index || Search Engine || Definition || Module


Ulm's Oberon Library:
Semaphores


NAME

Semaphores - general interface for semaphores

SYNOPSIS

TYPE Semaphore = POINTER TO SemaphoreRec;
TYPE SemaphoreRec = RECORD (Disciplines.ObjectRec) END;
TYPE SemaOp = PROCEDURE (sema: Semaphore);
TYPE StatusProc = PROCEDURE (sema: Semaphore) : INTEGER;
TYPE GetConditionProc = PROCEDURE (sema: Semaphore;
                                   VAR condition: Conditions.Condition);
TYPE DropProc = PROCEDURE (condition: Conditions.Condition);
TYPE Interface = POINTER TO InterfaceRec;
TYPE InterfaceRec =
   RECORD
      p: SemaOp; (* optional: may be NIL *)
      v: SemaOp;
      getcondition: GetConditionProc;
      drop: DropProc;
      status: StatusProc;
   END;


PROCEDURE Init(sema: Semaphore; if: Interface); PROCEDURE P(sema: Semaphore); PROCEDURE V(sema: Semaphore); PROCEDURE GetCondition(sema: Semaphore; VAR condition: Conditions.Condition); PROCEDURE Drop(condition: Conditions.Condition); PROCEDURE Status(sema: Semaphore) : INTEGER;

DESCRIPTION

Semaphores provides an interface for semaphores. Semaphores are used for synchronization where multiple processes want to share common accessible resources. If the number of resources equals one, semaphores may be used to assure mutual exclusion if several processes possibly access the same data structure.

Init initializes a newly created semaphore and associates it with the given interface if. The interface procedures are expected to meet the specifications following:

p: PROCEDURE(sema: Semaphore);
block the current task until one of the resources becomes free and allocate it. This interface procedure is optional (i.e. it may be set to NIL) because it may be replaced by getcondition and Tasks.WaitFor. It is provided, however, to allow to avoid Tasks.WaitFor if one of the resources is already free.

v: PROCEDURE(sema: Semaphore);
free one of the claimed resources.

status: PROCEDURE() : INTEGER;
return the number of free resources, or, if zero, the negated number of processes which wait for this resource to become available.

getcondition: PROCEDURE(sema: Semaphore; VAR condition: Conditions.Condition);
create a condition which allows to wait for one of the resources. The condition must not only indicate the availability of the resource but has to claim it.

drop: PROCEDURE(condition: Conditions.Condition);
remove the condition from the list of waiting conditions, or, release the resource if it has already has been claimed.

P and V realize Dijkstra's semaphore operations which claim and release a resource.

GetCondition returns a condition which evaluates to TRUE when the resource has been claimed. Note that the condition returned by GetCondition does not indicate the availability of the resource only but claims the resource itself, i.e. P must not be called additionally if Conditions.TestCondition returns TRUE. For this reason conditions may not be recycled, i.e. for each new try to claim a resource a new condition has to be created.

To undo GetCondition, Drop may be called. Drop either unqueues the condition from the list of conditions waiting for one of the resource becoming available, or releases the resource if it was already claimed by the condition.

Status reports the current status of sema. If positive, the returned value indicates the number of free resources. If less or equal to zero, the absolute value of the returned number gives the number of processes which waits for the resource to become available.

DIAGNOSTICS

Semaphores does not produce itself any diagnostics. Implementations are expected to relate any error events to the semaphore. For external semaphores (i.e. those which are maintained outside) it is wise to setup an event queue for the semaphore and to check for pending events after P operations for lost resources.

Following runtime tests are performed by assertions:

CAVEAT

Critical regions which are threatened by asynchronous interrupts, (i.e. which are possible reentered during interrupt processing) must be also protected by use of the priority system to assure avoidance of dead locks. The general pattern for these cases looks as following:
Events.AssertPriority(Priorities.interrupts);
Semaphores.P(mutex);
   (* ... critical region ... *)
Semaphores.V(mutex);
Events.ExitPriority;

SEE ALSO

Events
priority system
LocalSemaphores
implementation of internal semaphores
RelatedEvents
setup of event queues

BUGS

Neither Semaphores nor its implementations are able to check whether P and V operations are properly nested.
Edited by: borchert, last change: 1997/07/11, revision: 1.4, converted to HTML: 1997/07/11

Oberon || Library || Module Index || Search Engine || Definition || Module