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

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

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

  1 #ifndef _SPARC_SEMAPHORE_H
  2 #define _SPARC_SEMAPHORE_H
  3 
  4 /* Dinky, good for nothing, just barely irq safe, Sparc semaphores. */
  5 
  6 #ifdef __KERNEL__
  7 
  8 #include <asm/atomic.h>
  9 #include <linux/wait.h>
 10 
 11 struct semaphore {
 12         atomic_t count;
 13         int sleepers;
 14         wait_queue_head_t wait;
 15 #if WAITQUEUE_DEBUG
 16         long __magic;
 17 #endif
 18 };
 19 
 20 #if WAITQUEUE_DEBUG
 21 # define __SEM_DEBUG_INIT(name) \
 22                 , (long)&(name).__magic
 23 #else
 24 # define __SEM_DEBUG_INIT(name)
 25 #endif
 26 
 27 #define __SEMAPHORE_INITIALIZER(name,count) \
 28 { ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
 29         __SEM_DEBUG_INIT(name) }
 30 
 31 #define __MUTEX_INITIALIZER(name) \
 32         __SEMAPHORE_INITIALIZER(name,1)
 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 
 40 static inline void sema_init (struct semaphore *sem, int val)
 41 {
 42         atomic_set(&sem->count, val);
 43         sem->sleepers = 0;
 44         init_waitqueue_head(&sem->wait);
 45 #if WAITQUEUE_DEBUG
 46         sem->__magic = (long)&sem->__magic;
 47 #endif
 48 }
 49 
 50 static inline void init_MUTEX (struct semaphore *sem)
 51 {
 52         sema_init(sem, 1);
 53 }
 54 
 55 static inline void 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 static inline void down(struct semaphore * sem)
 66 {
 67         register atomic_t *ptr asm("g1");
 68         register int increment asm("g2");
 69 
 70 #if WAITQUEUE_DEBUG
 71         CHECK_MAGIC(sem->__magic);
 72 #endif
 73 
 74         ptr = (atomic_t *) __atomic_fool_gcc(sem);
 75         increment = 1;
 76 
 77         __asm__ __volatile__("
 78         mov     %%o7, %%g4
 79         call    ___atomic_sub
 80          add    %%o7, 8, %%o7
 81         tst     %%g2
 82         bl      2f
 83          nop
 84 1:
 85         .subsection 2
 86 2:      save    %%sp, -64, %%sp
 87         mov     %%g1, %%l1
 88         mov     %%g5, %%l5
 89         call    %3
 90          mov    %%g1, %%o0
 91         mov     %%l1, %%g1
 92         ba      1b
 93          restore %%l5, %%g0, %%g5
 94         .previous\n"
 95         : "=&r" (increment)
 96         : "" (increment), "r" (ptr), "i" (__down)
 97         : "g3", "g4", "g7", "memory", "cc");
 98 }
 99 
