voron

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

commit 2495223bb4a77539f2060d7b18038bdd3664e090
parent 72c0ea32616df5f6e4054a6e2cefb1801679a365
Author: oblique <psyberbits@gmail.com>
Date:   Mon Nov  5 18:07:44 +0200

improved and safer semaphores

Diffstat:
include/semaphore.h | 60++++++++++++++++++++++++++----------------------------------
1 file changed, 26 insertions(+), 34 deletions(-)
diff --git a/include/semaphore.h b/include/semaphore.h @@ -2,22 +2,25 @@ #define __SEMAPHORE_H #include <io.h> +#include <spinlock.h> #include <sched.h> typedef struct { u32 counter; + spinlock_t lock; } semaphore_t; typedef struct { semaphore_t sem; } mutex_t; -#define SEMAPHORE_INIT(v) { (v) } +#define SEMAPHORE_INIT(v) { (v), SPINLOCK_INIT } static inline void semaphore_init(semaphore_t *sem, u32 value) { sem->counter = value; + INIT_SPINLOCK(&sem->lock); } /* returns 1 if managed to decreased the counter @@ -25,53 +28,42 @@ semaphore_init(semaphore_t *sem, u32 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 + spinlock_lock(&sem->lock); + if (sem->counter == 0) { + spinlock_unlock(&sem->lock); return 0; + } + sem->counter--; + spinlock_unlock(&sem->lock); + return 1; } /* blocks until it manage to decrease the counter */ static inline void semaphore_wait(semaphore_t *sem) { - while (!semaphore_trywait(sem)) - suspend_task((u32)sem); /* sleep */ + while (1) { + spinlock_lock(&sem->lock); + if (sem->counter == 0) { + suspend_task_no_schedule((u32)sem); + spinlock_unlock(&sem->lock); + schedule(); + continue; + } + sem->counter--; + spinlock_unlock(&sem->lock); + break; + } } /* increases the counter and resumes other tasks */ 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 that use the same semaphore */ + spinlock_lock(&sem->lock); + sem->counter++; resume_tasks((u32)sem); + spinlock_unlock(&sem->lock); }