2.8. sem — Counting semaphores

The semaphore is a synchronization primitive used to protect a shared resource. A semaphore counts the number of resources taken, and suspends threads when the maximum number of resources are taken. When a resource becomes available, a suspended thread is resumed.

A semaphore initialized with count_max one(1) is called a binary semaphore. A binary semaphore can only be taken by one thread at a time and can be used to signal that an event has occured. That is, sem_give() may be called multiple times and the semaphore resource count will remain at zero(0) until sem_take() is called.

2.8.1. Example usage

This is a small example of protecting a shared resource with a semaphore.

struct sem_t sem;
int resource = 0;

/* Initialize the semaphore. */
sem_init(&sem, 0, 1);

/* Increment the shared resource by one. */
sem_take(&sem, NULL);
resource++;
sem_give(&sem, 1);

Source code: src/sync/sem.h, src/sync/sem.c

Test code: tst/sync/sem/main.c

Test coverage: src/sync/sem.c


Defines

SEM_INIT_DECL(name, _count, _count_max)

Functions

int sem_module_init(void)

Initialize the semaphore module. This function must be called before calling any other function in this module.

The module will only be initialized once even if this function is called multiple times.

Return
zero(0) or negative error code

int sem_init(struct sem_t *self_p, int count, int count_max)

Initialize given semaphore object. Maximum count is the number of resources that can be taken at any given moment.

Return
zero(0) or negative error code.
Parameters
  • self_p: Semaphore to initialize.
  • count: Initial taken resource count. Set the initial count to the same value as count_max to initialize the semaphore with all resources taken.
  • count_max: Maximum number of resources that can be taken at any given moment.

int sem_take(struct sem_t *self_p, struct time_t *timeout_p)

Take given semaphore. If the semaphore count is zero the calling thread will be suspended until count is incremented by sem_give().

Return
zero(0) or negative error code.
Parameters
  • self_p: Semaphore to take.
  • timeout_p: Timeout.

int sem_give(struct sem_t *self_p, int count)

Give given count to given semaphore. Any suspended thread waiting for this semaphore, in sem_take(), is resumed. This continues until the semaphore count becomes zero or there are no threads in the suspended list.

Giving a count greater than the currently taken count is allowed and results in all resources available. This is especially useful for binary semaphores where sem_give() if often called more often than sem_take().

Return
zero(0) or negative error code.
Parameters
  • self_p: Semaphore to give count to.
  • count: Count to give.

int sem_give_isr(struct sem_t *self_p, int count)

Give given count to given semaphore from isr or with the system lock taken.

Return
zero(0) or negative error code.
Parameters
  • self_p: Semaphore to give count to.
  • count: Count to give.

struct sem_t

Public Members

int count

Number of used resources.

int count_max

Maximum number of resources.

struct thrd_prio_list_t waiters

Wait list.