mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #6155 from lebrush/sema-non-ipc
Semaphore implementation without IPC
This commit is contained in:
commit
2a05385560
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
@ -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" {
|
||||
@ -33,103 +36,89 @@ 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()).
|
||||
*
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @brief Wait for a semaphore being posted (without timeout).
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
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.
|
||||
* @pre `(sema != NULL)`
|
||||
*
|
||||
* @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).
|
||||
* @brief Wait for a semaphore being posted (without timeout).
|
||||
*
|
||||
* @pre `(sema != NULL)`
|
||||
*
|
||||
* @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 sema_wait(sema_t *sema)
|
||||
@ -137,13 +126,27 @@ static inline int sema_wait(sema_t *sema)
|
||||
return sema_wait_timed(sema, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test if the semaphore is posted
|
||||
*
|
||||
* @pre `(sema != NULL)`
|
||||
*
|
||||
* This is a non-blocking alternative to @ref sema_wait.
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -EAGAIN, if the semaphore is not posted.
|
||||
* @return -ECANCELED, if the semaphore was destroyed.
|
||||
*/
|
||||
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);
|
||||
@ -152,5 +155,5 @@ int sema_post(sema_t *sema);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SEM_H_ */
|
||||
#endif /* SEMA_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
|
||||
@ -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_
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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.
|
||||
|
@ -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
|
||||
@ -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>
|
||||
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
226
sys/sema/sema.c
226
sys/sema/sema.c
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2013-15 Freie Universität Berlin
|
||||
* Copyright (C) 2016 TriaGnoSys GmbH
|
||||
* 2013-15 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
|
||||
@ -11,169 +12,108 @@
|
||||
*
|
||||
* @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>
|
||||
* @author Víctor Ariño <victor.arino@zii.aero>
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "irq.h"
|
||||
#include "msg.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "sema.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#define MSG_SIGNAL (0x0501)
|
||||
#define MSG_TIMEOUT (0x0502)
|
||||
#define MSG_DESTROYED (0x0503)
|
||||
|
||||
int sema_create(sema_t *sema, unsigned int value)
|
||||
void sema_create(sema_t *sema, unsigned int value)
|
||||
{
|
||||
if (sema == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
assert(sema != NULL);
|
||||
|
||||
sema->value = value;
|
||||
/* waiters for the mutex */
|
||||
sema->queue.first = NULL;
|
||||
sema->state = SEMA_OK;
|
||||
mutex_init(&sema->mutex);
|
||||
if (value == 0) {
|
||||
mutex_lock(&sema->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void sema_destroy(sema_t *sema)
|
||||
{
|
||||
assert(sema != NULL);
|
||||
|
||||
sema->state = SEMA_DESTROY;
|
||||
mutex_unlock(&sema->mutex);
|
||||
}
|
||||
|
||||
int sema_try_wait(sema_t *sema)
|
||||
{
|
||||
assert(sema != NULL);
|
||||
|
||||
int ret = -ECANCELED;
|
||||
if (sema->state == SEMA_OK) {
|
||||
ret = -EAGAIN;
|
||||
unsigned old = irq_disable();
|
||||
if (sema->value > 0) {
|
||||
--sema->value;
|
||||
ret = 0;
|
||||
}
|
||||
irq_restore(old);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sema_wait_timed(sema_t *sema, uint64_t us)
|
||||
{
|
||||
assert(sema != NULL);
|
||||
|
||||
if (sema->state != SEMA_OK) {
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
unsigned old = irq_disable();
|
||||
if (sema->value == 0) {
|
||||
irq_restore(old);
|
||||
int timeout = xtimer_mutex_lock_timeout(&sema->mutex, us);
|
||||
|
||||
if (sema->state != SEMA_OK) {
|
||||
mutex_unlock(&sema->mutex);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
if (timeout) {
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
old = irq_disable();
|
||||
}
|
||||
|
||||
unsigned int value = --sema->value;
|
||||
irq_restore(old);
|
||||
|
||||
if (value > 0) {
|
||||
mutex_unlock(&sema->mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sema_destroy(sema_t *sema)
|
||||
{
|
||||
unsigned int old_state;
|
||||
priority_queue_node_t *next;
|
||||
|
||||
if (sema == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
old_state = irq_disable();
|
||||
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 = sema;
|
||||
msg_send_int(&msg, pid);
|
||||
}
|
||||
irq_restore(old_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sema_wait_timed_msg(sema_t *sema, uint64_t timeout, msg_t *msg)
|
||||
{
|
||||
unsigned old_state;
|
||||
msg_t timeout_msg;
|
||||
xtimer_t timeout_timer;
|
||||
|
||||
if (sema == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (timeout != 0) {
|
||||
old_state = irq_disable();
|
||||
timeout_timer.target = 0, timeout_timer.long_target = 0;
|
||||
timeout_msg.type = MSG_TIMEOUT;
|
||||
timeout_msg.content.ptr = 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);
|
||||
irq_restore(old_state);
|
||||
}
|
||||
while (1) {
|
||||
priority_queue_node_t n;
|
||||
unsigned value;
|
||||
|
||||
old_state = irq_disable();
|
||||
value = sema->value;
|
||||
if (value != 0) {
|
||||
sema->value = value - 1;
|
||||
irq_restore(old_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* I'm going blocked */
|
||||
n.priority = (uint32_t)sched_active_thread->priority;
|
||||
n.data = (unsigned int)sched_active_pid;
|
||||
n.next = NULL;
|
||||
priority_queue_add(&sema->queue, &n);
|
||||
|
||||
DEBUG("sema_wait: %" PRIkernel_pid ": Adding node to semaphore queue: prio: %" PRIu32 "\n",
|
||||
sched_active_thread->pid, sched_active_thread->priority);
|
||||
|
||||
irq_restore(old_state);
|
||||
msg_receive(msg);
|
||||
old_state = irq_disable();
|
||||
if (timeout != 0) {
|
||||
xtimer_remove(&timeout_timer);
|
||||
}
|
||||
priority_queue_remove(&sema->queue, &n);
|
||||
irq_restore(old_state);
|
||||
if (msg->content.ptr != sema) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
switch (msg->type) {
|
||||
case MSG_SIGNAL:
|
||||
continue;
|
||||
case MSG_TIMEOUT:
|
||||
return -ETIMEDOUT;
|
||||
case MSG_DESTROYED:
|
||||
return -ECANCELED;
|
||||
default:
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int sema_wait_timed(sema_t *sema, uint64_t timeout)
|
||||
{
|
||||
int result;
|
||||
|
||||
do {
|
||||
msg_t msg;
|
||||
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);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sema_post(sema_t *sema)
|
||||
{
|
||||
unsigned int old_state, value;
|
||||
priority_queue_node_t *next;
|
||||
assert(sema != NULL);
|
||||
|
||||
if (sema == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
old_state = irq_disable();
|
||||
value = sema->value;
|
||||
if (value == UINT_MAX) {
|
||||
irq_restore(old_state);
|
||||
unsigned old = irq_disable();
|
||||
if (sema->value == UINT_MAX) {
|
||||
irq_restore(old);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
++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("sema_post: %" PRIkernel_pid ": waking up %" PRIkernel_pid "\n",
|
||||
sched_active_thread->pid, next_process->pid);
|
||||
msg.type = MSG_SIGNAL;
|
||||
msg.content.ptr = sema;
|
||||
msg_send_int(&msg, pid);
|
||||
irq_restore(old_state);
|
||||
sched_switch(prio);
|
||||
}
|
||||
else {
|
||||
irq_restore(old_state);
|
||||
|
||||
unsigned value = sema->value++;
|
||||
irq_restore(old);
|
||||
|
||||
if (value == 0) {
|
||||
mutex_unlock(&sema->mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
Loading…
Reference in New Issue
Block a user