From ee4f79482acbc7fbdfcbdc643862965998c6f746 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 19 Oct 2015 16:15:37 +0200 Subject: [PATCH 1/9] sem: rename to sema To prevent name colisions with POSIX semaphores --- Makefile.dep | 4 ++-- sys/Makefile | 4 ++-- sys/include/{sem.h => sema.h} | 0 sys/posix/include/semaphore.h | 2 +- sys/posix/semaphore/posix_semaphore.c | 2 +- sys/{sem => sema}/Makefile | 0 sys/{sem/sem.c => sema/sema.c} | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) rename sys/include/{sem.h => sema.h} (100%) rename sys/{sem => sema}/Makefile (100%) rename sys/{sem/sem.c => sema/sema.c} (99%) diff --git a/Makefile.dep b/Makefile.dep index 584830b6f4..c8f975e40f 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -283,11 +283,11 @@ ifneq (,$(filter posix,$(USEMODULE))) endif ifneq (,$(filter posix_semaphore,$(USEMODULE))) - USEMODULE += sem + USEMODULE += sema USEMODULE += vtimer endif -ifneq (,$(filter sem,$(USEMODULE))) +ifneq (,$(filter sema,$(USEMODULE))) USEMODULE += vtimer endif diff --git a/sys/Makefile b/sys/Makefile index 8baba47737..226e3c02c6 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -71,8 +71,8 @@ endif ifneq (,$(filter netopt,$(USEMODULE))) DIRS += net/crosslayer/netopt endif -ifneq (,$(filter sem,$(USEMODULE))) - DIRS += sem +ifneq (,$(filter sema,$(USEMODULE))) + DIRS += sema endif DIRS += $(dir $(wildcard $(addsuffix /Makefile, ${USEMODULE}))) diff --git a/sys/include/sem.h b/sys/include/sema.h similarity index 100% rename from sys/include/sem.h rename to sys/include/sema.h diff --git a/sys/posix/include/semaphore.h b/sys/posix/include/semaphore.h index cbf3fd64f9..1ffe83c1e4 100644 --- a/sys/posix/include/semaphore.h +++ b/sys/posix/include/semaphore.h @@ -26,7 +26,7 @@ #include #include -#include "sem.h" +#include "sema.h" #ifdef __cplusplus extern "C" { diff --git a/sys/posix/semaphore/posix_semaphore.c b/sys/posix/semaphore/posix_semaphore.c index 4e8d67893c..1076aae08a 100644 --- a/sys/posix/semaphore/posix_semaphore.c +++ b/sys/posix/semaphore/posix_semaphore.c @@ -21,7 +21,7 @@ #include "irq.h" #include "sched.h" -#include "sem.h" +#include "sema.h" #include "tcb.h" #include "timex.h" #include "thread.h" diff --git a/sys/sem/Makefile b/sys/sema/Makefile similarity index 100% rename from sys/sem/Makefile rename to sys/sema/Makefile diff --git a/sys/sem/sem.c b/sys/sema/sema.c similarity index 99% rename from sys/sem/sem.c rename to sys/sema/sema.c index a4256069b7..0cc1cff90e 100644 --- a/sys/sem/sem.c +++ b/sys/sema/sema.c @@ -24,7 +24,7 @@ #include "msg.h" #include "vtimer.h" -#include "sem.h" +#include "sema.h" #define ENABLE_DEBUG (0) #include "debug.h" From 5cef6bcc0a0325ca579ca8a662f6364737ebea37 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 19 Oct 2015 16:25:06 +0200 Subject: [PATCH 2/9] sema: apply rename to function and type names --- sys/include/sema.h | 37 ++++++++-------- sys/posix/include/semaphore.h | 8 +++- sys/posix/semaphore/posix_semaphore.c | 2 +- sys/sema/sema.c | 61 ++++++++++++--------------- 4 files changed, 55 insertions(+), 53 deletions(-) diff --git a/sys/include/sema.h b/sys/include/sema.h index 6d647e4dcd..4d5d724778 100644 --- a/sys/include/sema.h +++ b/sys/include/sema.h @@ -7,7 +7,7 @@ */ /** - * @defgroup sys_sem Semaphores + * @defgroup sys_sema Semaphores * @ingroup sys * @brief Lightweight semaphore implementation * @{ @@ -22,6 +22,7 @@ #ifndef SEM_H_ #define SEM_H_ +#include "msg.h" #include "priority_queue.h" #include "timex.h" @@ -35,7 +36,7 @@ extern "C" { typedef struct { volatile unsigned int value; /**< value of the semaphore */ priority_queue_t queue; /**< list of threads waiting for the semaphore */ -} sem_t; +} sema_t; /** * @brief Creates semaphore. @@ -44,13 +45,13 @@ typedef struct { * The Open Group Base Specifications Issue 7, sem_init() * (without `pshared` parameter) * - * @param[out] sem The created semaphore. + * @param[out] sema The created semaphore. * @param[in] value Initial value for the semaphore. * * @return 0 on success. * @return -EINVAL, if semaphore is invalid. */ -int sem_create(sem_t *sem, unsigned int value); +int sema_create(sema_t *sema, unsigned int value); /** * @brief Destroys a semaphore. @@ -59,19 +60,19 @@ int sem_create(sem_t *sem, unsigned int value); * The Open Group Base Specifications Issue 7, sem_destroy() * * - * @param[in] sem The semaphore to destroy. + * @param[in] sema The semaphore to destroy. * * @return 0 on success. * @return -EINVAL, if semaphore is invalid. */ -int sem_destroy(sem_t *sem); +int sema_destroy(sema_t *sema); /** * @brief Wait for a semaphore being posted. * * @pre Message queue of active thread is initialized (see @ref msg_init_queue()). * - * @param[in] sem A semaphore. + * @param[in] sema A semaphore. * @param[in] timeout Time until the semaphore times out. NULL for no timeout. * @param[out] msg Container for a spurious message during the timed wait (result == -EAGAIN). * @@ -81,12 +82,12 @@ int sem_destroy(sem_t *sem); * @return -ECANCELED, if the semaphore was destroyed. * @return -EAGAIN, if the thread received a message while waiting for the lock. */ -int sem_wait_timed_msg(sem_t *sem, timex_t *timeout, msg_t *msg); +int sema_wait_timed_msg(sema_t *sema, timex_t *timeout, msg_t *msg); /** * @brief Wait for a semaphore being posted (without timeout). * - * @param[in] sem A semaphore. + * @param[in] sema A semaphore. * @param[out] msg Container for a spurious message during the timed wait (result == -EAGAIN). * * @return 0 on success @@ -94,16 +95,16 @@ int sem_wait_timed_msg(sem_t *sem, timex_t *timeout, msg_t *msg); * @return -ECANCELED, if the semaphore was destroyed. * @return -EAGAIN, if the thread received a message while waiting for the lock. */ -static inline int sem_wait_msg(sem_t *sem, msg_t *msg) +static inline int sema_wait_msg(sema_t *sema, msg_t *msg) { - return sem_wait_timed_msg(sem, NULL, msg); + return sema_wait_timed_msg(sema, NULL, msg); } /** * @brief Wait for a semaphore being posted (dropping spurious messages). * @details Any spurious messages received while waiting for the semaphore are silently dropped. * - * @param[in] sem A semaphore. + * @param[in] sema A semaphore. * @param[in] timeout Time until the semaphore times out. NULL for no timeout. * * @return 0 on success @@ -111,31 +112,31 @@ static inline int sem_wait_msg(sem_t *sem, msg_t *msg) * @return -ETIMEDOUT, if the semaphore times out. * @return -ECANCELED, if the semaphore was destroyed. */ -int sem_wait_timed(sem_t *sem, timex_t *timeout); +int sema_wait_timed(sema_t *sema, timex_t *timeout); /** * @brief Wait for a semaphore being posted (without timeout, dropping spurious messages). * - * @param[in] sem A semaphore. + * @param[in] sema A semaphore. * * @return 0 on success * @return -EINVAL, if semaphore is invalid. * @return -ECANCELED, if the semaphore was destroyed. */ -static inline int sem_wait(sem_t *sem) +static inline int sema_wait(sema_t *sema) { - return sem_wait_timed(sem, NULL); + return sema_wait_timed(sema, NULL); } /** * @brief Signal semaphore. * - * @param[in] sem A semaphore. + * @param[in] sema A semaphore. * * @return -EINVAL, if semaphore is invalid. * @return -EOVERFLOW, if the semaphore's value would overflow. */ -int sem_post(sem_t *sem); +int sema_post(sema_t *sema); #ifdef __cplusplus } diff --git a/sys/posix/include/semaphore.h b/sys/posix/include/semaphore.h index 1ffe83c1e4..fabeb337e1 100644 --- a/sys/posix/include/semaphore.h +++ b/sys/posix/include/semaphore.h @@ -32,6 +32,8 @@ extern "C" { #endif +typedef sema_t sem_t; + /** * @brief Value returned if `sem_open' failed. */ @@ -58,7 +60,11 @@ extern "C" { * @return 0 on success. * @return -EINVAL, if semaphore is invalid. */ -#define sem_init(sem, pshared, value) sem_create(sem, value) +#define sem_init(sem, pshared, value) sema_create((sema_t *)(sem), (value)) + +#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 Open a named semaphore @p name with open flags @p oflag. diff --git a/sys/posix/semaphore/posix_semaphore.c b/sys/posix/semaphore/posix_semaphore.c index 1076aae08a..4d91053de2 100644 --- a/sys/posix/semaphore/posix_semaphore.c +++ b/sys/posix/semaphore/posix_semaphore.c @@ -42,7 +42,7 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime) return -ETIMEDOUT; } timeout = timex_sub(timeout, now); - res = sem_wait_timed(sem, &timeout); + res = sema_wait_timed(sem, &timeout); if (res < 0) { errno = -res; } diff --git a/sys/sema/sema.c b/sys/sema/sema.c index 0cc1cff90e..e5c3b0ca5f 100644 --- a/sys/sema/sema.c +++ b/sys/sema/sema.c @@ -33,45 +33,39 @@ #define MSG_TIMEOUT (0x0502) #define MSG_DESTROYED (0x0503) -int sem_create(sem_t *sem, unsigned int value) +int sema_create(sema_t *sema, unsigned int value) { - if (sem == NULL) { -#ifdef MODULE_POSIX_SEMAPHORE - errno = EINVAL; -#endif + if (sema == NULL) { return -EINVAL; } - sem->value = value; + sema->value = value; /* waiters for the mutex */ - sem->queue.first = NULL; + sema->queue.first = NULL; return 0; } -int sem_destroy(sem_t *sem) +int sema_destroy(sema_t *sema) { unsigned int old_state; priority_queue_node_t *next; - if (sem == NULL) { -#ifdef MODULE_POSIX_SEMAPHORE - errno = EINVAL; -#endif + if (sema == NULL) { return -EINVAL; } old_state = disableIRQ(); - while ((next = priority_queue_remove_head(&sem->queue)) != NULL) { + while ((next = priority_queue_remove_head(&sema->queue)) != NULL) { msg_t msg; kernel_pid_t pid = (kernel_pid_t)next->data; msg.type = MSG_DESTROYED; - msg.content.ptr = (void *) sem; + msg.content.ptr = (void *) sema; msg_send_int(&msg, pid); } restoreIRQ(old_state); return 0; } -int sem_wait_timed_msg(sem_t *sem, timex_t *timeout, msg_t *msg) +int sema_wait_timed_msg(sema_t *sema, timex_t *timeout, msg_t *msg) { - if (sem == NULL) { + if (sema == NULL) { return -EINVAL; } while (1) { @@ -79,9 +73,9 @@ int sem_wait_timed_msg(sem_t *sem, timex_t *timeout, msg_t *msg) priority_queue_node_t n; vtimer_t timeout_timer; - unsigned value = sem->value; + unsigned value = sema->value; if (value != 0) { - sem->value = value - 1; + sema->value = value - 1; restoreIRQ(old_state); return 0; } @@ -90,14 +84,14 @@ int sem_wait_timed_msg(sem_t *sem, timex_t *timeout, msg_t *msg) n.priority = (uint32_t)sched_active_thread->priority; n.data = (unsigned int)sched_active_pid; n.next = NULL; - priority_queue_add(&sem->queue, &n); + priority_queue_add(&sema->queue, &n); - DEBUG("sem_wait: %" PRIkernel_pid ": Adding node to semaphore queue: prio: %" PRIu32 "\n", + DEBUG("sema_wait: %" PRIkernel_pid ": Adding node to semaphore queue: prio: %" PRIu32 "\n", sched_active_thread->pid, sched_active_thread->priority); if (timeout != NULL) { vtimer_set_msg(&timeout_timer, *timeout, sched_active_pid, - MSG_TIMEOUT, sem); + MSG_TIMEOUT, sema); } restoreIRQ(old_state); @@ -107,7 +101,7 @@ int sem_wait_timed_msg(sem_t *sem, timex_t *timeout, msg_t *msg) vtimer_remove(&timeout_timer); /* remove timer just to be sure */ } - if (msg->content.ptr != (void *) sem) { + if (msg->content.ptr != (void *) sema) { return -EAGAIN; } @@ -124,41 +118,42 @@ int sem_wait_timed_msg(sem_t *sem, timex_t *timeout, msg_t *msg) } } -int sem_wait_timed(sem_t *sem, timex_t *timeout) +int sema_wait_timed(sema_t *sema, timex_t *timeout) { int result; do { msg_t msg; - result = sem_wait_timed_msg(sem, timeout, &msg); - DEBUG("sem_wait: %" PRIkernel_pid ": Discarding message from %" PRIkernel_pid "\n", + result = sema_wait_timed_msg(sema, timeout, &msg); + DEBUG("sema_wait: %" PRIkernel_pid ": Discarding message from %" PRIkernel_pid "\n", sched_active_thread->pid, msg->sender_pid); - } while (result == -EAGAIN); + } + while (result == -EAGAIN); return result; } -int sem_post(sem_t *sem) +int sema_post(sema_t *sema) { unsigned int old_state, value; priority_queue_node_t *next; - if (sem == NULL) { + if (sema == NULL) { return -EINVAL; } old_state = disableIRQ(); - value = sem->value; + value = sema->value; if (value == UINT_MAX) { restoreIRQ(old_state); return -EOVERFLOW; } - ++sem->value; - next = priority_queue_remove_head(&sem->queue); + ++sema->value; + next = priority_queue_remove_head(&sema->queue); if (next) { uint16_t prio = (uint16_t)next->priority; kernel_pid_t pid = (kernel_pid_t) next->data; msg_t msg; - DEBUG("sem_post: %" PRIkernel_pid ": waking up %" PRIkernel_pid "\n", + DEBUG("sema_post: %" PRIkernel_pid ": waking up %" PRIkernel_pid "\n", sched_active_thread->pid, next_process->pid); msg.type = MSG_SIGNAL; - msg.content.ptr = (void *) sem; + msg.content.ptr = (void *) sema; msg_send_int(&msg, pid); restoreIRQ(old_state); sched_switch(prio); From 45b30a8e913aa8a677ba202ff7e5f4b82abb27f8 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 19 Oct 2015 16:43:27 +0200 Subject: [PATCH 3/9] 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 fabeb337e1..8ccb3de251 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; +} -#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 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; +} + +/** + * @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 4d91053de2..5db5673797 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 e113bfe9dd..257083f745 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) From 5c2da0e289cb974f37a59218c30f0af765f9713d Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Sun, 25 Oct 2015 19:25:12 +0100 Subject: [PATCH 4/9] tests: adapt posix_semaphores test to correct API --- tests/posix_semaphore/main.c | 32 +++++++++++++++++---------- tests/posix_semaphore/tests/01-run.py | 1 + 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/tests/posix_semaphore/main.c b/tests/posix_semaphore/main.c index 257083f745..2ae718419a 100644 --- a/tests/posix_semaphore/main.c +++ b/tests/posix_semaphore/main.c @@ -46,7 +46,7 @@ static void *test1_second_thread(void *arg) msg_init_queue(test1_msg_queue, SEMAPHORE_MSG_QUEUE_SIZE); puts("second: sem_trywait"); - if (sem_trywait(&s1) == 0) { + if (sem_trywait(&s1) < 0) { puts("second: sem_trywait failed"); } @@ -54,7 +54,7 @@ static void *test1_second_thread(void *arg) puts("second: wait for post"); - if (sem_wait(&s1) != 1) { + if (sem_wait(&s1) < 0) { puts("second: sem_wait failed"); } @@ -68,7 +68,7 @@ static void test1(void) { puts("first: sem_init"); - if (sem_init(&s1, 0, 0) != 0) { + if (sem_init(&s1, 0, 0) < 0) { puts("first: sem_init failed"); } @@ -88,7 +88,7 @@ static void test1(void) puts("first: sem_getvalue"); int val; - if (sem_getvalue(&s1, &val) != 0 || val != 0) { + if (sem_getvalue(&s1, &val) < 0 || val != 0) { puts("first: sem_getvalue FAILED"); } @@ -102,7 +102,7 @@ static void test1(void) puts("first: sem_trywait"); - if (sem_trywait(&s1) != -1) { + if (sem_trywait(&s1) < 0) { puts("first: sem_trywait FAILED"); } @@ -110,7 +110,7 @@ static void test1(void) puts("first: sem_post"); - if (sem_post(&s1) != 1) { + if (sem_post(&s1) < 0) { puts("first: sem_post FAILED"); } @@ -120,7 +120,7 @@ static void test1(void) puts("first: sem_destroy"); - if (sem_destroy(&s1) != 0) { + if (sem_destroy(&s1) < 0) { puts("first: sem_destroy FAILED"); } @@ -141,7 +141,7 @@ void test2(void) { puts("first: sem_init"); - if (sem_init(&s1, 0, 0) != 0) { + if (sem_init(&s1, 0, 0) < 0) { puts("first: sem_init FAILED"); } @@ -201,11 +201,11 @@ static void *test3_two_one_thread(void *arg) void test3(void) { puts("first: sem_init s1"); - if (sem_init(&s1, 0, 0) != 0) { + if (sem_init(&s1, 0, 0) < 0) { puts("first: sem_init FAILED"); } puts("first: sem_init s2"); - if (sem_init(&s2, 0, 0) != 0) { + if (sem_init(&s2, 0, 0) < 0) { puts("first: sem_init FAILED"); } puts("first: create thread 1"); @@ -242,12 +242,20 @@ void test4(void) abs.tv_sec = now.seconds + 1; abs.tv_nsec = now.microseconds * 1000; puts("first: sem_init s1"); - if (sem_init(&s1, 0, 0) != 0) { + if (sem_init(&s1, 0, 0) < 0) { puts("first: sem_init FAILED"); } vtimer_now(&start); puts("first: wait 1 sec for s1"); - sem_timedwait(&s1, &abs); + if (sem_timedwait(&s1, &abs) != 0) { + if (errno != ETIMEDOUT) { + printf("error waiting: %d\n", errno); + return; + } + else { + puts("first: timed out"); + } + } vtimer_now(&stop); stop = timex_sub(stop, start); if (timex_cmp(stop, exp) < 0) { diff --git a/tests/posix_semaphore/tests/01-run.py b/tests/posix_semaphore/tests/01-run.py index 81abdeabf2..091741f6f6 100755 --- a/tests/posix_semaphore/tests/01-run.py +++ b/tests/posix_semaphore/tests/01-run.py @@ -89,6 +89,7 @@ def test4(term): term.expect_exact("######################### TEST4:") term.expect_exact("first: sem_init s1") term.expect_exact("first: wait 1 sec for s1") + term.expect_exact("first: timed out") term.expect(r"first: waited 1\.\d{6} s") if __name__ == "__main__": From d104cff214cff2ba645748313806f9d1fc82f696 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Sun, 25 Oct 2015 15:44:42 +0100 Subject: [PATCH 5/9] sema: port to xtimer --- Makefile.dep | 2 +- sys/include/sema.h | 12 ++++++------ sys/sema/sema.c | 25 ++++++++++++++----------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/Makefile.dep b/Makefile.dep index c8f975e40f..29776529fb 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -288,7 +288,7 @@ ifneq (,$(filter posix_semaphore,$(USEMODULE))) endif ifneq (,$(filter sema,$(USEMODULE))) - USEMODULE += vtimer + USEMODULE += xtimer endif ifneq (,$(filter vtimer,$(USEMODULE))) diff --git a/sys/include/sema.h b/sys/include/sema.h index 4d5d724778..360c4deb5b 100644 --- a/sys/include/sema.h +++ b/sys/include/sema.h @@ -73,7 +73,7 @@ int sema_destroy(sema_t *sema); * @pre Message queue of active thread is initialized (see @ref msg_init_queue()). * * @param[in] sema A semaphore. - * @param[in] timeout Time until the semaphore times out. NULL for no timeout. + * @param[in] timeout Time in microseconds until the semaphore times out. 0 for no timeout. * @param[out] msg Container for a spurious message during the timed wait (result == -EAGAIN). * * @return 0 on success @@ -82,7 +82,7 @@ int sema_destroy(sema_t *sema); * @return -ECANCELED, if the semaphore was destroyed. * @return -EAGAIN, if the thread received a message while waiting for the lock. */ -int sema_wait_timed_msg(sema_t *sema, timex_t *timeout, msg_t *msg); +int sema_wait_timed_msg(sema_t *sema, uint64_t timeout, msg_t *msg); /** * @brief Wait for a semaphore being posted (without timeout). @@ -97,7 +97,7 @@ int sema_wait_timed_msg(sema_t *sema, timex_t *timeout, msg_t *msg); */ static inline int sema_wait_msg(sema_t *sema, msg_t *msg) { - return sema_wait_timed_msg(sema, NULL, msg); + return sema_wait_timed_msg(sema, 0, msg); } /** @@ -105,14 +105,14 @@ static inline int sema_wait_msg(sema_t *sema, msg_t *msg) * @details Any spurious messages received while waiting for the semaphore are silently dropped. * * @param[in] sema A semaphore. - * @param[in] timeout Time until the semaphore times out. NULL for no timeout. + * @param[in] timeout Time in microseconds until the semaphore times out. 0 for no timeout. * * @return 0 on success * @return -EINVAL, if semaphore is invalid. * @return -ETIMEDOUT, if the semaphore times out. * @return -ECANCELED, if the semaphore was destroyed. */ -int sema_wait_timed(sema_t *sema, timex_t *timeout); +int sema_wait_timed(sema_t *sema, uint64_t timeout); /** * @brief Wait for a semaphore being posted (without timeout, dropping spurious messages). @@ -125,7 +125,7 @@ int sema_wait_timed(sema_t *sema, timex_t *timeout); */ static inline int sema_wait(sema_t *sema) { - return sema_wait_timed(sema, NULL); + return sema_wait_timed(sema, 0); } /** diff --git a/sys/sema/sema.c b/sys/sema/sema.c index e5c3b0ca5f..ef7f28b113 100644 --- a/sys/sema/sema.c +++ b/sys/sema/sema.c @@ -22,7 +22,7 @@ #include "irq.h" #include "msg.h" -#include "vtimer.h" +#include "xtimer.h" #include "sema.h" @@ -63,7 +63,7 @@ int sema_destroy(sema_t *sema) return 0; } -int sema_wait_timed_msg(sema_t *sema, timex_t *timeout, msg_t *msg) +int sema_wait_timed_msg(sema_t *sema, uint64_t timeout, msg_t *msg) { if (sema == NULL) { return -EINVAL; @@ -71,7 +71,8 @@ int sema_wait_timed_msg(sema_t *sema, timex_t *timeout, msg_t *msg) while (1) { unsigned old_state = disableIRQ(); priority_queue_node_t n; - vtimer_t timeout_timer; + xtimer_t timeout_timer; + msg_t timeout_msg; unsigned value = sema->value; if (value != 0) { @@ -89,19 +90,21 @@ int sema_wait_timed_msg(sema_t *sema, timex_t *timeout, msg_t *msg) DEBUG("sema_wait: %" PRIkernel_pid ": Adding node to semaphore queue: prio: %" PRIu32 "\n", sched_active_thread->pid, sched_active_thread->priority); - if (timeout != NULL) { - vtimer_set_msg(&timeout_timer, *timeout, sched_active_pid, - MSG_TIMEOUT, sema); + if (timeout != 0) { + timeout_msg.type = MSG_TIMEOUT; + timeout_msg.content.ptr = (char *)sema; + /* we will stay in the same stack context so we can use timeout_msg */ + xtimer_set_msg64(&timeout_timer, timeout, &timeout_msg, sched_active_pid); } restoreIRQ(old_state); msg_receive(msg); - if (timeout != NULL) { - vtimer_remove(&timeout_timer); /* remove timer just to be sure */ + if (timeout != 0) { + xtimer_remove(&timeout_timer); } - - if (msg->content.ptr != (void *) sema) { + priority_queue_remove(&sema->queue, &n); + if (msg->content.ptr != (void *)sema) { return -EAGAIN; } @@ -118,7 +121,7 @@ int sema_wait_timed_msg(sema_t *sema, timex_t *timeout, msg_t *msg) } } -int sema_wait_timed(sema_t *sema, timex_t *timeout) +int sema_wait_timed(sema_t *sema, uint64_t timeout) { int result; do { From 21ea7cc4ae0d46b058e1498ff4487cf1476a9354 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Sun, 25 Oct 2015 15:53:26 +0100 Subject: [PATCH 6/9] posix_semaphore: port to xtimer --- Makefile.dep | 2 +- sys/posix/semaphore/posix_semaphore.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Makefile.dep b/Makefile.dep index 29776529fb..770d23614c 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -284,7 +284,7 @@ endif ifneq (,$(filter posix_semaphore,$(USEMODULE))) USEMODULE += sema - USEMODULE += vtimer + USEMODULE += xtimer endif ifneq (,$(filter sema,$(USEMODULE))) diff --git a/sys/posix/semaphore/posix_semaphore.c b/sys/posix/semaphore/posix_semaphore.c index 5db5673797..d1152ef686 100644 --- a/sys/posix/semaphore/posix_semaphore.c +++ b/sys/posix/semaphore/posix_semaphore.c @@ -25,7 +25,7 @@ #include "tcb.h" #include "timex.h" #include "thread.h" -#include "vtimer.h" +#include "xtimer.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -34,15 +34,16 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime) { - timex_t now, timeout = { abstime->tv_sec, abstime->tv_nsec / USEC_IN_NS }; + uint64_t now, timeout = (((uint64_t)abstime->tv_sec) * SEC_IN_USEC) + + (abstime->tv_nsec / USEC_IN_NS); int res; - vtimer_now(&now); - if (timex_cmp(now, timeout) > 0) { + now = xtimer_now64(); + if (now > timeout) { errno = ETIMEDOUT; return -1; } - timeout = timex_sub(timeout, now); - res = sema_wait_timed((sema_t *)sem, &timeout); + timeout = timeout - now; + res = sema_wait_timed((sema_t *)sem, timeout); if (res < 0) { errno = -res; return -1; From aca1224401e26612f7242e5b7b20dc322bd569e2 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Sun, 25 Oct 2015 18:38:55 +0100 Subject: [PATCH 7/9] tests: port semaphore tests to xtimer --- tests/posix_semaphore/main.c | 26 +++++++++++++------------- tests/posix_semaphore/tests/01-run.py | 3 +-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/tests/posix_semaphore/main.c b/tests/posix_semaphore/main.c index 2ae718419a..155696fbf2 100644 --- a/tests/posix_semaphore/main.c +++ b/tests/posix_semaphore/main.c @@ -22,13 +22,14 @@ * @} */ +#include #include #include #include "msg.h" #include "timex.h" #include "thread.h" -#include "vtimer.h" +#include "xtimer.h" #define SEMAPHORE_MSG_QUEUE_SIZE (8) #define SEMAPHORE_TEST_THREADS (5) @@ -236,16 +237,16 @@ void test3(void) void test4(void) { struct timespec abs; - char timestamp[TIMEX_MAX_STR_LEN]; - timex_t now, start, stop, exp = { 1, 0 }; - vtimer_now(&now); - abs.tv_sec = now.seconds + 1; - abs.tv_nsec = now.microseconds * 1000; + uint64_t now, start, stop; + const uint64_t exp = 1000000; + now = xtimer_now64(); + abs.tv_sec = (time_t)((now / SEC_IN_USEC) + 1); + abs.tv_nsec = (long)((now % SEC_IN_USEC) * 1000); puts("first: sem_init s1"); if (sem_init(&s1, 0, 0) < 0) { puts("first: sem_init FAILED"); } - vtimer_now(&start); + start = xtimer_now64(); puts("first: wait 1 sec for s1"); if (sem_timedwait(&s1, &abs) != 0) { if (errno != ETIMEDOUT) { @@ -256,18 +257,17 @@ void test4(void) puts("first: timed out"); } } - vtimer_now(&stop); - stop = timex_sub(stop, start); - if (timex_cmp(stop, exp) < 0) { - printf("first: waited only %s => FAILED\n", - timex_to_str(stop, timestamp)); + stop = xtimer_now64() - start; + if (stop < exp) { + printf("first: waited only %" PRIu64 " usec => FAILED\n", stop); } - printf("first: waited %s\n", timex_to_str(stop, timestamp)); + printf("first: waited %" PRIu64 " usec\n", stop); } int main(void) { msg_init_queue(main_msg_queue, SEMAPHORE_MSG_QUEUE_SIZE); + xtimer_init(); puts("######################### TEST1:"); test1(); puts("######################### TEST2:"); diff --git a/tests/posix_semaphore/tests/01-run.py b/tests/posix_semaphore/tests/01-run.py index 091741f6f6..056098804f 100755 --- a/tests/posix_semaphore/tests/01-run.py +++ b/tests/posix_semaphore/tests/01-run.py @@ -32,7 +32,6 @@ def test1(term): term.expect_exact("first: sem_trywait FAILED") term.expect_exact("first: sem_trywait done") term.expect_exact("first: sem_post") - term.expect_exact("second: sem_wait failed") term.expect_exact("second: sem was posted") term.expect_exact("second: end") term.expect_exact("first: sem_post done") @@ -90,7 +89,7 @@ def test4(term): term.expect_exact("first: sem_init s1") term.expect_exact("first: wait 1 sec for s1") term.expect_exact("first: timed out") - term.expect(r"first: waited 1\.\d{6} s") + term.expect(r"first: waited 1\d{6} usec") if __name__ == "__main__": TERM = init() From 77547dd399cf4e2d4a03eed27b102807fc65b0aa Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 11 Nov 2015 11:30:12 +0100 Subject: [PATCH 8/9] sema: fix race-condition that causes timeout reset --- sys/sema/sema.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/sys/sema/sema.c b/sys/sema/sema.c index ef7f28b113..53962a1e72 100644 --- a/sys/sema/sema.c +++ b/sys/sema/sema.c @@ -65,16 +65,26 @@ int sema_destroy(sema_t *sema) int sema_wait_timed_msg(sema_t *sema, uint64_t timeout, msg_t *msg) { + unsigned old_state; + msg_t timeout_msg; + xtimer_t timeout_timer; if (sema == NULL) { return -EINVAL; } + if (timeout != 0) { + old_state = disableIRQ(); + timeout_msg.type = MSG_TIMEOUT; + timeout_msg.content.ptr = (char *)sema; + /* we will stay in the same stack context so we can use timeout_msg */ + xtimer_set_msg64(&timeout_timer, timeout, &timeout_msg, sched_active_pid); + restoreIRQ(old_state); + } while (1) { - unsigned old_state = disableIRQ(); priority_queue_node_t n; - xtimer_t timeout_timer; - msg_t timeout_msg; + unsigned value; - unsigned value = sema->value; + old_state = disableIRQ(); + value = sema->value; if (value != 0) { sema->value = value - 1; restoreIRQ(old_state); @@ -90,13 +100,6 @@ int sema_wait_timed_msg(sema_t *sema, uint64_t timeout, msg_t *msg) DEBUG("sema_wait: %" PRIkernel_pid ": Adding node to semaphore queue: prio: %" PRIu32 "\n", sched_active_thread->pid, sched_active_thread->priority); - if (timeout != 0) { - timeout_msg.type = MSG_TIMEOUT; - timeout_msg.content.ptr = (char *)sema; - /* we will stay in the same stack context so we can use timeout_msg */ - xtimer_set_msg64(&timeout_timer, timeout, &timeout_msg, sched_active_pid); - } - restoreIRQ(old_state); msg_receive(msg); From db01af35020403053cc0d124670033f61a04aaf2 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 24 Nov 2015 09:43:04 +0100 Subject: [PATCH 9/9] sema: deactivate interrupts for queue manipulation --- sys/sema/sema.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/sema/sema.c b/sys/sema/sema.c index 53962a1e72..b9ae892a97 100644 --- a/sys/sema/sema.c +++ b/sys/sema/sema.c @@ -102,11 +102,12 @@ int sema_wait_timed_msg(sema_t *sema, uint64_t timeout, msg_t *msg) restoreIRQ(old_state); msg_receive(msg); - + old_state = disableIRQ(); if (timeout != 0) { xtimer_remove(&timeout_timer); } priority_queue_remove(&sema->queue, &n); + restoreIRQ(old_state); if (msg->content.ptr != (void *)sema) { return -EAGAIN; }