commit 27311c2f3d0fe52542c0ad0e356a0d5140b5cc93
parent 87c996caabb6a92cbc8586758c0c5028b64de8d7
Author: oblique <psyberbits@gmail.com>
Date: Thu, 1 Nov 2012 17:11:18 +0200
add semaphore and mutex
Diffstat:
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);
}