11.1: POSIX Semaphores
- Page ID
- 40641
A semaphore is a data structure used to help threads work together without interfering with each other.
The POSIX standard specifies an interface for semaphores; it is not part of Pthreads, but most UNIXes that implement Pthreads also provide semaphores.
POSIX semaphores have type sem_t
. As usual, I put a wrapper around sem_t
to make it easier to use. The interface is defined in sem.h
:
typedef sem_t Semaphore; Semaphore *make_semaphore(int value); void semaphore_wait(Semaphore *sem); void semaphore_signal(Semaphore *sem);
Semaphore
is a synonym for sem_t
, but I find it more readable, and the capital letter reminds me to treat it like an object and pass it by pointer.
The implementation of these functions is in sem.c
:
Semaphore *make_semaphore(int value) { Semaphore *sem = check_malloc(sizeof(Semaphore)); int n = sem_init(sem, 0, value); if (n != 0) perror_exit("sem_init failed"); return sem; }
make_semaphore
takes the initial value of the semaphore as a parameter. It allocates space for a Semaphore, initializes it, and returns a pointer to Semaphore
.
sem_init
returns 0 if it succeeds and -1 if anything goes wrong. One nice thing about using wrapper functions is that you can encapsulate the error-checking code, which makes the code that uses these functions more readable.
Here is the implementation of semaphore_wait
:
void semaphore_wait(Semaphore *sem) { int n = sem_wait(sem); if (n != 0) perror_exit("sem_wait failed"); }
And here is semaphore_signal
:
void semaphore_signal(Semaphore *sem) { int n = sem_post(sem); if (n != 0) perror_exit("sem_post failed"); }
I prefer to call this operation “signal” rather than “post”, although both terms are common.
Here’s an example that shows how to use a semaphore as a mutex:
Semaphore *mutex = make_semaphore(1); semaphore_wait(mutex); // protected code goes here semaphore_signal(mutex);
When you use a semaphore as a mutex, you usually initialize it to 1 to indicate that the mutex is unlocked; that is, one thread can pass the semaphore without blocking.
Here I am using the variable name mutex
to indicate that the semaphore is being used as a mutex. But remember that the behavior of a semaphore is not the same as a Pthread mutex.