voron

experimental ARM OS
git clone git://git.2f30.org/voron
Log | Files | Refs | README | LICENSE

commit 27311c2f3d0fe52542c0ad0e356a0d5140b5cc93
parent 87c996caabb6a92cbc8586758c0c5028b64de8d7
Author: oblique <psyberbits@gmail.com>
Date:   Thu,  1 Nov 2012 17:11:18 +0200

add semaphore and mutex

Diffstat:
Ainclude/semaphore.h | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mkernel/kmain.c | 18++++++++++++++++--
2 files changed, 114 insertions(+), 2 deletions(-)

diff --git a/include/semaphore.h b/include/semaphore.h @@ -0,0 +1,98 @@ +#ifndef __SEMAPHORE_H +#define __SEMAPHORE_H + +#include <io.h> +#include <sched.h> + +typedef struct { + u32 counter; +} semaphore_t; + +typedef struct { + semaphore_t sem; +} mutex_t; + +#define SEMAPHORE_INIT(v) { (v) } + +static inline void +semaphore_init(semaphore_t *sem, u32 value) +{ + sem->counter = value; +} + +static inline int +semaphore_trywait(semaphore_t *sem) +{ + u32 tmp; + + asm volatile ( + "ldrex v1, [%1] \n\t" + "teq v1, #0 \n\t" + "moveq %0, #1 \n\t" + "subne v1, v1, #1 \n\t" + "strexne %0, v1, [%1] \n\t" + : "=&r" (tmp) + : "r" (&sem->counter) + : "v1", "memory", "cc" + ); + + if (tmp == 0) { + dmb(); + return 1; + } else + return 0; +} + +static inline void +semaphore_wait(semaphore_t *sem) +{ + while (!semaphore_trywait(sem)) + suspend_task((u32)sem); +} + +static inline void +semaphore_done(semaphore_t *sem) +{ + dmb(); + asm volatile ( + "1: \n\t" + "ldrex v1, [%0] \n\t" + "add v1, v1, #1 \n\t" + "strex v2, v1, [%0] \n\t" + "teq v2, #0 \n\t" + "bne 1b \n\t" + : + : "r" (&sem->counter) + : "v1", "v2", "memory", "cc" + ); + dmb(); + resume_tasks((u32)sem); +} + +#define MUTEX_INIT { SEMAPHORE_INIT(1) } + +static inline void +mutex_init(mutex_t *mut) +{ + semaphore_init(&mut->sem, 1); +} + +static inline int +mutex_trylock(mutex_t *mut) +{ + return semaphore_trywait(&mut->sem); +} + +static inline void +mutex_lock(mutex_t *mut) +{ + semaphore_wait(&mut->sem); +} + +static inline void +mutex_unlock(mutex_t *mut) +{ + semaphore_done(&mut->sem); +} + +#endif /* __SEMAPHORE_H */ diff --git a/kernel/kmain.c b/kernel/kmain.c @@ -1,13 +1,26 @@ #include <kernel.h> #include <sched.h> +#include <semaphore.h> + +semaphore_t sem = SEMAPHORE_INIT(2); static void thread_func(void *arg) { - u32 n = (u32)arg; + u32 i = 0, n = (u32)arg; while (1) { - kprintf("thread %d\n", n); + if (i == 5 * n) { + kprintf("thread %d waiting semaphore\n", n); + semaphore_wait(&sem); + kprintf("thread %d locked semaphore\n", n); + } + kprintf("thread %d i: %d\n", n, i); msleep(500); + i++; + if (i == 20 * n) { + semaphore_done(&sem); + kprintf("thread %d released semaphore\n", n); + } } } @@ -17,4 +30,5 @@ kmain(void) kprintf("voron initial stage\n\n"); kthread_create(thread_func, (void*)1); kthread_create(thread_func, (void*)2); + kthread_create(thread_func, (void*)3); }