Skip to content
Snippets Groups Projects
Commit de421cdf authored by Martine Lenders's avatar Martine Lenders
Browse files

posix: use sem module for semaphore implementation

parent 3ad92843
No related branches found
No related tags found
No related merge requests found
...@@ -301,6 +301,11 @@ ifneq (,$(filter posix,$(USEMODULE))) ...@@ -301,6 +301,11 @@ ifneq (,$(filter posix,$(USEMODULE)))
USEMODULE += vtimer USEMODULE += vtimer
endif endif
ifneq (,$(filter posix_semaphore,$(USEMODULE)))
USEMODULE += sem
USEMODULE += vtimer
endif
ifneq (,$(filter sem,$(USEMODULE))) ifneq (,$(filter sem,$(USEMODULE)))
USEMODULE += vtimer USEMODULE += vtimer
endif endif
......
ifneq (,$(filter posix_semaphore,$(USEMODULE)))
DIRS += posix/semaphore
endif
ifneq (,$(filter posix_sockets,$(USEMODULE))) ifneq (,$(filter posix_sockets,$(USEMODULE)))
DIRS += posix/sockets DIRS += posix/sockets
endif endif
......
...@@ -18,6 +18,9 @@ ifneq (,$(filter posix,$(USEMODULE))) ...@@ -18,6 +18,9 @@ ifneq (,$(filter posix,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif endif
ifneq (,$(filter posix_semaphore,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
endif
ifneq (,$(filter posix_sockets,$(USEMODULE))) ifneq (,$(filter posix_sockets,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
endif endif
......
...@@ -6,117 +6,170 @@ ...@@ -6,117 +6,170 @@
* directory for more details. * 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 <time.h>
#include "priority_queue.h" #include "sem.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/** Value returned if `sem_open' failed. */
#define SEM_FAILED ((sem_t *) 0)
/** /**
* @brief Semaphore struct * @brief Value returned if `sem_open' failed.
*/ */
typedef struct sem { #define SEM_FAILED ((sem_t *) 0)
/** the value of the semaphore */
volatile unsigned int value;
/** list of threads waiting for the semaphore */
priority_queue_t queue;
} sem_t;
/** /**
* @brief Initialize semaphore object SEM to VALUE. * @brief Initialize semaphore.
* *
* @param sem Semaphore to initialize * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html">
* @param pshared unused * The Open Group Base Specifications Issue 7, sem_init()
* @param value Value to set * </a>
*/
int sem_init(sem_t *sem, int pshared, unsigned int value);
/**
* @brief Free resources associated with semaphore object SEM.
* *
* @param sem Semaphore to destroy * 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(),
int sem_destroy(sem_t *sem); * 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.
* @brief Open a named semaphore NAME with open flags OFLAG.
* *
* @brief WARNING: named semaphore are currently not supported * @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.
* *
* @param name Name to set * @return 0 on success.
* @param oflag Flags to set * @return -EINVAL, if semaphore is invalid.
*/ */
sem_t *sem_open(const char *name, int oflag, ...); #define sem_init(sem, pshared, value) sem_create(sem, value)
/** /**
* @brief Close descriptor for named semaphore SEM. * @brief Open a named semaphore @p name with open flags @p oflag.
* *
* @brief WARNING: named semaphore are currently not supported * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_open.html">
* The Open Group Base Specifications Issue 7, sem_open()
* </a>
* *
* @param sem Semaphore to close * @todo named semaphore are currently not supported
*/
int sem_close(sem_t *sem);
/**
* @brief Remove named semaphore NAME.
* *
* @brief WARNING: named semaphore are currently not supported * @param[in] name Name to set.
* @param[in] oflag Flags to set.
* *
* @param name Name to unlink * @return Always @ref SEM_FAILED, since it is not implemented currently.
*/ */
int sem_unlink(const char *name); #define sem_open(name, oflag, ...) (SEM_FAILED)
/** /**
* @brief Wait for SEM being posted. * @brief Close descriptor for named semaphore @p sem.
* *
* @param sem Semaphore to wait * @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_wait(sem_t *sem); #define sem_close(sem) (-1)
/** /**
* @brief Similar to `sem_wait' but wait only until ABSTIME. * @brief Remove named semaphore @p name.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_unlink.html">
* The Open Group Base Specifications Issue 7, sem_unlink()
* </a>
* *
* @brief WARNING: currently not supported * @todo named semaphore are currently not supported
* *
* @param sem Semaphore to wait on * @param[in] name Name to unlink.
* @param abstime Max time to wait for a post
* *
* @return Always -1, since it is not implemented currently.
*/
#define sem_unlink(name) (-1)
/**
* @brief Similar to `sem_wait' but wait only until @p abstime.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_timedwait.html">
* The Open Group Base Specifications Issue 7, sem_timedwait()
* </a>
*
* 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[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); int sem_timedwait(sem_t *sem, const struct timespec *abstime);
/** /**
* @brief Test whether SEM is posted. * @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
int sem_trywait(sem_t *sem);
/**
* @brief Post SEM.
* *
* @param sem Semaphore to post on * @return 0 on success
* @return -EINVAL, if semaphore is invalid.
* @return -EAGAIN, if the semaphore was already locked.
*/ */
int sem_post(sem_t *sem); int sem_trywait(sem_t *sem);
/** /**
* @brief Get current value of SEM and store it in *SVAL. * @brief Get current value of SEM and store it in *SVAL.
* *
* @param sem Semaphore to get value from * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html">
* @param sval place whre value goes to * 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 #ifdef __cplusplus
} }
#endif #endif
#endif /* semaphore.h */ #endif /* POSIX_SEMAPHORE_H_ */
/** @} */
/**
* 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;
}
MODULE = posix_semaphore
include $(RIOTBASE)/Makefile.base
/*
* 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 ...@@ -4,7 +4,7 @@ include ../Makefile.tests_common
BOARD_INSUFFICIENT_MEMORY := msb-430 msb-430h mbed_lpc1768 chronos stm32f0discovery \ BOARD_INSUFFICIENT_MEMORY := msb-430 msb-430h mbed_lpc1768 chronos stm32f0discovery \
pca10000 pca10005 weio yunjia-nrf51822 nrf6310 spark-core pca10000 pca10005 weio yunjia-nrf51822 nrf6310 spark-core
USEMODULE += posix USEMODULE += posix_semaphore
DISABLE_MODULE += auto_init DISABLE_MODULE += auto_init
......
/* /*
* Copyright (C) 2013 Christian Mehlis <mehlis@inf.fu-berlin.de> * Copyright (C) 2013 Christian Mehlis <mehlis@inf.fu-berlin.de>
* Copyright (C) 2013 René Kijewski <rene.kijewski@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 * 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 * General Public License v2.1. See the file LICENSE in the top level
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment