Skip to content

Commit

Permalink
Merge pull request #6155 from lebrush/sema-non-ipc
Browse files Browse the repository at this point in the history
Semaphore implementation without IPC
  • Loading branch information
miri64 committed Jan 19, 2017
2 parents b9b6e49 + 49adbf2 commit 2a05385
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 218 deletions.
1 change: 1 addition & 0 deletions pkg/lwip/contrib/sock/lwip_sock.c
Expand Up @@ -19,6 +19,7 @@
#include "net/ipv4/addr.h"
#include "net/ipv6/addr.h"
#include "net/sock.h"
#include "timex.h"

#include "lwip/err.h"
#include "lwip/ip.h"
Expand Down
4 changes: 1 addition & 3 deletions pkg/lwip/contrib/sys_arch.c
Expand Up @@ -59,9 +59,7 @@ void sys_mutex_free(sys_mutex_t *mutex)

err_t sys_sem_new(sys_sem_t *sem, u8_t count)
{
if (sema_create((sema_t *)sem, (unsigned int)count) < 0) {
return ERR_VAL;
}
sema_create((sema_t *)sem, (unsigned int)count);
return ERR_OK;
}

Expand Down
105 changes: 54 additions & 51 deletions sys/include/sema.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
* Copyright (C) 2016 TriaGnoSys GmbH
* 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
Expand All @@ -18,13 +19,15 @@
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author Christian Mehlis <mehlis@inf.fu-berlin.de>
* @author René Kijewski <kijewski@inf.fu-berlin.de>
* @author Víctor Ariño <victor.arino@zii.aero>
*/
#ifndef SEM_H_
#define SEM_H_

#include "msg.h"
#include "priority_queue.h"
#include "timex.h"
#ifndef SEMA_H
#define SEMA_H

#include <stdint.h>

#include "mutex.h"

#ifdef __cplusplus
extern "C" {
Expand All @@ -33,117 +36,117 @@ extern "C" {
/**
* @brief Creates semaphore statically.
*
* @param[in] value Initial value for the semaphore.
* @param[in] value Initial value for the semaphore (can't be 0). For a 0
* initialized semaphore @see SEMA_CREATE_LOCKED
*
* @return Statically initialized semaphore.
*/
#define SEMA_CREATE(value) { (value), PRIORITY_QUEUE_INIT }
#define SEMA_CREATE(value) { (value), SEMA_OK, MUTEX_INIT }

/**
* @brief Creates semaphore statically initialized to 0
* @return Statically initialized semaphore.
*/
#define SEMA_CREATE_LOCKED() { (0), SEMA_OK, MUTEX_INIT_LOCKED }

/**
* @brief A Semaphore states.
*/
typedef enum {
SEMA_OK = 0,
SEMA_DESTROY,
} sema_state_t;

/**
* @brief A Semaphore.
*/
typedef struct {
volatile unsigned int value; /**< value of the semaphore */
priority_queue_t queue; /**< list of threads waiting for the semaphore */
unsigned int value; /**< value of the semaphore */
sema_state_t state; /**< state of the semaphore */
mutex_t mutex; /**< mutex of the semaphore */
} sema_t;

/**
* @brief Creates semaphore dynamically.
*
* @pre `(sema != NULL)`
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html">
* The Open Group Base Specifications Issue 7, sem_init()
* </a> (without `pshared` parameter)
*
* @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 sema_create(sema_t *sema, unsigned int value);
void sema_create(sema_t *sema, unsigned int value);

/**
* @brief Destroys a semaphore.
*
* @pre `(sema != NULL)`
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_destroy.html">
* The Open Group Base Specifications Issue 7, sem_destroy()
* </a>
*
* @param[in] sema The semaphore to destroy.
* Destroying a semaphore upon which other threads are currently blocked
* will wake the other threads causing the @ref sema_wait (or
* @ref sema_wait_timed) to return error (-ECANCELLED).
*
* @return 0 on success.
* @return -EINVAL, if semaphore is invalid.
* @param[in] sema The semaphore to destroy.
*/
int sema_destroy(sema_t *sema);
void 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()).
* @pre `(sema != NULL)`
*
* @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
* @return -EINVAL, if semaphore is invalid.
* @return -ETIMEDOUT, if the semaphore times out.
* @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, uint64_t timeout, msg_t *msg);
int sema_wait_timed(sema_t *sema, uint64_t timeout);

/**
* @brief Wait for a semaphore being posted (without timeout).
*
* @pre `(sema != NULL)`
*
* @param[in] sema A semaphore.
* @param[out] msg Container for a spurious message during the timed wait (result == -EAGAIN).
*
* @return 0 on success
* @return -EINVAL, if semaphore is invalid.
* @return -ECANCELED, if the semaphore was destroyed.
* @return -EAGAIN, if the thread received a message while waiting for the lock.
*/
static inline int sema_wait_msg(sema_t *sema, msg_t *msg)
static inline int sema_wait(sema_t *sema)
{
return sema_wait_timed_msg(sema, 0, msg);
return sema_wait_timed(sema, 0);
}

