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

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

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

  1 #ifndef _ASM_IA64_SEMAPHORE_H
  2 #define _ASM_IA64_SEMAPHORE_H
  3 
  4 /*
  5  * Copyright (C) 1998-2000 Hewlett-Packard Co
  6  * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
  7  */
  8 
  9 #include <linux/wait.h>
 10 
 11 #include <asm/atomic.h>
 12 
 13 struct semaphore {
 14         atomic_t count;
 15         int sleepers;
 16         wait_queue_head_t wait;
 17 #if WAITQUEUE_DEBUG
 18         long __magic;           /* initialized by __SEM_DEBUG_INIT() */
 19 #endif
 20 };
 21 
 22 #if WAITQUEUE_DEBUG
 23 # define __SEM_DEBUG_INIT(name)         , (long) &(name).__magic
 24 #else
 25 # define __SEM_DEBUG_INIT(name)
 26 #endif
 27 
 28 #define __SEMAPHORE_INITIALIZER(name,count)                                     \
 29 {                                                                               \
 30         ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)       \
 31         __SEM_DEBUG_INIT(name)                                                  \
 32 }
 33 
 34 #define __MUTEX_INITIALIZER(name)       __SEMAPHORE_INITIALIZER(name,1)
 35 
 36 #define __DECLARE_SEMAPHORE_GENERIC(name,count)                                 \
 37         struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
 38 
 39 #define DECLARE_MUTEX(name)             __DECLARE_SEMAPHORE_GENERIC(name, 1)
 40 #define DECLARE_MUTEX_LOCKED(name)      __DECLARE_SEMAPHORE_GENERIC(name, 0)
 41 
 42 static inline void
 43 sema_init (struct semaphore *sem, int val)
 44 {
 45         *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
 46 }
 47 
 48 static inline void
 49 init_MUTEX (struct semaphore *sem)
 50 {
 51         sema_init(sem, 1);
 52 }
 53 
 54 static inline void
 55 init_MUTEX_LOCKED (struct semaphore *sem)
 56 {
 57         sema_init(sem, 0);
 58 }
 59 
 60 extern void __down (struct semaphore * sem);
 61 extern int  __down_interruptible (struct semaphore * sem);
 62 extern int  __down_trylock (struct semaphore * sem);
 63 extern void __up (struct semaphore * sem);
 64 
 65 extern spinlock_t semaphore_wake_lock;
 66 
 67 /*
 68  * Atomically decrement the semaphore's count.  If it goes negative,
 69  * block the calling thread in the TASK_UNINTERRUPTIBLE state.
 70  */
 71 static inline void
 72 down (struct semaphore *sem)
 73 {
 74 #if WAITQUEUE_DEBUG
 75         CHECK_MAGIC(sem->__magic);
 76 #endif
 77         if (atomic_dec_return(&sem->count) < 0)
 78                 __down(sem);
 79 }
 80 
 81 /*
 82  * Atomically decrement the semaphore's count.  If it goes negative,
 83  * block the calling thread in the TASK_INTERRUPTIBLE state.
 84  */
 85 static inline int
 86 down_interruptible (struct semaphore * sem)
 87 {
 88         int ret = 0;
 89 
 90 #if WAITQUEUE_DEBUG
 91         CHECK_MAGIC(sem->__magic);
 92 #endif
 93         if (atomic_dec_return(&sem->count) < 0)
 94                 ret = __down_interruptible(sem);
 95         return ret;
 96 }
 97 
 98 static inline int
 99 down_trylock (struct semaphore *sem)
