diff --git a/hermit/include/hermit/mailbox.h b/hermit/include/hermit/mailbox.h new file mode 100644 index 000000000..713c6c1fe --- /dev/null +++ b/hermit/include/hermit/mailbox.h @@ -0,0 +1,142 @@ +/* + * 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. + */ + +#ifndef __MAILBOX_H__ +#define __MAILBOX_H__ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAILBOX(name, type) \ + inline static int mailbox_##name##_init(mailbox_##name##_t* m) { \ + if (BUILTIN_EXPECT(!m, 0)) \ + return -EINVAL; \ + \ + memset(m->buffer, 0x00, sizeof(type)*MAILBOX_SIZE); \ + m->wpos = m->rpos = 0; \ + sem_init(&m->mails, 0); \ + sem_init(&m->boxes, MAILBOX_SIZE); \ + spinlock_init(&m->rlock); \ + spinlock_init(&m->wlock); \ + \ + return 0; \ + }\ + \ + inline static int mailbox_##name##_destroy(mailbox_##name##_t* m) { \ + if (BUILTIN_EXPECT(!m, 0)) \ + return -EINVAL; \ + \ + sem_destroy(&m->mails); \ + sem_destroy(&m->boxes); \ + spinlock_destroy(&m->rlock); \ + spinlock_destroy(&m->wlock); \ + \ + return 0; \ + } \ + \ + inline static int mailbox_##name##_post(mailbox_##name##_t* m, type mail) { \ + if (BUILTIN_EXPECT(!m, 0)) \ + return -EINVAL; \ + \ + sem_wait(&m->boxes, 0); \ + spinlock_lock(&m->wlock); \ + m->buffer[m->wpos] = mail; \ + m->wpos = (m->wpos+1) % MAILBOX_SIZE; \ + spinlock_unlock(&m->wlock); \ + sem_post(&m->mails); \ + \ + return 0; \ + } \ + \ + inline static int mailbox_##name##_trypost(mailbox_##name##_t* m, type mail) { \ + if (BUILTIN_EXPECT(!m, 0)) \ + return -EINVAL; \ + \ + if (sem_trywait(&m->boxes)) \ + return -EBUSY; \ + spinlock_lock(&m->wlock); \ + m->buffer[m->wpos] = mail; \ + m->wpos = (m->wpos+1) % MAILBOX_SIZE; \ + spinlock_unlock(&m->wlock); \ + sem_post(&m->mails); \ + \ + return 0; \ + } \ + \ + inline static int mailbox_##name##_fetch(mailbox_##name##_t* m, type* mail, uint32_t ms) { \ + int err; \ + \ + if (BUILTIN_EXPECT(!m || !mail, 0)) \ + return -EINVAL; \ + \ + err = sem_wait(&m->mails, ms); \ + if (err) return err; \ + spinlock_lock(&m->rlock); \ + *mail = m->buffer[m->rpos]; \ + m->rpos = (m->rpos+1) % MAILBOX_SIZE; \ + spinlock_unlock(&m->rlock); \ + sem_post(&m->boxes); \ + \ + return 0; \ + } \ + \ + inline static int mailbox_##name##_tryfetch(mailbox_##name##_t* m, type* mail) { \ + if (BUILTIN_EXPECT(!m || !mail, 0)) \ + return -EINVAL; \ + \ + if (sem_trywait(&m->mails) != 0) \ + return -EINVAL; \ + spinlock_lock(&m->rlock); \ + *mail = m->buffer[m->rpos]; \ + m->rpos = (m->rpos+1) % MAILBOX_SIZE; \ + spinlock_unlock(&m->rlock); \ + sem_post(&m->boxes); \ + \ + return 0; \ + }\ + +MAILBOX(wait_msg, wait_msg_t) +MAILBOX(int32, int32_t) +MAILBOX(int16, int16_t) +MAILBOX(int8, int8_t) +MAILBOX(uint32, uint32_t) +MAILBOX(uint16, uint16_t) +MAILBOX(uint8, uint8_t) +MAILBOX(ptr, void*) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hermit/include/hermit/mailbox_types.h b/hermit/include/hermit/mailbox_types.h new file mode 100644 index 000000000..de18d1749 --- /dev/null +++ b/hermit/include/hermit/mailbox_types.h @@ -0,0 +1,75 @@ +/* + * 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/metalsvm/mailbox_types.h + * @brief Message type structure definitions for various task return types + */ + +#ifndef __MAILBOX_TYPES_H__ +#define __MAILBOX_TYPES_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Wait message structure + * + * This message struct keeps a recipient task id and the message itself */ +typedef struct { + /// The task id of the task which is waiting for this message + tid_t id; + /// The message payload + int32_t result; +} wait_msg_t; + +#define MAILBOX_TYPES(name, type) \ + typedef struct mailbox_##name { \ + type buffer[MAILBOX_SIZE]; \ + int wpos, rpos; \ + sem_t mails; \ + sem_t boxes; \ + spinlock_t rlock, wlock; \ + } mailbox_##name##_t; + +MAILBOX_TYPES(wait_msg, wait_msg_t) +MAILBOX_TYPES(int32, int32_t) +MAILBOX_TYPES(int16, int16_t) +MAILBOX_TYPES(int8, int8_t) +MAILBOX_TYPES(uint32, uint32_t) +MAILBOX_TYPES(uint16, uint16_t) +MAILBOX_TYPES(uint8, uint8_t) +MAILBOX_TYPES(ptr, void*) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hermit/include/hermit/semaphore.h b/hermit/include/hermit/semaphore.h new file mode 100644 index 000000000..4dc63f0ff --- /dev/null +++ b/hermit/include/hermit/semaphore.h @@ -0,0 +1,220 @@ +/* + * 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/hermit/semaphore.h + * @brief semaphore functions definition + */ + +#ifndef __SEMAPHORE_H__ +#define __SEMAPHORE_H__ + +#include +#include +#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_irqsave_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_irqsave_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_irqsave_lock(&s->lock); + if (s->value > 0) { + s->value--; + ret = 0; + } + spinlock_irqsave_unlock(&s->lock); + + return ret; +} + +/** @brief Blocking wait for semaphore + * + * @param s Address of the according sem_t structure + * @param ms Timeout in milliseconds + * @return + * - 0 on success + * - -EINVAL on invalid argument + * - -ETIME on timer expired + */ +inline static int sem_wait(sem_t* s, uint32_t ms) { + task_t* curr_task = per_core(current_task); + + if (BUILTIN_EXPECT(!s, 0)) + return -EINVAL; + + if (!ms) { +next_try1: + spinlock_irqsave_lock(&s->lock); + if (s->value > 0) { + s->value--; + spinlock_irqsave_unlock(&s->lock); + } else { + s->queue[s->pos] = curr_task->id; + s->pos = (s->pos + 1) % MAX_TASKS; + block_current_task(); + spinlock_irqsave_unlock(&s->lock); + reschedule(); + goto next_try1; + } + } else { + uint32_t ticks = (ms * TIMER_FREQ) / 1000; + uint32_t remain = (ms * TIMER_FREQ) % 1000; + + if (ticks) { + uint64_t deadline = get_clock_tick() + ticks; + +next_try2: + spinlock_irqsave_lock(&s->lock); + if (s->value > 0) { + s->value--; + spinlock_irqsave_unlock(&s->lock); + return 0; + } else { + if (get_clock_tick() >= deadline) { + spinlock_irqsave_unlock(&s->lock); + goto timeout; + } + s->queue[s->pos] = curr_task->id; + s->pos = (s->pos + 1) % MAX_TASKS; + set_timer(deadline); + spinlock_irqsave_unlock(&s->lock); + reschedule(); + goto next_try2; + } + } + +timeout: + while (remain) { + udelay(1000); + remain--; + + if (!sem_trywait(s)) + return 0; + } + + return -ETIME; + } + + 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_irqsave_lock(&s->lock); + if (s->value > 0) { + s->value++; + spinlock_irqsave_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_irqsave_unlock(&s->lock); + } + + return 0; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hermit/include/hermit/semaphore_types.h b/hermit/include/hermit/semaphore_types.h new file mode 100644 index 000000000..40dd199a3 --- /dev/null +++ b/hermit/include/hermit/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/hermit/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_irqsave_t lock; +} sem_t; + +/// Macro for initialization of semaphore +#define SEM_INIT(v) {v, {[0 ... MAX_TASKS-1] = MAX_TASKS}, 0, SPINLOCK_IRQSAVE_INIT} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hermit/include/stdarg.h b/hermit/include/stdarg.h new file mode 100644 index 000000000..ff2293b0b --- /dev/null +++ b/hermit/include/stdarg.h @@ -0,0 +1,16 @@ +#ifndef __ANSI_STDARG_H__ +#define __ANSI_STDARG_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define __VALIST va_list + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hermit/include/stddef.h b/hermit/include/stddef.h new file mode 100644 index 000000000..f7d2e74e3 --- /dev/null +++ b/hermit/include/stddef.h @@ -0,0 +1,14 @@ +#ifndef __ANSI_STDDEF_H__ +#define __ANSI_STDDEF_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hermit/include/string.h b/hermit/include/string.h new file mode 100644 index 000000000..5c8b65e5b --- /dev/null +++ b/hermit/include/string.h @@ -0,0 +1,14 @@ +#ifndef __ANSI_STRING_H__ +#define __ANSI_STRING_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif