mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
posix: use sem module for semaphore implementation
This commit is contained in:
parent
3ad9284357
commit
de421cdf78
@ -301,6 +301,11 @@ ifneq (,$(filter posix,$(USEMODULE)))
|
||||
USEMODULE += vtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter posix_semaphore,$(USEMODULE)))
|
||||
USEMODULE += sem
|
||||
USEMODULE += vtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter sem,$(USEMODULE)))
|
||||
USEMODULE += vtimer
|
||||
endif
|
||||
|
@ -1,3 +1,6 @@
|
||||
ifneq (,$(filter posix_semaphore,$(USEMODULE)))
|
||||
DIRS += posix/semaphore
|
||||
endif
|
||||
ifneq (,$(filter posix_sockets,$(USEMODULE)))
|
||||
DIRS += posix/sockets
|
||||
endif
|
||||
|
@ -18,6 +18,9 @@ ifneq (,$(filter posix,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
|
||||
endif
|
||||
ifneq (,$(filter posix_semaphore,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
|
||||
endif
|
||||
ifneq (,$(filter posix_sockets,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
|
||||
endif
|
||||
|
@ -6,117 +6,170 @@
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#ifndef _SEMAPHORE_H
|
||||
#define _SEMAPHORE_H 1
|
||||
/**
|
||||
* @defgroup posix_semaphore POSIX semaphores
|
||||
* @ingroup posix
|
||||
* @{
|
||||
* @file
|
||||
* @brief Semaphores
|
||||
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/semaphore.h.html">
|
||||
* The Open Group Base Specifications Issue 7, <semaphore.h>
|
||||
* </a>
|
||||
* @author Christian Mehlis <mehlis@inf.fu-berlin.de>
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* @author René Kijewski <kijewski@inf.fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef POSIX_SEMAPHORE_H_
|
||||
#define POSIX_SEMAPHORE_H_
|
||||
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "priority_queue.h"
|
||||
#include "sem.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Value returned if `sem_open' failed. */
|
||||
/**
|
||||
* @brief Value returned if `sem_open' failed.
|
||||
*/
|
||||
#define SEM_FAILED ((sem_t *) 0)
|
||||
|
||||
/**
|
||||
* @brief Semaphore struct
|
||||
* @brief Initialize semaphore.
|
||||
*
|
||||
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html">
|
||||
* The Open Group Base Specifications Issue 7, sem_init()
|
||||
* </a>
|
||||
*
|
||||
* The sem_init() function shall initialize the unnamed semaphore referred to by @p sem. The value
|
||||
* of the initialized semaphore shall be @p value. Following a successful call to sem_init(),
|
||||
* the semaphore may be used in subsequent calls to sem_wait(), sem_timedwait(),
|
||||
* sem_trywait(), sem_post(), and sem_destroy(). This semaphore shall remain usable until the
|
||||
* semaphore is destroyed.
|
||||
*
|
||||
* @param[out] sem Semaphore to initialize.
|
||||
* @param[in] pshared **(unused, since RIOT only has threads)**
|
||||
* Semaphore is shared between processes not threads.
|
||||
* @param[in] value Value to set.
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return -EINVAL, if semaphore is invalid.
|
||||
*/
|
||||
typedef struct sem {
|
||||
/** the value of the semaphore */
|
||||
volatile unsigned int value;
|
||||
/** list of threads waiting for the semaphore */
|
||||
priority_queue_t queue;
|
||||
} sem_t;
|
||||
#define sem_init(sem, pshared, value) sem_create(sem, value)
|
||||
|
||||
/**
|
||||
* @brief Initialize semaphore object SEM to VALUE.
|
||||
* @brief Open a named semaphore @p name with open flags @p oflag.
|
||||
*
|
||||
* @param sem Semaphore to initialize
|
||||
* @param pshared unused
|
||||
* @param value Value to set
|
||||
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_open.html">
|
||||
* The Open Group Base Specifications Issue 7, sem_open()
|
||||
* </a>
|
||||
*
|
||||
* @todo named semaphore are currently not supported
|
||||
*
|
||||
* @param[in] name Name to set.
|
||||
* @param[in] oflag Flags to set.
|
||||
*
|
||||
* @return Always @ref SEM_FAILED, since it is not implemented currently.
|
||||
*/
|
||||
int sem_init(sem_t *sem, int pshared, unsigned int value);
|
||||
#define sem_open(name, oflag, ...) (SEM_FAILED)
|
||||
|
||||
/**
|
||||
* @brief Free resources associated with semaphore object SEM.
|
||||
* @brief Close descriptor for named semaphore @p sem.
|
||||
*
|
||||
* @param sem Semaphore to destroy
|
||||
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_close.html">
|
||||
* The Open Group Base Specifications Issue 7, sem_close()
|
||||
* </a>
|
||||
*
|
||||
* @todo named semaphore are currently not supported
|
||||
*
|
||||
* @param[in] sem Semaphore to close.
|
||||
*
|
||||
* @return Always -1, since it is not implemented currently.
|
||||
*/
|
||||
int sem_destroy(sem_t *sem);
|
||||
|
||||
/*
|
||||
* @brief Open a named semaphore NAME with open flags OFLAG.
|
||||
*
|
||||
* @brief WARNING: named semaphore are currently not supported
|
||||
*
|
||||
* @param name Name to set
|
||||
* @param oflag Flags to set
|
||||
*/
|
||||
sem_t *sem_open(const char *name, int oflag, ...);
|
||||
#define sem_close(sem) (-1)
|
||||
|
||||
/**
|
||||
* @brief Close descriptor for named semaphore SEM.
|
||||
* @brief Remove named semaphore @p name.
|
||||
*
|
||||
* @brief WARNING: named semaphore are currently not supported
|
||||
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_unlink.html">
|
||||
* The Open Group Base Specifications Issue 7, sem_unlink()
|
||||
* </a>
|
||||
*
|
||||
* @param sem Semaphore to close
|
||||
* @todo named semaphore are currently not supported
|
||||
*
|
||||
* @param[in] name Name to unlink.
|
||||
*
|
||||
* @return Always -1, since it is not implemented currently.
|
||||
*/
|
||||
int sem_close(sem_t *sem);
|
||||
#define sem_unlink(name) (-1)
|
||||
|
||||
/**
|
||||
* @brief Remove named semaphore NAME.
|
||||
* @brief Similar to `sem_wait' but wait only until @p abstime.
|
||||
*
|
||||
* @brief WARNING: named semaphore are currently not supported
|
||||
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_timedwait.html">
|
||||
* The Open Group Base Specifications Issue 7, sem_timedwait()
|
||||
* </a>
|
||||
*
|
||||
* @param name Name to unlink
|
||||
*/
|
||||
int sem_unlink(const char *name);
|
||||
|
||||
/**
|
||||
* @brief Wait for SEM being posted.
|
||||
* The sem_timedwait() function shall lock the semaphore referenced by @p sem as in the sem_wait()
|
||||
* function. However, if the semaphore cannot be locked without waiting for another process or
|
||||
* thread to unlock the semaphore by performing a sem_post() function, this wait shall be
|
||||
* terminated when the specified timeout expires.
|
||||
*
|
||||
* @param sem Semaphore to wait
|
||||
*/
|
||||
int sem_wait(sem_t *sem);
|
||||
|
||||
/**
|
||||
* @brief Similar to `sem_wait' but wait only until ABSTIME.
|
||||
*
|
||||
* @brief WARNING: currently not supported
|
||||
*
|
||||
* @param sem Semaphore to wait on
|
||||
* @param abstime Max time to wait for a post
|
||||
* @param[in] sem Semaphore to wait on.
|
||||
* @param[in] abstime Absolute time (that is when the clock on which temouts are based equals
|
||||
* 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.
|
||||
*/
|
||||
int sem_timedwait(sem_t *sem, const struct timespec *abstime);
|
||||
|
||||
/**
|
||||
* @brief Test whether SEM is posted.
|
||||
*
|
||||
* @param sem Semaphore to trywait on
|
||||
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html">
|
||||
* The Open Group Base Specifications Issue 7, sem_trywait()
|
||||
* </a>
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
int sem_trywait(sem_t *sem);
|
||||
|
||||
/**
|
||||
* @brief Post SEM.
|
||||
*
|
||||
* @param sem Semaphore to post on
|
||||
*/
|
||||
int sem_post(sem_t *sem);
|
||||
|
||||
/**
|
||||
* @brief Get current value of SEM and store it in *SVAL.
|
||||
*
|
||||
* @param sem Semaphore to get value from
|
||||
* @param sval place whre value goes to
|
||||
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html">
|
||||
* The Open Group Base Specifications Issue 7, sem_getvalue()
|
||||
* </a>
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
int sem_getvalue(sem_t *sem, int *sval);
|
||||
static inline int sem_getvalue(sem_t *sem, int *sval)
|
||||
{
|
||||
if (sem != NULL) {
|
||||
*sval = (int)sem->value;
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* semaphore.h */
|
||||
#endif /* POSIX_SEMAPHORE_H_ */
|
||||
/** @} */
|
||||
|
@ -1,159 +0,0 @@
|
||||
/**
|
||||
* Semaphore implemenation
|
||||
*
|
||||
* Copyright (C) 2013 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*
|
||||
* @ingroup posix
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of semaphores with priority queues
|
||||
*
|
||||
* @author Christian Mehlis <mehlis@inf.fu-berlin.de>
|
||||
* @author René Kijewski <kijewski@inf.fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "irq.h"
|
||||
#include "sched.h"
|
||||
#include "tcb.h"
|
||||
#include "thread.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#include "semaphore.h"
|
||||
|
||||
int sem_init(sem_t *sem, int pshared, unsigned int value)
|
||||
{
|
||||
(void) pshared; /* nothing to do */
|
||||
|
||||
sem->value = value;
|
||||
|
||||
/* waiters for the mutex */
|
||||
sem->queue.first = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sem_destroy(sem_t *sem)
|
||||
{
|
||||
if (sem->queue.first) {
|
||||
DEBUG("sem_destroy: %" PRIkernel_pid ": tried to destroy active semaphore.\n",
|
||||
sched_active_thread->pid);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sem_t *sem_open(const char *name, int oflag, ...)
|
||||
{
|
||||
(void) name; /* named semaphore currently not supported */
|
||||
(void) oflag;
|
||||
return SEM_FAILED;
|
||||
}
|
||||
|
||||
int sem_close(sem_t *sem)
|
||||
{
|
||||
(void) sem; /* named semaphore currently not supported */
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sem_unlink(const char *name)
|
||||
{
|
||||
(void) name; /* named semaphore currently not supported */
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sem_wait(sem_t *sem)
|
||||
{
|
||||
while (1) {
|
||||
unsigned old_state = disableIRQ();
|
||||
|
||||
unsigned value = sem->value;
|
||||
if (value != 0) {
|
||||
sem->value = value - 1;
|
||||
restoreIRQ(old_state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* I'm going blocked */
|
||||
priority_queue_node_t n;
|
||||
n.priority = (uint32_t) sched_active_thread->priority;
|
||||
n.data = (uintptr_t) sched_active_thread;
|
||||
n.next = NULL;
|
||||
priority_queue_add(&sem->queue, &n);
|
||||
|
||||
DEBUG("sem_wait: %" PRIkernel_pid ": Adding node to mutex queue: prio: %" PRIu32 "\n",
|
||||
sched_active_thread->pid, sched_active_thread->priority);
|
||||
|
||||
/* scheduler should schedule an other thread, that unlocks the
|
||||
* mutex in the future, when this happens I get scheduled again
|
||||
*/
|
||||
sched_set_status((tcb_t*) sched_active_thread, STATUS_MUTEX_BLOCKED);
|
||||
restoreIRQ(old_state);
|
||||
thread_yield_higher();
|
||||
}
|
||||
}
|
||||
|
||||
int sem_timedwait(sem_t *sem, const struct timespec *abstime)
|
||||
{
|
||||
(void) sem; /* timedwait currently not supported */
|
||||
(void) abstime;
|
||||
return -1; /* signal problem */
|
||||
}
|
||||
|
||||
int sem_trywait(sem_t *sem)
|
||||
{
|
||||
unsigned old_state = disableIRQ();
|
||||
int result;
|
||||
|
||||
unsigned value = sem->value;
|
||||
if (value == 0) {
|
||||
result = -1;
|
||||
}
|
||||
else {
|
||||
result = 0;
|
||||
sem->value = value - 1;
|
||||
}
|
||||
|
||||
restoreIRQ(old_state);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sem_post(sem_t *sem)
|
||||
{
|
||||
unsigned old_state = disableIRQ();
|
||||
++sem->value;
|
||||
|
||||
priority_queue_node_t *next = priority_queue_remove_head(&sem->queue);
|
||||
if (next) {
|
||||
tcb_t *next_process = (tcb_t*) next->data;
|
||||
DEBUG("sem_post: %" PRIkernel_pid ": waking up %" PRIkernel_pid "\n",
|
||||
sched_active_thread->pid, next_process->pid);
|
||||
sched_set_status(next_process, STATUS_PENDING);
|
||||
|
||||
uint16_t prio = next_process->priority;
|
||||
restoreIRQ(old_state);
|
||||
sched_switch(prio);
|
||||
}
|
||||
else {
|
||||
restoreIRQ(old_state);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sem_getvalue(sem_t *sem, int *sval)
|
||||
{
|
||||
*sval = sem->value;
|
||||
return 0;
|
||||
}
|
3
sys/posix/semaphore/Makefile
Normal file
3
sys/posix/semaphore/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = posix_semaphore
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
77
sys/posix/semaphore/posix_semaphore.c
Normal file
77
sys/posix/semaphore/posix_semaphore.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
*
|
||||
* @author Christian Mehlis <mehlis@inf.fu-berlin.de>
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* @author René Kijewski <kijewski@inf.fu-berlin.de>
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "irq.h"
|
||||
#include "sched.h"
|
||||
#include "sem.h"
|
||||
#include "tcb.h"
|
||||
#include "timex.h"
|
||||
#include "thread.h"
|
||||
#include "vtimer.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#include "semaphore.h"
|
||||
|
||||
#define USEC_IN_NS (1000)
|
||||
|
||||
int sem_timedwait(sem_t *sem, const struct timespec *abstime)
|
||||
{
|
||||
timex_t now, timeout = { abstime->tv_sec, abstime->tv_nsec / USEC_IN_NS };
|
||||
int res;
|
||||
vtimer_now(&now);
|
||||
if (timex_cmp(now, timeout) > 0) {
|
||||
errno = ETIMEDOUT;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
timeout = timex_sub(timeout, now);
|
||||
res = sem_wait_timed(sem, &timeout);
|
||||
if (res < 0) {
|
||||
errno = -res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int sem_trywait(sem_t *sem)
|
||||
{
|
||||
unsigned int old_state, value;
|
||||
int result;
|
||||
if (sem == NULL) {
|
||||
errno = EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
old_state = disableIRQ();
|
||||
value = sem->value;
|
||||
if (value == 0) {
|
||||
errno = EAGAIN;
|
||||
result = -EAGAIN;
|
||||
}
|
||||
else {
|
||||
result = 0;
|
||||
sem->value = value - 1;
|
||||
}
|
||||
|
||||
restoreIRQ(old_state);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @} */
|
@ -4,7 +4,7 @@ include ../Makefile.tests_common
|
||||
BOARD_INSUFFICIENT_MEMORY := msb-430 msb-430h mbed_lpc1768 chronos stm32f0discovery \
|
||||
pca10000 pca10005 weio yunjia-nrf51822 nrf6310 spark-core
|
||||
|
||||
USEMODULE += posix
|
||||
USEMODULE += posix_semaphore
|
||||
|
||||
DISABLE_MODULE += auto_init
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Christian Mehlis <mehlis@inf.fu-berlin.de>
|
||||
* Copyright (C) 2013 René Kijewski <rene.kijewski@fu-berlin.de>
|
||||
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
|
Loading…
Reference in New Issue
Block a user