100 {
101         int ret = 0;
102 
103 #if WAITQUEUE_DEBUG
104         CHECK_MAGIC(sem->__magic);
105 #endif
106         if (atomic_dec_return(&sem->count) < 0)
107                 ret = __down_trylock(sem);
108         return ret;
109 }
110 
111 static inline void
112 up (struct semaphore * sem)
113 {
114 #if WAITQUEUE_DEBUG
115         CHECK_MAGIC(sem->__magic);
116 #endif
117         if (atomic_inc_return(&sem->count) <= 0)
118                 __up(sem);
119 }       
120 
121 /*
122  * rw mutexes (should that be mutices? =) -- throw rw spinlocks and
123  * semaphores together, and this is what we end up with...
124  *
125  * The lock is initialized to BIAS.  This way, a writer subtracts BIAS
126  * ands gets 0 for the case of an uncontended lock.  Readers decrement
127  * by 1 and see a positive value when uncontended, negative if there
128  * are writers waiting (in which case it goes to sleep).  BIAS must be
129  * chosen such that subtracting BIAS once per CPU will result either
130  * in zero (uncontended case) or in a negative value (contention
131  * case).  On the other hand, BIAS must be at least as big as the
132  * number of processes in the system.
133  *
134  * On IA-64, we use a BIAS value of 0x100000000, which supports up to
135  * 2 billion (2^31) processors and 4 billion processes.
136  *
137  * In terms of fairness, when there is heavy use of the lock, we want
138  * to see the lock being passed back and forth between readers and
139  * writers (like in a producer/consumer style of communication).
140  *
141  *            -ben (with clarifications & IA-64 comments by davidm)
142  */
143 #define RW_LOCK_BIAS            0x100000000ul
144 
145 struct rw_semaphore {
146         volatile long           count;
147         volatile __u8           write_bias_granted;
148         volatile __u8           read_bias_granted;
149         __u16                   pad1;
150         __u32                   pad2;
151         wait_queue_head_t       wait;
152         wait_queue_head_t       write_bias_wait;
153 #if WAITQUEUE_DEBUG
154         long                    __magic;
155         atomic_t                readers;
156         atomic_t                writers;
157 #endif
158 };
159 
160 #if WAITQUEUE_DEBUG
161 # define __RWSEM_DEBUG_INIT     , ATOMIC_INIT(0), ATOMIC_INIT(0)
162 #else
163 # define __RWSEM_DEBUG_INIT
164 #endif
165 
166 #define __RWSEM_INITIALIZER(name,count)                                         \
167 {                                                                               \
168         (count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),        \
169         __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait)                   \
170         __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT                               \
171 }
172 
173 #define __DECLARE_RWSEM_GENERIC(name,count)                                     \
174         struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
175 
176 #define DECLARE_RWSEM(name)                     __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS)
177 #define DECLARE_RWSEM_READ_LOCKED(name)         __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS - 1)
178 #define DECLARE_RWSEM_WRITE_LOCKED(name)        __DECLARE_RWSEM_GENERIC(name, 0)
179 
180 extern void __down_read_failed (struct rw_semaphore *sem, long count);
181 extern void __down_write_failed (struct rw_semaphore *sem, long count);
182 extern void __rwsem_wake (struct rw_semaphore *sem, long count);
183 
184 static inline void
185 init_rwsem (struct rw_semaphore *sem)
186 {
187         sem->count = RW_LOCK_BIAS;
188         sem->read_bias_granted = 0;
189         sem->write_bias_granted = 0;
190         init_waitqueue_head(&sem->wait);
191         init_waitqueue_head(&sem->write_bias_wait);
192 #if WAITQUEUE_DEBUG
193         sem->__magic = (long)&sem->__magic;
194         atomic_set(&sem->readers, 0);
195         atomic_set(&sem->writers, 0);
196 #endif
197 }
198 
199 static inline void
200 down_read (struct rw_semaphore *sem)
201 {
202         long count;
203 
204 #if WAITQUEUE_DEBUG
205         CHECK_MAGIC(sem->__magic);
206 #endif
207 
208         count = ia64_fetch_and_add(-1, &sem->count);
209         if (count < 0)
210                 __down_read_failed(sem, count);
211 
212 #if WAITQUEUE_DEBUG
213         if (sem->write_bias_granted)
214                 BUG();
215         if (atomic_read(&sem->writers))
216                 BUG();
217         atomic_inc(&sem->readers);
218 #endif
219 }
220 
221 static inline void
222 down_write (struct rw_semaphore *sem)
223 {
224         long old_count, new_count;
225 
226 #if WAITQUEUE_DEBUG
227         CHECK_MAGIC(sem->__magic);
228 #endif
229 
230         do {
231                 old_count = sem->count;
232                 new_count = old_count - RW_LOCK_BIAS;
233         } while (cmpxchg_acq(&sem->count, old_count, new_count) != old_count);
234 
235         if (new_count != 0)
236                 __down_write_failed(sem, new_count);
237 #if WAITQUEUE_DEBUG
238         if (atomic_read(&sem->writers))
239                 BUG();
240         if (atomic_read(&sem->readers))
241                 BUG();
242         if (sem->read_bias_granted)
243                 BUG();
244         if (sem->write_bias_granted)
245                 BUG();
246         atomic_inc(&sem->writers);
247 #endif
248 }
249 
250 /*
251  * When a reader does a release, the only significant
252  * case is when there was a writer waiting, and we've
253  * bumped the count to 0: we must wake the writer up.
254  */
255 static inline void
256 __up_read (struct rw_semaphore *sem)
257 {
258         long count;
259 
260         count = ia64_fetch_and_add(1, &sem->count);
261         if (count == 0)
262                 /*
263                  * Other processes are blocked already; resolve
264                  * contention by letting either a writer or a reader
265                  * proceed...
266                  */
267                 __rwsem_wake(sem, count);
268 }
269 
270 /*
271  * Releasing the writer is easy -- just release it and
272  * wake up any sleepers.
273  */
274 static inline void
275 __up_write (struct rw_semaphore *sem)
276 {
277         long old_count, new_count;
278 
279         do {
280                 old_count = sem->count;
281                 new_count = old_count + RW_LOCK_BIAS;
282         } while (cmpxchg_rel(&sem->count, old_count, new_count) != old_count);
283 
284         /*
285          * Note: new_count <u RW_LOCK_BIAS <=> old_count < 0 && new_count >= 0.
286          *       (where <u is "unsigned less-than").
287          */
288         if ((unsigned long) new_count < RW_LOCK_BIAS)
289                 /* someone is blocked already, resolve contention... */
290                 __rwsem_wake(sem, new_count);
291 }
292 
293 static inline void
294 up_read (struct rw_semaphore *sem)
295 {
296 #if WAITQUEUE_DEBUG
297         if (sem->write_bias_granted)
298                 BUG();
299         if (atomic_read(&sem->writers))
300                 BUG();
301         atomic_dec(&sem->readers);
302 #endif
303         __up_read(sem);
304 }
305 
306 static inline void
307 up_write (struct rw_semaphore *sem)
308 {
309 #if WAITQUEUE_DEBUG
310         if (sem->read_bias_granted)
311                 BUG();
312         if (sem->write_bias_granted)
313                 BUG();
314         if (atomic_read(&sem->readers))
315                 BUG();
316         if (atomic_read(&sem->writers) != 1)
317                 BUG();
318         atomic_dec(&sem->writers);
319 #endif
320         __up_write(sem);
321 }
322 
323 #endif /* _ASM_IA64_SEMAPHORE_H */
324 

~ [ 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.