From de9207a6b2b3e78e3754799908159bc669f619a8 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 26 Nov 2013 09:17:59 +0100 Subject: [PATCH] add semaphore, which does not base busy-waiting --- include/eduos/semaphore.h | 176 ++++++++++++++++++++++++++++++++ include/eduos/semaphore_types.h | 62 +++++++++++ 2 files changed, 238 insertions(+) create mode 100644 include/eduos/semaphore.h create mode 100644 include/eduos/semaphore_types.h diff --git a/include/eduos/semaphore.h b/include/eduos/semaphore.h new file mode 100644 index 0000000..b0f9e7d --- /dev/null +++ b/include/eduos/semaphore.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @author Stefan Lankes + * @file include/eduos/semaphore.h + * @brief semaphore functions definition + */ + +#ifndef __SEMAPHORE_H__ +#define __SEMAPHORE_H__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Semaphore initialization + * + * Always init semaphores before use! + * + * @param s Pointer to semaphore structure to initialize + * @param v Resource count + * + * @return + * - 0 on success + * - -EINVAL on invalid argument + */ +inline static int sem_init(sem_t* s, unsigned int v) { + unsigned int i; + + if (BUILTIN_EXPECT(!s, 0)) + return -EINVAL; + + s->value = v; + s->pos = 0; + for(i=0; iqueue[i] = MAX_TASKS; + spinlock_init(&s->lock); + + return 0; +} + +/** @brief Destroy semaphore + * @return + * - 0 on success + * - -EINVAL on invalid argument + */ +inline static int sem_destroy(sem_t* s) { + if (BUILTIN_EXPECT(!s, 0)) + return -EINVAL; + + spinlock_destroy(&s->lock); + + return 0; +} + +/** @brief Nonblocking trywait for sempahore + * + * Will return immediately if not available + * + * @return + * - 0 on success (You got the semaphore) + * - -EINVAL on invalid argument + * - -ECANCELED on failure (You still have to wait) + */ +inline static int sem_trywait(sem_t* s) { + int ret = -ECANCELED; + + if (BUILTIN_EXPECT(!s, 0)) + return -EINVAL; + + spinlock_lock(&s->lock); + if (s->value > 0) { + s->value--; + ret = 0; + } + spinlock_unlock(&s->lock); + + return ret; +} + +/** @brief Blocking wait for semaphore + * + * @param s Address of the according sem_t structure + * @return + * - 0 on success + * - -EINVAL on invalid argument + * - -ETIME on timer expired + */ +inline static int sem_wait(sem_t* s) { + if (BUILTIN_EXPECT(!s, 0)) + return -EINVAL; + +next_try1: + spinlock_lock(&s->lock); + if (s->value > 0) { + s->value--; + spinlock_unlock(&s->lock); + } else { + s->queue[s->pos] = current_task->id; + s->pos = (s->pos + 1) % MAX_TASKS; + block_current_task(); + spinlock_unlock(&s->lock); + reschedule(); + goto next_try1; + } + + return 0; +} + +/** @brief Give back resource + * @return + * - 0 on success + * - -EINVAL on invalid argument + */ +inline static int sem_post(sem_t* s) { + if (BUILTIN_EXPECT(!s, 0)) + return -EINVAL; + + spinlock_lock(&s->lock); + if (s->value > 0) { + s->value++; + spinlock_unlock(&s->lock); + } else { + unsigned int k, i; + + s->value++; + i = s->pos; + for(k=0; kqueue[i] < MAX_TASKS) { + wakeup_task(s->queue[i]); + s->queue[i] = MAX_TASKS; + break; + } + i = (i + 1) % MAX_TASKS; + } + spinlock_unlock(&s->lock); + } + + return 0; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/eduos/semaphore_types.h b/include/eduos/semaphore_types.h new file mode 100644 index 0000000..a8c0165 --- /dev/null +++ b/include/eduos/semaphore_types.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @author Stefan Lankes + * @file include/eduos/semaphore_types.h + * @brief semaphore type definition + */ + +#ifndef __SEMAPHORE_TYPES_H__ +#define __SEMAPHORE_TYPES_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Semaphore structure */ +typedef struct { + /// Resource available count + unsigned int value; + /// Queue of waiting tasks + tid_t queue[MAX_TASKS]; + /// Position in queue + unsigned int pos; + /// Access lock + spinlock_t lock; +} sem_t; + +/// Macro for initialization of semaphore +#define SEM_INIT(v) {v, {[0 ... MAX_TASKS-1] = MAX_TASKS}, 0, SPINLOCK_INIT} + +#ifdef __cplusplus +} +#endif + +#endif