voron

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

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 */