Browse Source

posix: use sem module for semaphore implementation

cc430
Martine Lenders 8 years ago committed by Martine Lenders
parent
commit
de421cdf78
  1. 5
      Makefile.dep
  2. 3
      sys/Makefile
  3. 3
      sys/Makefile.include
  4. 177
      sys/posix/include/semaphore.h
  5. 159
      sys/posix/semaphore.c
  6. 3
      sys/posix/semaphore/Makefile
  7. 77
      sys/posix/semaphore/posix_semaphore.c
  8. 2
      tests/posix_semaphore/Makefile
  9. 1
      tests/posix_semaphore/main.c

5
Makefile.dep

@ -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

3
sys/Makefile

@ -1,3 +1,6 @@
ifneq (,$(filter posix_semaphore,$(USEMODULE)))
DIRS += posix/semaphore
endif
ifneq (,$(filter posix_sockets,$(USEMODULE)))
DIRS += posix/sockets
endif

3
sys/Makefile.include

@ -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

177
sys/posix/include/semaphore.h

@ -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. */
#define SEM_FAILED ((sem_t *) 0)
/**
* @brief Semaphore struct
* @brief Value returned if `sem_open' failed.
*/
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_FAILED ((sem_t *) 0)
/**
* @brief Initialize semaphore object SEM to VALUE.
* @brief Initialize semaphore.
*
* @param sem Semaphore to initialize
* @param pshared unused
* @param value Value to set
*/
int sem_init(sem_t *sem, int pshared, unsigned int value);
/**
* @brief Free resources associated with semaphore object SEM.
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html">
* The Open Group Base Specifications Issue 7, sem_init()
* </a>
*
* @param sem Semaphore to destroy
*/
int sem_destroy(sem_t *sem);
/*
* @brief Open a named semaphore NAME with open flags OFLAG.
* 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.
*
* @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
* @param oflag Flags to set
* @return 0 on success.
* @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
*/
int sem_close(sem_t *sem);
/**
* @brief Remove named semaphore NAME.
* @todo named semaphore are currently not supported
*
* @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 abstime Max time to wait for a post
* @param[in] name Name to unlink.
*
* @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);
/**
* @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>
*
*/
int sem_trywait(sem_t *sem);
/**
* @brief Post SEM.
* @param[in] sem Semaphore to try to wait on
*
* @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.
*
* @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_ */
/** @} */

159
sys/posix/semaphore.c

@ -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

@ -0,0 +1,3 @@
MODULE = posix_semaphore
include $(RIOTBASE)/Makefile.base

77
sys/posix/semaphore/posix_semaphore.c

@ -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;
}
/** @} */

2
tests/posix_semaphore/Makefile

@ -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
tests/posix_semaphore/main.c

@ -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…
Cancel
Save