The POSIX thread library contains functions for working with semaphores and mutexes. There is much more to say than what is mentioned here. A good place to find more information is linux.die.net.
The functions should all be compiled and linked with -pthread.
What is a semaphore in LINUX?
A semaphore is fundamentally an integer whose value is never allowed to fall below 0. There are two operations on a semaphore: wait and post. The post operation increment the semaphore by 1, and the wait operations does the following: If the semaphore has a value > 0, the semaphore is decremented by 1. If the semaphore has value 0, the caller will be blocked (busy-waiting or more likely on a queue) until the semaphore has a value larger than 0, and then it is decremented by 1.
We declare a semaphore as:
sem_t sem;
where sem_t is a typedef defined in a header file as (apparently) a kind of unsigned char.
An example of this might be that we have a set of N interchangeable resources. We start with semaphore S = N. We use a resource, so there are now N-1 available (wait), and we return it when we are done (post). If the semaphore has value 0, there are no resources available, and we have to wait (until someone does a post).
Semaphores are thus used to coordinate concurrent processes.
This is what some people call a "counted semaphore". There is a similar notion called a "binary semaphore" which is limited to the values 0 and 1.
A semaphore may be named or unnamed. These notes assume we are using named semaphores.
sem_init()
Prototype: int sem_init(sem_t * sem, int pshared, unsigned int value);
Library: #include <semaphore.h>
Purpose: This initializes the semaphore *sem. The initial value of the semaphore will be value. If pshared is 0, the semaphore is shared among all threads of a process (and hence need to be visible to all of them such as a global variable). If pshared is not zero, the semaphore is shared but should be in shared memory.
Notes:
sem_wait()
Prototype: int sem_wait(sem_t * sem);
Library: #include <semaphore.h>
Purpose: This implements the wait function described above on the semaphore *sem.
Notes:
sem_post()
Prototype: int sem_post(sem_t * sem);
Library: #include <semaphore.h>
Purpose: This implements the post function described above on the semaphore *sem.
Note: On success, the return value is 0, and on failure, the return value is -1 (and the value of the semaphore is unchanged).
sem_destroy()
Prototype: int sem_destroy(sem_t * sem);
Library: #include <semaphore.h>
Purpose: This destroys the semaphore *sem, so *sem becomes uninitialized.
Notes:
What is a mutex in LINUX?
A mutex (named for "mutual exclusion") is a binary semaphore with an ownership restriction: it can be unlocked (the post operation) only by whoever locked it (the wait operation). Thus a mutex offers a somewhat stronger protection than an ordinary semaphore.
We declare a mutex as:
pthread_mutex_t mutex;
pthread_mutex_init()
Prototype:
int pthread_mutex_init(pthread_mutex_t * restrict mutex, const pthread_mutexattr_t * restrict attr);
Library: #include <pthread.h>
Purpose: This initializes *mutex with the attributes specified by attr. If attr is NULL, a default set of attributes is used. The initial state of *mutex will be "initialized and unlocked".
Notes:
pthread_mutex_destroy()
Prototype: int pthread_mutex_destroy(pthread_mutex_t * restrict mutex);
Library: #include <pthread.h>
Purpose: This destroys the mutex object *mutex, so *mutex becomes uninitialized.
Notes:
pthread_mutex_lock()
Prototype: int pthread_mutex_lock(pthread_mutex_t * mutex);
Library: #include <pthread.h>
Purpose: This locks *mutex. If necessary, the caller is blocked until *mutex is unlocked (by someone else) and then &mutex is locked. When the function call ends, *mutex will be in a locked state.
Notes:
pthread_mutex_unlock()
Prototype: int pthread_mutex_unlock(pthread_mutex_t * mutex);
Library: #include <pthread.h>
Purpose: This unlocks *mutex.
Notes: