~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-parisc/semaphore.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #ifndef _ASM_PARISC_SEMAPHORE_H
  2 #define _ASM_PARISC_SEMAPHORE_H
  3 
  4 #include <linux/linkage.h>
  5 
  6 /*
  7  * SMP- and interrupt-safe semaphores.
  8  *
  9  * (C) Copyright 1996 Linus Torvalds
 10  *
 11  * SuperH verison by Niibe Yutaka
 12  *
 13  */
 14 
 15 /* if you're going to use out-of-line slowpaths, use .section .lock.text,
 16  * not .text.lock or the -ffunction-sections monster will eat you alive
 17  */
 18 
 19 #include <linux/spinlock.h>
 20 
 21 #include <asm/system.h>
 22 #include <asm/atomic.h>
 23 
 24 struct semaphore {
 25         atomic_t count;
 26         int waking;
 27         wait_queue_head_t wait;
 28 #if WAITQUEUE_DEBUG
 29         long __magic;
 30 #endif
 31 };
 32 
 33 #if WAITQUEUE_DEBUG
 34 # define __SEM_DEBUG_INIT(name) \
 35                 , (long)&(name).__magic
 36 #else
 37 # define __SEM_DEBUG_INIT(name)
 38 #endif
 39 
 40 #define __SEMAPHORE_INITIALIZER(name,count) \
 41 { ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
 42         __SEM_DEBUG_INIT(name) }
 43 
 44 #define __MUTEX_INITIALIZER(name) \
 45         __SEMAPHORE_INITIALIZER(name,1)
 46 
 47 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
 48         struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 49 
 50 #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
 51 #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
 52 
 53 extern inline void sema_init (struct semaphore *sem, int val)
 54 {
 55 /*
 56  *      *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
 57  *
 58  * i'd rather use the more flexible initialization above, but sadly
 59  * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
 60  */
 61         atomic_set(&sem->count, val);
 62         sem->waking = 0;
 63         init_waitqueue_head(&sem->wait);
 64 #if WAITQUEUE_DEBUG
 65         sem->__magic = (long)&sem->__magic;
 66 #endif
 67 }
 68 
 69 static inline void init_MUTEX (struct semaphore *sem)
 70 {
 71         sema_init(sem, 1);
 72 }
 73 
 74 static inline void init_MUTEX_LOCKED (struct semaphore *sem)
 75 {
 76         sema_init(sem, 0);
 77 }
 78 
 79 asmlinkage void __down_failed(void /* special register calling convention */);
 80 asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
 81 asmlinkage int  __down_failed_trylock(void  /* params in registers */);
 82 asmlinkage void __up_wakeup(void /* special register calling convention */);
 83 
 84 asmlinkage void __down(struct semaphore * sem);
 85 asmlinkage int  __down_interruptible(struct semaphore * sem);
 86 asmlinkage int  __down_trylock(struct semaphore * sem);
 87 asmlinkage void __up(struct semaphore * sem);
 88 
 89 extern spinlock_t semaphore_wake_lock;
 90 
 91 extern __inline__ void down(struct semaphore * sem)
 92 {
 93 #if WAITQUEUE_DEBUG
 94         CHECK_MAGIC(sem->__magic);
 95 #endif
 96 
 97         if (atomic_dec_return(&sem->count) < 0)
 98                 __down(sem);
 99 }
