semaphore.h (2070B)
1 #ifndef __SEMAPHORE_H 2 #define __SEMAPHORE_H 3 4 #include <irq.h> 5 #include <io.h> 6 #include <spinlock.h> 7 #include <sched.h> 8 9 typedef struct { 10 u32 counter; 11 spinlock_t lock; 12 } semaphore_t; 13 14 #define SEMAPHORE_INIT(v) { (v), SPINLOCK_INIT } 15 16 static inline void 17 semaphore_init(semaphore_t *sem, u32 value) 18 { 19 sem->counter = value; 20 spinlock_init(&sem->lock); 21 } 22 23 /* returns 1 if managed to decreased the counter 24 * returns 0 if not */ 25 static inline int 26 semaphore_trywait(semaphore_t *sem) 27 { 28 spinlock_lock(&sem->lock); 29 if (sem->counter == 0) { 30 spinlock_unlock(&sem->lock); 31 return 0; 32 } 33 sem->counter--; 34 spinlock_unlock(&sem->lock); 35 return 1; 36 } 37 38 /* blocks until it manage to decrease the counter */ 39 static inline void 40 semaphore_wait(semaphore_t *sem) 41 { 42 while (1) { 43 spinlock_lock(&sem->lock); 44 if (sem->counter == 0) { 45 sched_disable(); 46 suspend_task_no_schedule((u32)sem); 47 spinlock_unlock(&sem->lock); 48 sched_enable(); 49 schedule(); 50 continue; 51 } 52 sem->counter--; 53 spinlock_unlock(&sem->lock); 54 break; 55 } 56 } 57 58 /* increases the counter and resumes other tasks */ 59 static inline void 60 semaphore_done(semaphore_t *sem) 61 { 62 spinlock_lock(&sem->lock); 63 sem->counter++; 64 resume_tasks((u32)sem); 65 spinlock_unlock(&sem->lock); 66 } 67 68 69 /* mutex is a binary semaphore */ 70 typedef struct { 71 semaphore_t sem; 72 } mutex_t; 73 74 #define MUTEX_INIT { SEMAPHORE_INIT(1) } 75 #define MUTEX_INIT_LOCKED { SEMAPHORE_INIT(0) } 76 77 static inline void 78 mutex_init(mutex_t *mut) 79 { 80 semaphore_init(&mut->sem, 1); 81 } 82 83 /* returns 1 if managed to lock mutex 84 * returns 0 if not */ 85 static inline int 86 mutex_trylock(mutex_t *mut) 87 { 88 return semaphore_trywait(&mut->sem); 89 } 90 91 /* blocks until it manage to lock mutex */ 92 static inline void 93 mutex_lock(mutex_t *mut) 94 { 95 semaphore_wait(&mut->sem); 96 } 97 98 /* unlock mutex */ 99 static inline void 100 mutex_unlock(mutex_t *mut) 101 { 102 spinlock_lock(&mut->sem.lock); 103 /* if it's already unlocked, do nothing */ 104 if (mut->sem.counter == 1) { 105 spinlock_unlock(&mut->sem.lock); 106 return; 107 } 108 spinlock_unlock(&mut->sem.lock); 109 semaphore_done(&mut->sem); 110 } 111 112 #endif /* __SEMAPHORE_H */