mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-26 23:11:19 +01:00
Merge pull request #4110 from authmillenon/posix/api/i4109
posix_semaphore: make API POSIX compliant and port to xtimer (+ fixes)
This commit is contained in:
commit
7af2a62b12
@ -288,12 +288,12 @@ ifneq (,$(filter posix,$(USEMODULE)))
|
||||
endif
|
||||
|
||||
ifneq (,$(filter posix_semaphore,$(USEMODULE)))
|
||||
USEMODULE += sem
|
||||
USEMODULE += vtimer
|
||||
USEMODULE += sema
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter sem,$(USEMODULE)))
|
||||
USEMODULE += vtimer
|
||||
ifneq (,$(filter sema,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter vtimer,$(USEMODULE)))
|
||||
|
||||
@ -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})))
|
||||
|
||||
@ -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()
|
||||
* </a> (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,20 +60,20 @@ int sem_create(sem_t *sem, unsigned int value);
|
||||
* The Open Group Base Specifications Issue 7, sem_destroy()
|
||||
* </a>
|
||||
*
|
||||
* @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] timeout Time until the semaphore times out. NULL for no timeout.
|
||||
* @param[in] sema A semaphore.
|
||||
* @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
|
||||
@ -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, uint64_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,48 +95,48 @@ 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, 0, 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] timeout Time until the semaphore times out. NULL for no timeout.
|
||||
* @param[in] sema A semaphore.
|
||||
* @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 sem_wait_timed(sem_t *sem, 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).
|
||||
*
|
||||
* @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, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
}
|
||||
@ -26,19 +26,21 @@
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "sem.h"
|
||||
#include "sema.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef sema_t sem_t;
|
||||
|
||||
/**
|
||||
* @brief Value returned if `sem_open' failed.
|
||||
*/
|
||||
#define SEM_FAILED ((sem_t *) 0)
|
||||
|
||||
/**
|
||||
* @brief Initialize semaphore.
|
||||
* @brief Initialize an unnamed semaphore.
|
||||
*
|
||||
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html">
|
||||
* The Open Group Base Specifications Issue 7, sem_init()
|
||||
@ -56,9 +58,108 @@ extern "C" {
|
||||
* @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) sem_create(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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_destroy.html">
|
||||
* The Open Group Base Specifications Issue 7, sem_destroy()
|
||||
* </a>
|
||||
*
|
||||
* 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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_post.html">
|
||||
* The Open Group Base Specifications Issue 7, sem_post()
|
||||
* </a>
|
||||
*
|
||||
* 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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_wait.html">
|
||||
* The Open Group Base Specifications Issue 7, sem_wait()
|
||||
* </a>
|
||||
*
|
||||
* 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.
|
||||
@ -74,7 +175,13 @@ extern "C" {
|
||||
*
|
||||
* @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.
|
||||
@ -89,7 +196,12 @@ extern "C" {
|
||||
*
|
||||
* @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.
|
||||
@ -104,7 +216,12 @@ extern "C" {
|
||||
*
|
||||
* @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.
|
||||
@ -123,15 +240,13 @@ extern "C" {
|
||||
* 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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html">
|
||||
* The Open Group Base Specifications Issue 7, sem_trywait()
|
||||
@ -139,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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html">
|
||||
* The Open Group Base Specifications Issue 7, sem_getvalue()
|
||||
@ -155,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)
|
||||
{
|
||||
@ -164,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
|
||||
|
||||
@ -21,11 +21,11 @@
|
||||
|
||||
#include "irq.h"
|
||||
#include "sched.h"
|
||||
#include "sem.h"
|
||||
#include "sema.h"
|
||||
#include "tcb.h"
|
||||
#include "timex.h"
|
||||
#include "thread.h"
|
||||
#include "vtimer.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
@ -34,19 +34,21 @@
|
||||
|
||||
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 -ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
timeout = timex_sub(timeout, now);
|
||||
res = sem_wait_timed(sem, &timeout);
|
||||
timeout = timeout - now;
|
||||
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 +57,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;
|
||||
|
||||
@ -22,9 +22,9 @@
|
||||
|
||||
#include "irq.h"
|
||||
#include "msg.h"
|
||||
#include "vtimer.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#include "sem.h"
|
||||
#include "sema.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
@ -33,55 +33,60 @@
|
||||
#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, uint64_t timeout, msg_t *msg)
|
||||
{
|
||||
if (sem == NULL) {
|
||||
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;
|
||||
vtimer_t timeout_timer;
|
||||
unsigned value;
|
||||
|
||||
unsigned value = sem->value;
|
||||
old_state = disableIRQ();
|
||||
value = sema->value;
|
||||
if (value != 0) {
|
||||
sem->value = value - 1;
|
||||
sema->value = value - 1;
|
||||
restoreIRQ(old_state);
|
||||
return 0;
|
||||
}
|
||||
@ -90,24 +95,20 @@ 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);
|
||||
}
|
||||
|
||||
restoreIRQ(old_state);
|
||||
msg_receive(msg);
|
||||
|
||||
if (timeout != NULL) {
|
||||
vtimer_remove(&timeout_timer); /* remove timer just to be sure */
|
||||
old_state = disableIRQ();
|
||||
if (timeout != 0) {
|
||||
xtimer_remove(&timeout_timer);
|
||||
}
|
||||
|
||||
if (msg->content.ptr != (void *) sem) {
|
||||
priority_queue_remove(&sema->queue, &n);
|
||||
restoreIRQ(old_state);
|
||||
if (msg->content.ptr != (void *)sema) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
@ -124,41 +125,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, uint64_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);
|
||||
@ -22,13 +22,14 @@
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#include "msg.h"
|
||||
#include "timex.h"
|
||||
#include "thread.h"
|
||||
#include "semaphore.h"
|
||||
#include "vtimer.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#define SEMAPHORE_MSG_QUEUE_SIZE (8)
|
||||
#define SEMAPHORE_TEST_THREADS (5)
|
||||
@ -46,7 +47,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 +55,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 +69,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 +89,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 +103,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 +111,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 +121,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 +142,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 +202,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");
|
||||
@ -236,30 +237,37 @@ 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) {
|
||||
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");
|
||||
sem_timedwait(&s1, &abs);
|
||||
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));
|
||||
if (sem_timedwait(&s1, &abs) != 0) {
|
||||
if (errno != ETIMEDOUT) {
|
||||
printf("error waiting: %d\n", errno);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
puts("first: timed out");
|
||||
}
|
||||
}
|
||||
printf("first: waited %s\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 %" PRIu64 " usec\n", stop);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
msg_init_queue(main_msg_queue, SEMAPHORE_MSG_QUEUE_SIZE);
|
||||
xtimer_init();
|
||||
puts("######################### TEST1:");
|
||||
test1();
|
||||
puts("######################### TEST2:");
|
||||
|
||||
@ -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")
|
||||
@ -89,7 +88,8 @@ 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(r"first: waited 1\.\d{6} s")
|
||||
term.expect_exact("first: timed out")
|
||||
term.expect(r"first: waited 1\d{6} usec")
|
||||
|
||||
if __name__ == "__main__":
|
||||
TERM = init()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user