/**
* @brief Wait for a semaphore being posted (dropping spurious messages).
* @details Any spurious messages received while waiting for the semaphore are silently dropped.
* @brief Test if the semaphore is posted
*
* @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 sema_wait_timed(sema_t *sema, uint64_t timeout);

/**
* @brief Wait for a semaphore being posted (without timeout, dropping spurious messages).
* @pre `(sema != NULL)`
*
* @param[in] sema A semaphore.
* This is a non-blocking alternative to @ref sema_wait.
*
* @return 0 on success
* @return -EINVAL, if semaphore is invalid.
* @return 0 on success
* @return -EAGAIN, if the semaphore is not posted.
* @return -ECANCELED, if the semaphore was destroyed.
*/
static inline int sema_wait(sema_t *sema)
{
return sema_wait_timed(sema, 0);
}
int sema_try_wait(sema_t *sema);

/**
* @brief Signal semaphore.
*
* @pre `(sema != NULL)`
*
* @param[in] sema A semaphore.
*
* @return 0, on success
* @return -EINVAL, if semaphore is invalid.
* @return -EOVERFLOW, if the semaphore's value would overflow.
*/
int sema_post(sema_t *sema);
Expand All @@ -152,5 +155,5 @@ int sema_post(sema_t *sema);
}
#endif

#endif /* SEM_H_ */
#endif /* SEMA_H */
/** @} */
29 changes: 17 additions & 12 deletions sys/posix/include/semaphore.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 Freie Universität Berlin
* Copyright (C) 2017 TriaGnoSys GmbH
* 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
Expand All @@ -18,6 +19,7 @@
* @author Christian Mehlis <mehlis@inf.fu-berlin.de>
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author René Kijewski <kijewski@inf.fu-berlin.de>
* @author Víctor Ariño <victor.arino@zii.aero>
*/

#ifndef POSIX_SEMAPHORE_H_
Expand Down Expand Up @@ -62,12 +64,8 @@ typedef sema_t sem_t;
*/
static inline int sem_init(sem_t *sem, int pshared, unsigned value)
{
int res = sema_create((sema_t *)sem, value);
sema_create((sema_t *)sem, value);
(void)pshared;
if (res < 0) {
errno = -res;
return -1;
}
return 0;
}

Expand All @@ -94,11 +92,7 @@ static inline int sem_init(sem_t *sem, int pshared, unsigned value)
*/
static inline int sem_destroy(sem_t *sem)
{
int res = sema_destroy((sema_t *)sem);
if (res < 0) {
errno = -res;
return -1;
}
sema_destroy((sema_t *)sem);
return 0;
}

Expand Down Expand Up @@ -127,6 +121,7 @@ static inline int sem_destroy(sem_t *sem)
static inline int sem_post(sem_t *sem)
{
int res = sema_post((sema_t *)sem);

if (res < 0) {
errno = -res;
return -1;
Expand Down Expand Up @@ -154,6 +149,7 @@ static inline int sem_post(sem_t *sem)
static inline int sem_wait(sem_t *sem)
{
int res = sema_wait((sema_t *)sem);

if (res < 0) {
errno = -res;
return -1;
Expand Down Expand Up @@ -257,7 +253,16 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime);
* @return 0 on success.
* @return -1, on error and errno set to indicate the error.
*/
int sem_trywait(sem_t *sem);
static inline int sem_trywait(sem_t *sem)
{
int res = sema_try_wait((sema_t *)sem);

if (res < 0) {
errno = -res;
return -1;
}
return 0;
}

/**
* @brief Get current value of @p sem and store it in @p sval.
Expand Down
30 changes: 5 additions & 25 deletions sys/posix/semaphore/posix_semaphore.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 Freie Universität Berlin
* Copyright (C) 2017 TriaGnoSys GmbH
* 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
Expand All @@ -14,6 +15,7 @@
* @author Christian Mehlis <mehlis@inf.fu-berlin.de>
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author René Kijewski <kijewski@inf.fu-berlin.de>
* @author Víctor Ariño <victor.arino@zii.aero>
*/

#include <errno.h>
Expand All @@ -34,8 +36,9 @@
int sem_timedwait(sem_t *sem, const struct timespec *abstime)
{
uint64_t timeout = (((uint64_t)abstime->tv_sec) * SEC_IN_USEC) +
(abstime->tv_nsec / USEC_IN_NS);
(abstime->tv_nsec / USEC_IN_NS);
uint64_t now = xtimer_now_usec64();

if (now > timeout) {
errno = ETIMEDOUT;
return -1;
Expand All @@ -49,27 +52,4 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime)
return 0;
}

int sem_trywait(sem_t *sem)
{
unsigned int old_state, value;
int result;
if (sem == NULL) {
errno = EINVAL;
return -1;
}
old_state = irq_disable();
value = sem->value;
if (value == 0) {
errno = EAGAIN;
result = -1;
}
else {
result = 0;
sem->value = value - 1;
}

irq_restore(old_state);
return result;
}

/** @} */

0 comments on commit 2a05385

Please sign in to comment.