2018-02-06 11:57:44 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018 Intel Corporation
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <errno.h>
|
2018-04-06 01:11:15 +08:00
|
|
|
#include <posix/pthread.h>
|
2018-02-06 11:57:44 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Destroy semaphore.
|
|
|
|
*
|
|
|
|
* see IEEE 1003.1
|
|
|
|
*/
|
|
|
|
int sem_destroy(sem_t *semaphore)
|
|
|
|
{
|
|
|
|
if (semaphore == NULL) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-03-16 14:35:27 +08:00
|
|
|
if (k_sem_count_get(semaphore)) {
|
|
|
|
errno = EBUSY;
|
|
|
|
return -1;
|
|
|
|
}
|
2018-02-06 11:57:44 +08:00
|
|
|
|
2018-03-16 14:35:27 +08:00
|
|
|
k_sem_reset(semaphore);
|
2018-02-06 11:57:44 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get value of semaphore.
|
|
|
|
*
|
|
|
|
* See IEEE 1003.1
|
|
|
|
*/
|
|
|
|
int sem_getvalue(sem_t *semaphore, int *value)
|
|
|
|
{
|
|
|
|
*value = (int) k_sem_count_get(semaphore);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* @brief Initialize semaphore.
|
|
|
|
*
|
|
|
|
* See IEEE 1003.1
|
|
|
|
*/
|
|
|
|
int sem_init(sem_t *semaphore, int pshared, unsigned int value)
|
|
|
|
{
|
2018-03-07 00:38:00 +08:00
|
|
|
if (value > CONFIG_SEM_VALUE_MAX) {
|
2018-02-06 11:57:44 +08:00
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-03-16 14:35:27 +08:00
|
|
|
/*
|
|
|
|
* Zephyr has no concept of process, so only thread shared
|
|
|
|
* semaphore makes sense in here.
|
|
|
|
*/
|
|
|
|
__ASSERT(pshared == 0, "pshared should be 0");
|
2018-02-06 11:57:44 +08:00
|
|
|
|
|
|
|
k_sem_init(semaphore, value, CONFIG_SEM_VALUE_MAX);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Unlock a semaphore.
|
|
|
|
*
|
|
|
|
* See IEEE 1003.1
|
|
|
|
*/
|
|
|
|
int sem_post(sem_t *semaphore)
|
|
|
|
{
|
|
|
|
if (semaphore == NULL) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
k_sem_give(semaphore);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-03-16 14:35:27 +08:00
|
|
|
* @brief Try time limited locking a semaphore.
|
2018-02-06 11:57:44 +08:00
|
|
|
*
|
|
|
|
* See IEEE 1003.1
|
|
|
|
*/
|
|
|
|
int sem_timedwait(sem_t *semaphore, struct timespec *abstime)
|
|
|
|
{
|
2018-03-16 14:35:27 +08:00
|
|
|
s32_t timeout;
|
|
|
|
s64_t current_ms, abstime_ms;
|
2018-02-06 11:57:44 +08:00
|
|
|
|
|
|
|
__ASSERT(abstime, "abstime pointer NULL");
|
|
|
|
|
|
|
|
if ((abstime->tv_sec < 0) || (abstime->tv_nsec >= NSEC_PER_SEC)) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-03-16 14:35:27 +08:00
|
|
|
current_ms = (s64_t)k_uptime_get();
|
|
|
|
abstime_ms = (s64_t)_ts_to_ms(abstime);
|
2018-02-06 11:57:44 +08:00
|
|
|
|
|
|
|
if (abstime_ms <= current_ms) {
|
2018-03-16 14:35:27 +08:00
|
|
|
timeout = K_NO_WAIT;
|
2018-02-06 11:57:44 +08:00
|
|
|
} else {
|
2018-03-16 14:35:27 +08:00
|
|
|
timeout = (s32_t)(abstime_ms - current_ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (k_sem_take(semaphore, timeout)) {
|
|
|
|
errno = ETIMEDOUT;
|
|
|
|
return -1;
|
2018-02-06 11:57:44 +08:00
|
|
|
}
|
|
|
|
|
2018-03-16 14:35:27 +08:00
|
|
|
return 0;
|
2018-02-06 11:57:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-03-16 14:35:27 +08:00
|
|
|
* @brief Lock a semaphore if not taken.
|
2018-02-06 11:57:44 +08:00
|
|
|
*
|
|
|
|
* See IEEE 1003.1
|
|
|
|
*/
|
|
|
|
int sem_trywait(sem_t *semaphore)
|
|
|
|
{
|
|
|
|
if (k_sem_take(semaphore, K_NO_WAIT) == -EBUSY) {
|
|
|
|
errno = EAGAIN;
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-03-16 14:35:27 +08:00
|
|
|
* @brief Lock a semaphore.
|
2018-02-06 11:57:44 +08:00
|
|
|
*
|
|
|
|
* See IEEE 1003.1
|
|
|
|
*/
|
|
|
|
int sem_wait(sem_t *semaphore)
|
|
|
|
{
|
2018-03-16 14:35:27 +08:00
|
|
|
k_sem_take(semaphore, K_FOREVER);
|
|
|
|
return 0;
|
2018-02-06 11:57:44 +08:00
|
|
|
}
|