posix: semaphore: fix bugs and simplify code
Modifies several functions that are causing wrong behaviour. * semaphore.h: add missing restrict keyword. * sem_destroy(): check that nobody is waiting before destroying the object. * sem_timedwait(): simpify function logic and fix a bug when abstime > currtime, that passed ticks instead of ms to k_sem_take(). * sem_wait(): avoid unnecessary checks. * sem_init(): add pshared value assertion. Signed-off-by: Juan Manuel Torres Palma <j.m.torrespalma@gmail.com>
This commit is contained in:
parent
08418a210d
commit
342da7ac72
2 changed files with 29 additions and 50 deletions
|
@ -14,10 +14,10 @@ extern "C" {
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
int sem_destroy(sem_t *semaphore);
|
int sem_destroy(sem_t *semaphore);
|
||||||
int sem_getvalue(sem_t *semaphore, int *value);
|
int sem_getvalue(sem_t *restrict semaphore, int *restrict value);
|
||||||
int sem_init(sem_t *semaphore, int pshared, unsigned int value);
|
int sem_init(sem_t *semaphore, int pshared, unsigned int value);
|
||||||
int sem_post(sem_t *semaphore);
|
int sem_post(sem_t *semaphore);
|
||||||
int sem_timedwait(sem_t *semaphore, struct timespec *abstime);
|
int sem_timedwait(sem_t *restrict semaphore, struct timespec *restrict abstime);
|
||||||
int sem_trywait(sem_t *semaphore);
|
int sem_trywait(sem_t *semaphore);
|
||||||
int sem_wait(sem_t *semaphore);
|
int sem_wait(sem_t *semaphore);
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,6 @@
|
||||||
/**
|
/**
|
||||||
* @brief Destroy semaphore.
|
* @brief Destroy semaphore.
|
||||||
*
|
*
|
||||||
* FIXME: EBUSY is not taken care as of now
|
|
||||||
*
|
|
||||||
* see IEEE 1003.1
|
* see IEEE 1003.1
|
||||||
*/
|
*/
|
||||||
int sem_destroy(sem_t *semaphore)
|
int sem_destroy(sem_t *semaphore)
|
||||||
|
@ -21,8 +19,12 @@ int sem_destroy(sem_t *semaphore)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
k_sem_reset(semaphore);
|
if (k_sem_count_get(semaphore)) {
|
||||||
|
errno = EBUSY;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sem_reset(semaphore);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,9 +41,6 @@ int sem_getvalue(sem_t *semaphore, int *value)
|
||||||
/**
|
/**
|
||||||
* @brief Initialize semaphore.
|
* @brief Initialize semaphore.
|
||||||
*
|
*
|
||||||
* API only accepts 0 to share share semaphore among threads. Values
|
|
||||||
* greater than 0 are invalid as zephyr does not support processes.
|
|
||||||
*
|
|
||||||
* See IEEE 1003.1
|
* See IEEE 1003.1
|
||||||
*/
|
*/
|
||||||
int sem_init(sem_t *semaphore, int pshared, unsigned int value)
|
int sem_init(sem_t *semaphore, int pshared, unsigned int value)
|
||||||
|
@ -51,10 +50,11 @@ int sem_init(sem_t *semaphore, int pshared, unsigned int value)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pshared != 0) {
|
/*
|
||||||
errno = ENOSYS;
|
* Zephyr has no concept of process, so only thread shared
|
||||||
return -1;
|
* semaphore makes sense in here.
|
||||||
}
|
*/
|
||||||
|
__ASSERT(pshared == 0, "pshared should be 0");
|
||||||
|
|
||||||
k_sem_init(semaphore, value, CONFIG_SEM_VALUE_MAX);
|
k_sem_init(semaphore, value, CONFIG_SEM_VALUE_MAX);
|
||||||
|
|
||||||
|
@ -77,36 +77,15 @@ int sem_post(sem_t *semaphore)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int take_and_convert(sem_t *semaphore, s32_t timeout)
|
|
||||||
{
|
|
||||||
int temp, ret;
|
|
||||||
|
|
||||||
temp = k_sem_take(semaphore, timeout);
|
|
||||||
|
|
||||||
if (temp == -EBUSY) {
|
|
||||||
errno = EAGAIN;
|
|
||||||
ret = -1;
|
|
||||||
} else if (temp != 0) {
|
|
||||||
errno = ETIMEDOUT;
|
|
||||||
ret = -1;
|
|
||||||
} else {
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Lock a sempahore.
|
* @brief Try time limited locking a semaphore.
|
||||||
*
|
*
|
||||||
* See IEEE 1003.1
|
* See IEEE 1003.1
|
||||||
*/
|
*/
|
||||||
int sem_timedwait(sem_t *semaphore, struct timespec *abstime)
|
int sem_timedwait(sem_t *semaphore, struct timespec *abstime)
|
||||||
{
|
{
|
||||||
u32_t timeout;
|
s32_t timeout;
|
||||||
long msecs = 0;
|
s64_t current_ms, abstime_ms;
|
||||||
s64_t current_ms;
|
|
||||||
s32_t abstime_ms;
|
|
||||||
|
|
||||||
__ASSERT(abstime, "abstime pointer NULL");
|
__ASSERT(abstime, "abstime pointer NULL");
|
||||||
|
|
||||||
|
@ -115,21 +94,25 @@ int sem_timedwait(sem_t *semaphore, struct timespec *abstime)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_ms = k_uptime_get();
|
current_ms = (s64_t)k_uptime_get();
|
||||||
abstime_ms = _ts_to_ms(abstime);
|
abstime_ms = (s64_t)_ts_to_ms(abstime);
|
||||||
msecs = abstime_ms - current_ms;
|
|
||||||
|
|
||||||
if (abstime_ms <= current_ms) {
|
if (abstime_ms <= current_ms) {
|
||||||
timeout = 0;
|
timeout = K_NO_WAIT;
|
||||||
} else {
|
} else {
|
||||||
timeout = _ms_to_ticks(msecs);
|
timeout = (s32_t)(abstime_ms - current_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
return take_and_convert(semaphore, timeout);
|
if (k_sem_take(semaphore, timeout)) {
|
||||||
|
errno = ETIMEDOUT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Lock a sempahore.
|
* @brief Lock a semaphore if not taken.
|
||||||
*
|
*
|
||||||
* See IEEE 1003.1
|
* See IEEE 1003.1
|
||||||
*/
|
*/
|
||||||
|
@ -144,16 +127,12 @@ int sem_trywait(sem_t *semaphore)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Lock a sempahore.
|
* @brief Lock a semaphore.
|
||||||
*
|
*
|
||||||
* See IEEE 1003.1
|
* See IEEE 1003.1
|
||||||
*/
|
*/
|
||||||
int sem_wait(sem_t *semaphore)
|
int sem_wait(sem_t *semaphore)
|
||||||
{
|
{
|
||||||
if (k_sem_take(semaphore, K_FOREVER) == -EBUSY) {
|
k_sem_take(semaphore, K_FOREVER);
|
||||||
errno = EAGAIN;
|
return 0;
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue