1/* $Id: semaphore.h,v 1.1.1.1 2007/08/03 18:53:22 Exp $ */ 2 3/* On the i386 these are coded in asm, perhaps we should as well. Later.. */ 4 5#ifndef _CRIS_SEMAPHORE_H 6#define _CRIS_SEMAPHORE_H 7 8#define RW_LOCK_BIAS 0x01000000 9 10#include <linux/wait.h> 11#include <linux/spinlock.h> 12#include <linux/rwsem.h> 13 14#include <asm/system.h> 15#include <asm/atomic.h> 16 17/* 18 * CRIS semaphores, implemented in C-only so far. 19 */ 20 21struct semaphore { 22 atomic_t count; 23 atomic_t waking; 24 wait_queue_head_t wait; 25}; 26 27#define __SEMAPHORE_INITIALIZER(name, n) \ 28{ \ 29 .count = ATOMIC_INIT(n), \ 30 .waking = ATOMIC_INIT(0), \ 31 .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ 32} 33 34#define __DECLARE_SEMAPHORE_GENERIC(name,count) \ 35 struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) 36 37#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) 38#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0) 39 40static inline void sema_init(struct semaphore *sem, int val) 41{ 42 *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val); 43} 44 45static inline void init_MUTEX (struct semaphore *sem) 46{ 47 sema_init(sem, 1); 48} 49 50static inline void init_MUTEX_LOCKED (struct semaphore *sem) 51{ 52 sema_init(sem, 0); 53} 54 55extern void __down(struct semaphore * sem); 56extern int __down_interruptible(struct semaphore * sem); 57extern int __down_trylock(struct semaphore * sem); 58extern void __up(struct semaphore * sem); 59 60/* notice - we probably can do cli/sti here instead of saving */ 61 62static inline void down(struct semaphore * sem) 63{ 64 unsigned long flags; 65 int failed; 66 67 might_sleep(); 68 69 /* atomically decrement the semaphores count, and if its negative, we wait */ 70 cris_atomic_save(sem, flags); 71 failed = --(sem->count.counter) < 0; 72 cris_atomic_restore(sem, flags); 73 if(failed) { 74 __down(sem); 75 } 76} 77 78/* 79 * This version waits in interruptible state so that the waiting 80 * process can be killed. The down_interruptible routine 81 * returns negative for signalled and zero for semaphore acquired. 82 */ 83 84static inline int down_interruptible(struct semaphore * sem) 85{ 86 unsigned long flags; 87 int failed; 88 89 might_sleep(); 90 91 /* atomically decrement the semaphores count, and if its negative, we wait */ 92 cris_atomic_save(sem, flags); 93 failed = --(sem->count.counter) < 0; 94 cris_atomic_restore(sem, flags); 95 if(failed) 96 failed = __down_interruptible(sem); 97 return(failed); 98} 99 100static inline int down_trylock(struct semaphore * sem) 101{ 102 unsigned long flags; 103 int failed; 104 105 cris_atomic_save(sem, flags); 106 failed = --(sem->count.counter) < 0; 107 cris_atomic_restore(sem, flags); 108 if(failed) 109 failed = __down_trylock(sem); 110 return(failed); 111 112} 113 114/* 115 * Note! This is subtle. We jump to wake people up only if 116 * the semaphore was negative (== somebody was waiting on it). 117 * The default case (no contention) will result in NO 118 * jumps for both down() and up(). 119 */ 120static inline void up(struct semaphore * sem) 121{ 122 unsigned long flags; 123 int wakeup; 124 125 /* atomically increment the semaphores count, and if it was negative, we wake people */ 126 cris_atomic_save(sem, flags); 127 wakeup = ++(sem->count.counter) <= 0; 128 cris_atomic_restore(sem, flags); 129 if(wakeup) { 130 __up(sem); 131 } 132} 133 134#endif 135