Semaphore

https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/semaphore.h.html

Defines

SEM_FAILED ((sem_t *)0)

Semaphore initialization failed.

SEM_VALUE_MAX (0x7FFFFFFF)

Maximum value a semaphore may hold.

Typedefs

typedef void *sem_t

Functions

int sem_init(sem_t *semaphore, int pshared, unsigned count)

Initialize an unnamed semaphore with the given initial count.

Initializes the semaphore with an initial count of count. When the MPU is enabled the semaphore state is protected from unprivileged threads. The pshared flag is accepted but ignored — semaphores are always process-private on this kernel.

Error numbers:

Parameters:
  • semaphore – Pointer to the semaphore.

  • pshared – Ignored; semaphores are always process-private.

  • count – Initial semaphore count, at most SEM_VALUE_MAX.

Returns:

0 on success, -1 on error and errno set.

int sem_destroy(sem_t *semaphore)

Release the resources held by a semaphore.

The semaphore must have no waiters at the time of the call. The kernel object is freed back to the kernel heap and the caller’s handle is cleared, so any subsequent use of semaphore fails with EINVAL.

Error numbers:

  • EINVAL if the semaphore is invalid.

  • EBUSY if one or more threads are blocked on the semaphore.

Parameters:
  • semaphore – Pointer to the semaphore.

Returns:

int 0 on success, -1 on error and errno set.

int sem_post(sem_t *semaphore)

Increment a semaphore and wake one waiter, if any.

If the count is already at SEM_VALUE_MAX the call leaves the semaphore unchanged and reports an overflow. When QRT_CFG_DEFER_ENABLE is enabled the call may also be made from a deferred function or a timer callback (see qrt_defer_call()).

Error numbers:

  • EINVAL if the semaphore is invalid.

  • EOVERFLOW if the semaphore count is already at its maximum value.

Parameters:
  • semaphore – Pointer to the semaphore.

Returns:

int 0 on success, -1 on error and errno set.

static sem_t        event_sem;
static unsigned int events;

static void event_deferred(qrt_u32_t parameter)
{
    (void)parameter;
    (void)sem_post(&event_sem);
}

void Device_IRQHandler(void)
{
    (void)qrt_defer_call(event_deferred, 0u);
}

void *worker(void *arg)
{
    (void)arg;
    if (sem_init(&event_sem, 0, 0u) == 0)
    {
        for (;;)
        {
            (void)sem_wait(&event_sem);
            events++;
        }
    }
    return NULL;
}

int sem_timedwait(sem_t *semaphore, const struct timespec *abstime)

Decrement a semaphore, waiting until abstime on CLOCK_REALTIME if it is currently zero.

A thin wrapper around sem_clockwait() that fixes the clock to CLOCK_REALTIME.

Error numbers:

  • EINVAL if the semaphore is invalid.

  • EINVAL if the thread would have to wait and abstime has nanoseconds outside [0, 999’999’999].

  • ETIMEDOUT if the thread would have to wait and the deadline has passed (negative seconds lie before the epoch), or elapses before the count becomes positive.

    See also

    sem_clockwait() for example.

Parameters:
  • semaphore – Pointer to the semaphore.

  • abstime – Pointer to the absolute time to wait until.

Returns:

0 on success, -1 on error and errno set.

int sem_clockwait(sem_t *semaphore, clockid_t clock_id, const struct timespec *abstime)

Decrement a semaphore, waiting until abstime on the chosen clock if it is currently zero.

If the count is positive it is decremented and the call returns immediately. Otherwise the caller blocks on the semaphore’s wait list and is woken by sem_post() or when the deadline elapses. Every abstime, {0, 0} included, is an absolute time on clock_id; one with negative seconds lies before the epoch and has already passed. The call must be made from a thread, never from a deferred function or a timer callback.

Error numbers:

  • EINVAL if the semaphore is invalid.

  • EINVAL if the thread would have to wait and clock_id is not a supported clock.

  • EINVAL if the thread would have to wait and abstime has nanoseconds outside [0, 999’999’999].

  • ETIMEDOUT if the thread would have to wait and the deadline has passed (negative seconds lie before the epoch), or elapses before the count becomes positive.

Parameters:
  • semaphore – Pointer to the semaphore.

  • clock_id – Clock ID to use for the timeout.

  • abstime – Pointer to the absolute time to wait until.

Returns:

0 on success, -1 on error and errno set.

static unsigned int events;
static unsigned int timeouts;

void *worker(void *arg)
{
    sem_t           *sem = (sem_t *)arg;
    struct timespec  deadline;

    for (;;)
    {
        (void)clock_gettime(CLOCK_MONOTONIC, &deadline);
        deadline.tv_sec += 1;

        if (sem_clockwait(sem, CLOCK_MONOTONIC, &deadline) == 0)
        {
            events++;
        }
        else if (errno == ETIMEDOUT)
        {
            timeouts++;
        }
    }
    return NULL;
}

int sem_trywait(sem_t *semaphore)

Decrement a semaphore if doing so will not block.

Never blocks: the call succeeds when the count is positive and reports EAGAIN otherwise. When QRT_CFG_DEFER_ENABLE is enabled the call may also be made from a deferred function or a timer callback (see qrt_defer_call()), which sem_wait(), sem_timedwait() and sem_clockwait() may not.

Error numbers:

  • EINVAL if the semaphore is invalid.

  • EAGAIN if the semaphore count is zero.

Parameters:
  • semaphore – Pointer to the semaphore.

Returns:

0 on success, -1 on error and errno set.

int sem_wait(sem_t *semaphore)

Decrement a semaphore, waiting indefinitely if it is currently zero.

Equivalent to sem_timedwait() with a NULL deadline.

Error numbers:

Parameters:
  • semaphore – Pointer to the semaphore.

Returns:

0 on success, -1 on error and errno set.

int sem_getvalue(sem_t *semaphore, int *sval)

Read a semaphore’s current count into sval.

Stores the current count, or 0 when the semaphore is locked (held with no remaining permits). When QRT_CFG_DEFER_ENABLE is enabled the call may also be made from a deferred function or a timer callback (see qrt_defer_call()).

Error numbers:

  • EINVAL if the semaphore is invalid.

Parameters:
  • semaphore – Pointer to the semaphore.

  • sval – Pointer to the location where the current value will be stored.

Returns:

int 0 on success, -1 on error and errno set.

sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value)

Not supported.

Returns:

Always SEM_FAILED and sets errno to ENOSYS.

int sem_close(sem_t *semaphore)

Not supported.

Returns:

Always -1 and sets errno to ENOSYS.

Not supported.

Returns:

Always -1 and sets errno to ENOSYS.