From 45b30a8e913aa8a677ba202ff7e5f4b82abb27f8 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 19 Oct 2015 16:43:27 +0200 Subject: [PATCH] posix_semaphore: make API POSIX compliant --- sys/posix/include/semaphore.h | 151 ++++++++++++++++++++++---- sys/posix/semaphore/posix_semaphore.c | 11 +- tests/posix_semaphore/main.c | 2 +- 3 files changed, 137 insertions(+), 27 deletions(-) diff --git a/sys/posix/include/semaphore.h b/sys/posix/include/semaphore.h index fabeb337e..8ccb3de25 100644 --- a/sys/posix/include/semaphore.h +++ b/sys/posix/include/semaphore.h @@ -40,7 +40,7 @@ typedef sema_t sem_t; #define SEM_FAILED ((sem_t *) 0) /** - * @brief Initialize semaphore. + * @brief Initialize an unnamed semaphore. * * @see * The Open Group Base Specifications Issue 7, sem_init() @@ -58,13 +58,108 @@ typedef sema_t sem_t; * @param[in] value Value to set. * * @return 0 on success. - * @return -EINVAL, if semaphore is invalid. + * @return -1, on error and errno set to indicate the error. */ -#define sem_init(sem, pshared, value) sema_create((sema_t *)(sem), (value)) +static inline int sem_init(sem_t *sem, int pshared, unsigned value) +{ + int res = sema_create((sema_t *)sem, value); + (void)pshared; + if (res < 0) { + errno = -res; + return -1; + } + return 0; +} + +/** + * @brief destroy an unnamed semaphore + * + * @see + * The Open Group Base Specifications Issue 7, sem_destroy() + * + * + * The sem_destroy() function shall destroy the unnamed semaphore indicated by @p sem. Only a + * semaphore that was created using sem_init() may be destroyed using sem_destroy(); the effect of + * calling sem_destroy() with a named semaphore is undefined. The effect of subsequent use of the + * semaphore @p sem is undefined until sem is reinitialized by another call to sem_init(). + * + * It is safe to destroy an initialized semaphore upon which no threads are currently blocked. + * The effect of destroying a semaphore upon which other threads are currently blocked is + * undefined. + * + * @param sem A semaphore. + * + * @return 0 on success. + * @return -1, on error and errno set to indicate the error. + */ +static inline int sem_destroy(sem_t *sem) +{ + int res = sema_destroy((sema_t *)sem); + if (res < 0) { + errno = -res; + return -1; + } + return 0; +} + +/** + * @brief Unlock a semaphore. + * + * @see + * The Open Group Base Specifications Issue 7, sem_post() + * + * + * The sem_post() function shall unlock the semaphore referenced by @p sem by performing a + * semaphore unlock operation on that semaphore. + * + * If the semaphore value resulting from this operation is positive, then no threads were blocked + * waiting for the semaphore to become unlocked; the semaphore value is simply incremented. + * + * If the value of the semaphore resulting from this operation is zero, then one of the threads + * blocked waiting for the semaphore shall be allowed to return successfully from its call to + * sem_wait(). + * + * @param sem A semaphore + * + * @return 0 on success. + * @return -1, on error and errno set to indicate the error. + */ +static inline int sem_post(sem_t *sem) +{ + int res = sema_post((sema_t *)sem); + if (res < 0) { + errno = -res; + return -1; + } + return 0; +} -#define sem_destroy(sem) sema_destroy((sema_t *)(sem)) -#define sem_post(sem) sema_post((sema_t *)(sem)) -#define sem_wait(sem) sema_wait((sema_t *)(sem)) +/** + * @brief Lock a semaphore. + * + * @see + * The Open Group Base Specifications Issue 7, sem_wait() + * + * + * The sem_wait() function shall lock the semaphore referenced by @p sem by performing a semaphore + * lock operation on that semaphore. If the semaphore value is currently zero, then the calling + * thread shall not return from the call to sem_wait() until it either locks the semaphore or the + * call is interrupted by a signal. + * + * @param sem A semaphore. + * + * @return 0 on success. + * @return -1, on error and errno set to indicate the error. + */ +static inline int sem_wait(sem_t *sem) +{ + int res = sema_wait((sema_t *)sem); + if (res < 0) { + errno = -res; + return -1; + } + return 0; +} /** * @brief Open a named semaphore @p name with open flags @p oflag. @@ -80,7 +175,13 @@ typedef sema_t sem_t; * * @return Always @ref SEM_FAILED, since it is not implemented currently. */ -#define sem_open(name, oflag, ...) (SEM_FAILED) +static inline sem_t *sem_open(const char *name, int oflag, ...) +{ + (void)name; + (void)oflag; + errno = ENOMEM; + return SEM_FAILED; +} /** * @brief Close descriptor for named semaphore @p sem. @@ -95,7 +196,12 @@ typedef sema_t sem_t; * * @return Always -1, since it is not implemented currently. */ -#define sem_close(sem) (-1) +static inline int sem_close(sem_t *sem) +{ + (void)sem; + errno = EINVAL; + return -1; +} /** * @brief Remove named semaphore @p name. @@ -110,7 +216,12 @@ typedef sema_t sem_t; * * @return Always -1, since it is not implemented currently. */ -#define sem_unlink(name) (-1) +static inline int sem_unlink(const char *name) +{ + (void)name; + errno = ENOENT; + return -1; +} /** * @brief Similar to `sem_wait' but wait only until @p abstime. @@ -129,15 +240,13 @@ typedef sema_t sem_t; * this value) the timeout for the wait shall expire. If the value specified * has already passed the timeout expires immediately. * - * @return 0 on success - * @return -EINVAL, if semaphore is invalid. - * @return -ETIMEDOUT, if the semaphore times out. - * @return -ECANCELED, if the semaphore was destroyed. + * @return 0 on success. + * @return -1, on error and errno set to indicate the error. */ int sem_timedwait(sem_t *sem, const struct timespec *abstime); /** - * @brief Test whether SEM is posted. + * @brief Test whether @p sem is posted. * * @see * The Open Group Base Specifications Issue 7, sem_trywait() @@ -145,14 +254,13 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime); * * @param[in] sem Semaphore to try to wait on * - * @return 0 on success - * @return -EINVAL, if semaphore is invalid. - * @return -EAGAIN, if the semaphore was already locked. + * @return 0 on success. + * @return -1, on error and errno set to indicate the error. */ int sem_trywait(sem_t *sem); /** - * @brief Get current value of SEM and store it in *SVAL. + * @brief Get current value of @p sem and store it in @p sval. * * @see * The Open Group Base Specifications Issue 7, sem_getvalue() @@ -161,8 +269,8 @@ int sem_trywait(sem_t *sem); * @param[in] sem Semaphore to get the value from. * @param[out] sval Place where value goes to. * - * @return 0 on success - * @return -EINVAL, if semaphore is invalid. + * @return 0 on success. + * @return -1, on error and errno set to indicate the error. */ static inline int sem_getvalue(sem_t *sem, int *sval) { @@ -170,7 +278,8 @@ static inline int sem_getvalue(sem_t *sem, int *sval) *sval = (int)sem->value; return 0; } - return -EINVAL; + errno = EINVAL; + return -1; } #ifdef __cplusplus diff --git a/sys/posix/semaphore/posix_semaphore.c b/sys/posix/semaphore/posix_semaphore.c index 4d91053de..5db567379 100644 --- a/sys/posix/semaphore/posix_semaphore.c +++ b/sys/posix/semaphore/posix_semaphore.c @@ -39,14 +39,15 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime) vtimer_now(&now); if (timex_cmp(now, timeout) > 0) { errno = ETIMEDOUT; - return -ETIMEDOUT; + return -1; } timeout = timex_sub(timeout, now); - res = sema_wait_timed(sem, &timeout); + res = sema_wait_timed((sema_t *)sem, &timeout); if (res < 0) { errno = -res; + return -1; } - return res; + return 0; } int sem_trywait(sem_t *sem) @@ -55,13 +56,13 @@ int sem_trywait(sem_t *sem) int result; if (sem == NULL) { errno = EINVAL; - return -EINVAL; + return -1; } old_state = disableIRQ(); value = sem->value; if (value == 0) { errno = EAGAIN; - result = -EAGAIN; + result = -1; } else { result = 0; diff --git a/tests/posix_semaphore/main.c b/tests/posix_semaphore/main.c index e113bfe9d..257083f74 100644 --- a/tests/posix_semaphore/main.c +++ b/tests/posix_semaphore/main.c @@ -23,11 +23,11 @@ */ #include +#include #include "msg.h" #include "timex.h" #include "thread.h" -#include "semaphore.h" #include "vtimer.h" #define SEMAPHORE_MSG_QUEUE_SIZE (8)