100 static inline int down_interruptible(struct semaphore * sem)
101 {
102         register atomic_t *ptr asm("g1");
103         register int increment asm("g2");
104 
105 #if WAITQUEUE_DEBUG
106         CHECK_MAGIC(sem->__magic);
107 #endif
108 
109         ptr = (atomic_t *) __atomic_fool_gcc(sem);
110         increment = 1;
111 
112         __asm__ __volatile__("
113         mov     %%o7, %%g4
114         call    ___atomic_sub
115          add    %%o7, 8, %%o7
116         tst     %%g2
117         bl      2f
118          clr    %%g2
119 1:
120         .subsection 2
121 2:      save    %%sp, -64, %%sp
122         mov     %%g1, %%l1
123         mov     %%g5, %%l5
124         call    %3
125          mov    %%g1, %%o0
126         mov     %%l1, %%g1
127         mov     %%l5, %%g5
128         ba      1b
129          restore %%o0, %%g0, %%g2
130         .previous\n"
131         : "=&r" (increment)
132         : "" (increment), "r" (ptr), "i" (__down_interruptible)
133         : "g3", "g4", "g7", "memory", "cc");
134 
135         return increment;
136 }
137 
138 static inline int down_trylock(struct semaphore * sem)
139 {
140         register atomic_t *ptr asm("g1");
141         register int increment asm("g2");
142 
143 #if WAITQUEUE_DEBUG
144         CHECK_MAGIC(sem->__magic);
145 #endif
146 
147         ptr = (atomic_t *) __atomic_fool_gcc(sem);
148         increment = 1;
149 
150         __asm__ __volatile__("
151         mov     %%o7, %%g4
152         call    ___atomic_sub
153          add    %%o7, 8, %%o7
154         tst     %%g2
155         bl      2f
156          clr    %%g2
157 1:
158         .subsection 2
159 2:      save    %%sp, -64, %%sp
160         mov     %%g1, %%l1
161         mov     %%g5, %%l5
162         call    %3
163          mov    %%g1, %%o0
164         mov     %%l1, %%g1
165         mov     %%l5, %%g5
166         ba      1b
167          restore %%o0, %%g0, %%g2
168         .previous\n"
169         : "=&r" (increment)
170         : "" (increment), "r" (ptr), "i" (__down_trylock)
171         : "g3", "g4", "g7", "memory", "cc");
172 
173         return increment;
174 }
175 
176 static inline void up(struct semaphore * sem)
177 {
178         register atomic_t *ptr asm("g1");
179         register int increment asm("g2");
180 
181 #if WAITQUEUE_DEBUG
182         CHECK_MAGIC(sem->__magic);
183 #endif
184 
185         ptr = (atomic_t *) __atomic_fool_gcc(sem);
186         increment = 1;
187 
188         __asm__ __volatile__("
189         mov     %%o7, %%g4
190         call    ___atomic_add
191          add    %%o7, 8, %%o7
192         tst     %%g2
193         ble     2f
194          nop
195 1:
196         .subsection 2
197 2:      save    %%sp, -64, %%sp
198         mov     %%g1, %%l1
199         mov     %%g5, %%l5
200         call    %3
201          mov    %%g1, %%o0
202         mov     %%l1, %%g1
203         ba      1b
204          restore %%l5, %%g0, %%g5
205         .previous\n"
206         : "=&r" (increment)
207         : "" (increment), "r" (ptr), "i" (__up)
208         : "g3", "g4", "g7", "memory", "cc");
209 }       
210 
211 /* rw mutexes (should that be mutices? =) -- throw rw
212  * spinlocks and semaphores together, and this is what we
213  * end up with...
214  *
215  * The lock is initialized to BIAS.  This way, a writer
216  * subtracts BIAS ands gets 0 for the case of an uncontended
217  * lock.  Readers decrement by 1 and see a positive value
218  * when uncontended, negative if there are writers waiting
219  * (in which case it goes to sleep).
220  *
221  * The value 0x01000000 supports up to 128 processors and
222  * lots of processes.  BIAS must be chosen such that subtracting
223  * BIAS once per CPU will result in the int remaining
224  * negative.
225  * In terms of fairness, this should result in the lock
226  * flopping back and forth between readers and writers
227  * under heavy use.
228  *
229  *            -ben
230  */
231 #define RW_LOCK_BIAS            0x01000000
232 
233 struct rw_semaphore {
234         int                     count;
235         unsigned char           lock;
236         unsigned char           read_not_granted;
237         unsigned char           write_not_granted;
238         wait_queue_head_t       wait;
239         wait_queue_head_t       write_bias_wait;
240 #if WAITQUEUE_DEBUG
241         long                    __magic;
242         atomic_t                readers;
243         atomic_t                writers;
244 #endif
245 };
246 
247 #if WAITQUEUE_DEBUG
248 #define __RWSEM_DEBUG_INIT      , ATOMIC_INIT(0), ATOMIC_INIT(0)
249 #else
250 #define __RWSEM_DEBUG_INIT      /* */
251 #endif
252 
253 #define __RWSEM_INITIALIZER(name,count) \
254 { (count), 0, 0xff, 0xff, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
255   __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
256   __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
257 
258 #define __DECLARE_RWSEM_GENERIC(name,count) \
259         struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
260 
261 #define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
262 #define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
263 #define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
264 
265 static inline void init_rwsem(struct rw_semaphore *sem)
266 {
267         sem->count = RW_LOCK_BIAS;
268         sem->lock = 0;
269         sem->read_not_granted = 0xff;
270         sem->write_not_granted = 0xff;
271         init_waitqueue_head(&sem->wait);
272         init_waitqueue_head(&sem->write_bias_wait);
273 #if WAITQUEUE_DEBUG
274         sem->__magic = (long)&sem->__magic;
275         atomic_set(&sem->readers, 0);
276         atomic_set(&sem->writers, 0);
277 #endif
278 }
279 
280 extern void ___down_read(/* Special calling convention */ void);
281 extern void ___down_write(/* Special calling convention */ void);
282 extern void ___up_read(/* Special calling convention */ void);
283 extern void ___up_write(/* Special calling convention */ void);
284 
285 static inline void down_read(struct rw_semaphore *sem)
286 {
287         register atomic_t *ptr asm("g1");
288 
289 #if WAITQUEUE_DEBUG
290         CHECK_MAGIC(sem->__magic);
291 #endif
292 
293         ptr = (atomic_t *) __atomic_fool_gcc(sem);
294 
295         __asm__ __volatile__("
296         mov     %%o7, %%g4
297         call    %1
298          add    %%o7, 8, %%o7
299         "
300         :: "r" (ptr), "i" (___down_read)
301         : "g2", "g3", "g4", "g7", "memory", "cc");
302 #if WAITQUEUE_DEBUG
303         if (!sem->write_not_granted)
304                 BUG();
305         if (atomic_read(&sem->writers))
306                 BUG();
307         atomic_inc(&sem->readers);
308 #endif
309 }
310 
311 static inline void down_write(struct rw_semaphore *sem)
312 {
313         register atomic_t *ptr asm("g1");
314 
315 #if WAITQUEUE_DEBUG
316         CHECK_MAGIC(sem->__magic);
317 #endif
318 
319         ptr = (atomic_t *) __atomic_fool_gcc(sem);
320 
321         __asm__ __volatile__("
322         mov     %%o7, %%g4
323         call    %1
324          add    %%o7, 8, %%o7
325         "
326         :: "r" (ptr), "i" (___down_write)
327         : "g2", "g3", "g4", "g7", "memory", "cc");
328 #if WAITQUEUE_DEBUG
329         if (atomic_read(&sem->writers))
330                 BUG();
331         if (atomic_read(&sem->readers))
332                 BUG();
333         if (!sem->read_not_granted)
334                 BUG();
335         if (!sem->write_not_granted)
336                 BUG();
337         atomic_inc(&sem->writers);
338 #endif
339 }
340 
341 /* When a reader does a release, the only significant
342  * case is when there was a writer waiting, and we've
343  * bumped the count to 0: we must wake the writer up.
344  */
345 static inline void __up_read(struct rw_semaphore *sem)
346 {
347         register atomic_t *ptr asm("g1");
348 
349         ptr = (atomic_t *) __atomic_fool_gcc(sem);
350 
351         __asm__ __volatile__("
352         mov     %%o7, %%g4
353         call    %1
354          add    %%o7, 8, %%o7
355         "
356         :: "r" (ptr), "i" (___up_read)
357         : "g2", "g3", "g4", "g7", "memory", "cc");
358 }
359 
360 /* releasing the writer is easy -- just release it and
361  * wake up any sleepers.
362  */
363 static inline void __up_write(struct rw_semaphore *sem)
364 {
365         register atomic_t *ptr asm("g1");
366 
367         ptr = (atomic_t *) __atomic_fool_gcc(sem);
368 
369         __asm__ __volatile__("
370         mov     %%o7, %%g4
371         call    %1
372          add    %%o7, 8, %%o7
373         "
374         :: "r" (ptr), "i" (___up_write)
375         : "g2", "g3", "g4", "g7", "memory", "cc");
376 }
377 
378 static inline void up_read(struct rw_semaphore *sem)
379 {
380 #if WAITQUEUE_DEBUG
381         if (!sem->write_not_granted)
382                 BUG();
383         if (atomic_read(&sem->writers))
384                 BUG();
385         atomic_dec(&sem->readers);
386 #endif
387         __up_read(sem);
388 }
389 
390 static inline void up_write(struct rw_semaphore *sem)
391 {
392 #if WAITQUEUE_DEBUG
393         if (!sem->read_not_granted)
394                 BUG();
395         if (!sem->write_not_granted)
396                 BUG();
397         if (atomic_read(&sem->readers))
398                 BUG();
399         if (atomic_read(&sem->writers) != 1)
400                 BUG();
401         atomic_dec(&sem->writers);
402 #endif
403         __up_write(sem);
404 }
405 
406 #endif /* __KERNEL__ */
407 
408 #endif /* !(_SPARC_SEMAPHORE_H) */
409 

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