home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / s390 / include / asm / spinlock.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  4.3 KB  |  179 lines

  1. /*
  2.  *  include/asm-s390/spinlock.h
  3.  *
  4.  *  S390 version
  5.  *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  6.  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  7.  *
  8.  *  Derived from "include/asm-i386/spinlock.h"
  9.  */
  10.  
  11. #ifndef __ASM_SPINLOCK_H
  12. #define __ASM_SPINLOCK_H
  13.  
  14. #include <linux/smp.h>
  15.  
  16. #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
  17.  
  18. static inline int
  19. _raw_compare_and_swap(volatile unsigned int *lock,
  20.               unsigned int old, unsigned int new)
  21. {
  22.     asm volatile(
  23.         "    cs    %0,%3,%1"
  24.         : "=d" (old), "=Q" (*lock)
  25.         : "0" (old), "d" (new), "Q" (*lock)
  26.         : "cc", "memory" );
  27.     return old;
  28. }
  29.  
  30. #else /* __GNUC__ */
  31.  
  32. static inline int
  33. _raw_compare_and_swap(volatile unsigned int *lock,
  34.               unsigned int old, unsigned int new)
  35. {
  36.     asm volatile(
  37.         "    cs    %0,%3,0(%4)"
  38.         : "=d" (old), "=m" (*lock)
  39.         : "0" (old), "d" (new), "a" (lock), "m" (*lock)
  40.         : "cc", "memory" );
  41.     return old;
  42. }
  43.  
  44. #endif /* __GNUC__ */
  45.  
  46. /*
  47.  * Simple spin lock operations.  There are two variants, one clears IRQ's
  48.  * on the local processor, one does not.
  49.  *
  50.  * We make no fairness assumptions. They have a cost.
  51.  *
  52.  * (the type definitions are in asm/spinlock_types.h)
  53.  */
  54.  
  55. #define __raw_spin_is_locked(x) ((x)->owner_cpu != 0)
  56. #define __raw_spin_unlock_wait(lock) \
  57.     do { while (__raw_spin_is_locked(lock)) \
  58.          _raw_spin_relax(lock); } while (0)
  59.  
  60. extern void _raw_spin_lock_wait(raw_spinlock_t *);
  61. extern void _raw_spin_lock_wait_flags(raw_spinlock_t *, unsigned long flags);
  62. extern int _raw_spin_trylock_retry(raw_spinlock_t *);
  63. extern void _raw_spin_relax(raw_spinlock_t *lock);
  64.  
  65. static inline void __raw_spin_lock(raw_spinlock_t *lp)
  66. {
  67.     int old;
  68.  
  69.     old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id());
  70.     if (likely(old == 0))
  71.         return;
  72.     _raw_spin_lock_wait(lp);
  73. }
  74.  
  75. static inline void __raw_spin_lock_flags(raw_spinlock_t *lp,
  76.                      unsigned long flags)
  77. {
  78.     int old;
  79.  
  80.     old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id());
  81.     if (likely(old == 0))
  82.         return;
  83.     _raw_spin_lock_wait_flags(lp, flags);
  84. }
  85.  
  86. static inline int __raw_spin_trylock(raw_spinlock_t *lp)
  87. {
  88.     int old;
  89.  
  90.     old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id());
  91.     if (likely(old == 0))
  92.         return 1;
  93.     return _raw_spin_trylock_retry(lp);
  94. }
  95.  
  96. static inline void __raw_spin_unlock(raw_spinlock_t *lp)
  97. {
  98.     _raw_compare_and_swap(&lp->owner_cpu, lp->owner_cpu, 0);
  99. }
  100.         
  101. /*
  102.  * Read-write spinlocks, allowing multiple readers
  103.  * but only one writer.
  104.  *
  105.  * NOTE! it is quite common to have readers in interrupts
  106.  * but no interrupt writers. For those circumstances we
  107.  * can "mix" irq-safe locks - any writer needs to get a
  108.  * irq-safe write-lock, but readers can get non-irqsafe
  109.  * read-locks.
  110.  */
  111.  
  112. /**
  113.  * read_can_lock - would read_trylock() succeed?
  114.  * @lock: the rwlock in question.
  115.  */
  116. #define __raw_read_can_lock(x) ((int)(x)->lock >= 0)
  117.  
  118. /**
  119.  * write_can_lock - would write_trylock() succeed?
  120.  * @lock: the rwlock in question.
  121.  */
  122. #define __raw_write_can_lock(x) ((x)->lock == 0)
  123.  
  124. extern void _raw_read_lock_wait(raw_rwlock_t *lp);
  125. extern int _raw_read_trylock_retry(raw_rwlock_t *lp);
  126. extern void _raw_write_lock_wait(raw_rwlock_t *lp);
  127. extern int _raw_write_trylock_retry(raw_rwlock_t *lp);
  128.  
  129. static inline void __raw_read_lock(raw_rwlock_t *rw)
  130. {
  131.     unsigned int old;
  132.     old = rw->lock & 0x7fffffffU;
  133.     if (_raw_compare_and_swap(&rw->lock, old, old + 1) != old)
  134.         _raw_read_lock_wait(rw);
  135. }
  136.  
  137. static inline void __raw_read_unlock(raw_rwlock_t *rw)
  138. {
  139.     unsigned int old, cmp;
  140.  
  141.     old = rw->lock;
  142.     do {
  143.         cmp = old;
  144.         old = _raw_compare_and_swap(&rw->lock, old, old - 1);
  145.     } while (cmp != old);
  146. }
  147.  
  148. static inline void __raw_write_lock(raw_rwlock_t *rw)
  149. {
  150.     if (unlikely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) != 0))
  151.         _raw_write_lock_wait(rw);
  152. }
  153.  
  154. static inline void __raw_write_unlock(raw_rwlock_t *rw)
  155. {
  156.     _raw_compare_and_swap(&rw->lock, 0x80000000, 0);
  157. }
  158.  
  159. static inline int __raw_read_trylock(raw_rwlock_t *rw)
  160. {
  161.     unsigned int old;
  162.     old = rw->lock & 0x7fffffffU;
  163.     if (likely(_raw_compare_and_swap(&rw->lock, old, old + 1) == old))
  164.         return 1;
  165.     return _raw_read_trylock_retry(rw);
  166. }
  167.  
  168. static inline int __raw_write_trylock(raw_rwlock_t *rw)
  169. {
  170.     if (likely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0))
  171.         return 1;
  172.     return _raw_write_trylock_retry(rw);
  173. }
  174.  
  175. #define _raw_read_relax(lock)    cpu_relax()
  176. #define _raw_write_relax(lock)    cpu_relax()
  177.  
  178. #endif /* __ASM_SPINLOCK_H */
  179.