Implementing a Counting Semaphore

A counting (or general) semaphore may be implemented using (fair) binary semaphores. This type of semaphore can take on integer values greater than one, representing multiple units of a resource.

For the implementation we use two binary semaphores and an ordinary shared integer variable (csem) which acts as the counting semaphore. One semaphore (mutex) provides normal mutual exclusion on the shared variable csem. The other (delay) acts as a delay semaphore. This type of semaphore is initialized to zero, and thus causes all processes executing a P operation to wait until a future V operation occurs. In effect, a delay semaphore provides a convenient implementation for a queuing mechanism. The queuing discipline is that of the underlying semaphore implementation, usually assumed to be FIFO.

CONTROL VARIABLES:

	mutex: semaphore, initial value 1 (FREE)
      delay: semaphore, initial value 0
	csem: integer, initialized to the number of units of the resource

P(CSEM):

/* claim exclusive access to csem */
P(mutex);

/* decrement csem, either to claim a resource unit or to record a new waiter */
csem = csem - 1;

/* if there were no units available, release csem and join the queue */
if (csem <= -1) {
V(mutex);
P(delay);
}

/* otherwise, release csem and proceed to use (one unit of) the resource */
else V(mutex);


V(CSEM):

/* claim exclusive access to csem */
P(mutex);

/* increment csem, to release a waiter (if any) or announce a free unit */
csem = csem + 1;

/* if there were waiters in the queue, release one */
if (csem <= 0) V(delay);

/* release csem */
V(mutex);