100 
101 extern __inline__ int down_interruptible(struct semaphore * sem)
102 {
103         int ret = 0;
104 #if WAITQUEUE_DEBUG
105         CHECK_MAGIC(sem->__magic);
106 #endif
107 
108         if (atomic_dec_return(&sem->count) < 0)
109                 ret = __down_interruptible(sem);
110         return ret;
111 }
112 
113 extern __inline__ int down_trylock(struct semaphore * sem)
114 {
115         int ret = 0;
116 #if WAITQUEUE_DEBUG
117         CHECK_MAGIC(sem->__magic);
118 #endif
119 
120         if (atomic_dec_return(&sem->count) < 0)
121                 ret = __down_trylock(sem);
122         return ret;
123 }
124 
125 /*
126  * Note! This is subtle. We jump to wake people up only if
127  * the semaphore was negative (== somebody was waiting on it).
128  */
129 extern __inline__ void up(struct semaphore * sem)
130 {
131 #if WAITQUEUE_DEBUG
132         CHECK_MAGIC(sem->__magic);
133 #endif
134         if (atomic_inc_return(&sem->count) <= 0)
135                 __up(sem);
136 }
137 
138 /* rw mutexes (should that be mutices? =) -- throw rw
139  * spinlocks and semaphores together, and this is what we
140  * end up with...
141  *
142  * The lock is initialized to BIAS.  This way, a writer
143  * subtracts BIAS ands gets 0 for the case of an uncontended
144  * lock.  Readers decrement by 1 and see a positive value
145  * when uncontended, negative if there are writers waiting
146  * (in which case it goes to sleep).
147  *
148  * The value 0x01000000 supports up to 128 processors and
149  * lots of processes.  BIAS must be chosen such that subl'ing
150  * BIAS once per CPU will result in the long remaining
151  * negative.
152  *
153  * In terms of fairness, this should result in the lock
154  * flopping back and forth between readers and writers
155  * under heavy use.
156  *
157  *              -ben
158  */
159 struct rw_semaphore {
160         atomic_t                count;
161         volatile unsigned char  write_bias_granted;
162         volatile unsigned char  read_bias_granted;
163         volatile unsigned char  pad1;
164         volatile unsigned char  pad2;
165         wait_queue_head_t       wait;
166         wait_queue_head_t       write_bias_wait;
167 #if WAITQUEUE_DEBUG
168         long                    __magic;
169         atomic_t                readers;
170         atomic_t                writers;
171 #endif
172 };
173 
174 #if WAITQUEUE_DEBUG
175 #define __RWSEM_DEBUG_INIT      , ATOMIC_INIT(0), ATOMIC_INIT(0)
176 #else
177 #define __RWSEM_DEBUG_INIT      /* */
178 #endif
179 
180 #define RW_LOCK_BIAS 0x01000000
181 
182 #define __RWSEM_INITIALIZER(name,count) \
183 { ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
184         __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
185         __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
186 
187 #define __DECLARE_RWSEM_GENERIC(name,count) \
188         struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
189 
190 #define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
191 #define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
192 #define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
193 
194 extern inline void init_rwsem(struct rw_semaphore *sem)
195 {
196         atomic_set(&sem->count, RW_LOCK_BIAS);
197         sem->read_bias_granted = 0;
198         sem->write_bias_granted = 0;
199         init_waitqueue_head(&sem->wait);
200         init_waitqueue_head(&sem->write_bias_wait);
201 #if WAITQUEUE_DEBUG
202         sem->__magic = (long)&sem->__magic;
203         atomic_set(&sem->readers, 0);
204         atomic_set(&sem->writers, 0);
205 #endif
206 }
207 
208 #ifdef FIXME_WILLY_FIXME_FOR_REAL_THIS_TIME
209 extern struct rw_semaphore *__build_read_lock(struct rw_semaphore *sem, const char *what);
210 extern struct rw_semaphore *__build_write_lock(struct rw_semaphore *sem, const char *what);
211 #endif
212 
213 /* we use FASTCALL convention for the helpers */
214 extern struct rw_semaphore *FASTCALL(__down_read_failed(struct rw_semaphore *sem));
215 extern struct rw_semaphore *FASTCALL(__down_write_failed(struct rw_semaphore *sem));
216 extern struct rw_semaphore *FASTCALL(__rwsem_wake(struct rw_semaphore *sem));
217 
218 extern inline void down_read(struct rw_semaphore *sem)
219 {
220 #if WAITQUEUE_DEBUG
221         if (sem->__magic != (long)&sem->__magic)
222                 BUG();
223 #endif
224 #ifdef FIXME_WILLY_FIXME_FOR_REAL_THIS_TIME
225         __build_read_lock(sem, "__down_read_failed");
226 #endif
227 #if WAITQUEUE_DEBUG
228         if (sem->write_bias_granted)
229                 BUG();
230         if (atomic_read(&sem->writers))
231                 BUG();
232         atomic_inc(&sem->readers);
233 #endif
234 }
235 
236 extern inline void down_write(struct rw_semaphore *sem)
237 {
238 #if WAITQUEUE_DEBUG
239         if (sem->__magic != (long)&sem->__magic)
240                 BUG();
241 #endif
242 #ifdef FIXME_WILLY_FIXME_FOR_REAL_THIS_TIME
243         __build_write_lock(sem, "__down_write_failed");
244 #endif
245 #if WAITQUEUE_DEBUG
246         if (atomic_read(&sem->writers))
247                 BUG();
248         if (atomic_read(&sem->readers))
249                 BUG();
250         if (sem->read_bias_granted)
251                 BUG();
252         if (sem->write_bias_granted)
253                 BUG();
254         atomic_inc(&sem->writers);
255 #endif
256 }
257 
258 /* When a reader does a release, the only significant
259  * case is when there was a writer waiting, and we've
260  * bumped the count to 0: we must wake the writer up.
261  */
262 extern inline void __up_read(struct rw_semaphore *sem)
263 {
264 }
265 
266 /* releasing the writer is easy -- just release it and
267  * wake up any sleepers.
268  */
269 extern inline void __up_write(struct rw_semaphore *sem)
270 {
271 }
272 
273 extern inline void up_read(struct rw_semaphore *sem)
274 {
275 #if WAITQUEUE_DEBUG
276         if (sem->write_bias_granted)
277                 BUG();
278         if (atomic_read(&sem->writers))
279                 BUG();
280         atomic_dec(&sem->readers);
281 #endif
282         __up_read(sem);
283 }
284 
285 extern inline void up_write(struct rw_semaphore *sem)
286 {
287 #if WAITQUEUE_DEBUG
288         if (sem->read_bias_granted)
289                 BUG();
290         if (sem->write_bias_granted)
291                 BUG();
292         if (atomic_read(&sem->readers))
293                 BUG();
294         if (atomic_read(&sem->writers) != 1)
295                 BUG();
296         atomic_dec(&sem->writers);
297 #endif
298         __up_write(sem);
299 }
300 
301 #endif /* _ASM_PARISC_SEMAPHORE_H */
302 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.