home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-ia64 / rwsem.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  4.6 KB  |  195 lines

  1. /*
  2.  * asm-ia64/rwsem.h: R/W semaphores for ia64
  3.  *
  4.  * Copyright (C) 2003 Ken Chen <kenneth.w.chen@intel.com>
  5.  * Copyright (C) 2003 Asit Mallick <asit.k.mallick@intel.com>
  6.  * Copyright (C) 2005 Christoph Lameter <clameter@sgi.com>
  7.  *
  8.  * Based on asm-i386/rwsem.h and other architecture implementation.
  9.  *
  10.  * The MSW of the count is the negated number of active writers and
  11.  * waiting lockers, and the LSW is the total number of active locks.
  12.  *
  13.  * The lock count is initialized to 0 (no active and no waiting lockers).
  14.  *
  15.  * When a writer subtracts WRITE_BIAS, it'll get 0xffffffff00000001 for
  16.  * the case of an uncontended lock. Readers increment by 1 and see a positive
  17.  * value when uncontended, negative if there are writers (and maybe) readers
  18.  * waiting (in which case it goes to sleep).
  19.  */
  20.  
  21. #ifndef _ASM_IA64_RWSEM_H
  22. #define _ASM_IA64_RWSEM_H
  23.  
  24. #include <linux/list.h>
  25. #include <linux/spinlock.h>
  26.  
  27. #include <asm/intrinsics.h>
  28.  
  29. /*
  30.  * the semaphore definition
  31.  */
  32. struct rw_semaphore {
  33.     signed long        count;
  34.     spinlock_t        wait_lock;
  35.     struct list_head    wait_list;
  36. #if RWSEM_DEBUG
  37.     int            debug;
  38. #endif
  39. };
  40.  
  41. #define RWSEM_UNLOCKED_VALUE        __IA64_UL_CONST(0x0000000000000000)
  42. #define RWSEM_ACTIVE_BIAS        __IA64_UL_CONST(0x0000000000000001)
  43. #define RWSEM_ACTIVE_MASK        __IA64_UL_CONST(0x00000000ffffffff)
  44. #define RWSEM_WAITING_BIAS        -__IA64_UL_CONST(0x0000000100000000)
  45. #define RWSEM_ACTIVE_READ_BIAS        RWSEM_ACTIVE_BIAS
  46. #define RWSEM_ACTIVE_WRITE_BIAS        (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
  47.  
  48. /*
  49.  * initialization
  50.  */
  51. #if RWSEM_DEBUG
  52. #define __RWSEM_DEBUG_INIT      , 0
  53. #else
  54. #define __RWSEM_DEBUG_INIT    /* */
  55. #endif
  56.  
  57. #define __RWSEM_INITIALIZER(name) \
  58.     { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
  59.       LIST_HEAD_INIT((name).wait_list) \
  60.       __RWSEM_DEBUG_INIT }
  61.  
  62. #define DECLARE_RWSEM(name) \
  63.     struct rw_semaphore name = __RWSEM_INITIALIZER(name)
  64.  
  65. extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
  66. extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
  67. extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
  68. extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
  69.  
  70. static inline void
  71. init_rwsem (struct rw_semaphore *sem)
  72. {
  73.     sem->count = RWSEM_UNLOCKED_VALUE;
  74.     spin_lock_init(&sem->wait_lock);
  75.     INIT_LIST_HEAD(&sem->wait_list);
  76. #if RWSEM_DEBUG
  77.     sem->debug = 0;
  78. #endif
  79. }
  80.  
  81. /*
  82.  * lock for reading
  83.  */
  84. static inline void
  85. __down_read (struct rw_semaphore *sem)
  86. {
  87.     long result = ia64_fetchadd8_acq((unsigned long *)&sem->count, 1);
  88.  
  89.     if (result < 0)
  90.         rwsem_down_read_failed(sem);
  91. }
  92.  
  93. /*
  94.  * lock for writing
  95.  */
  96. static inline void
  97. __down_write (struct rw_semaphore *sem)
  98. {
  99.     long old, new;
  100.  
  101.     do {
  102.         old = sem->count;
  103.         new = old + RWSEM_ACTIVE_WRITE_BIAS;
  104.     } while (cmpxchg_acq(&sem->count, old, new) != old);
  105.  
  106.     if (old != 0)
  107.         rwsem_down_write_failed(sem);
  108. }
  109.  
  110. /*
  111.  * unlock after reading
  112.  */
  113. static inline void
  114. __up_read (struct rw_semaphore *sem)
  115. {
  116.     long result = ia64_fetchadd8_rel((unsigned long *)&sem->count, -1);
  117.  
  118.     if (result < 0 && (--result & RWSEM_ACTIVE_MASK) == 0)
  119.         rwsem_wake(sem);
  120. }
  121.  
  122. /*
  123.  * unlock after writing
  124.  */
  125. static inline void
  126. __up_write (struct rw_semaphore *sem)
  127. {
  128.     long old, new;
  129.  
  130.     do {
  131.         old = sem->count;
  132.         new = old - RWSEM_ACTIVE_WRITE_BIAS;
  133.     } while (cmpxchg_rel(&sem->count, old, new) != old);
  134.  
  135.     if (new < 0 && (new & RWSEM_ACTIVE_MASK) == 0)
  136.         rwsem_wake(sem);
  137. }
  138.  
  139. /*
  140.  * trylock for reading -- returns 1 if successful, 0 if contention
  141.  */
  142. static inline int
  143. __down_read_trylock (struct rw_semaphore *sem)
  144. {
  145.     long tmp;
  146.     while ((tmp = sem->count) >= 0) {
  147.         if (tmp == cmpxchg_acq(&sem->count, tmp, tmp+1)) {
  148.             return 1;
  149.         }
  150.     }
  151.     return 0;
  152. }
  153.  
  154. /*
  155.  * trylock for writing -- returns 1 if successful, 0 if contention
  156.  */
  157. static inline int
  158. __down_write_trylock (struct rw_semaphore *sem)
  159. {
  160.     long tmp = cmpxchg_acq(&sem->count, RWSEM_UNLOCKED_VALUE,
  161.                   RWSEM_ACTIVE_WRITE_BIAS);
  162.     return tmp == RWSEM_UNLOCKED_VALUE;
  163. }
  164.  
  165. /*
  166.  * downgrade write lock to read lock
  167.  */
  168. static inline void
  169. __downgrade_write (struct rw_semaphore *sem)
  170. {
  171.     long old, new;
  172.  
  173.     do {
  174.         old = sem->count;
  175.         new = old - RWSEM_WAITING_BIAS;
  176.     } while (cmpxchg_rel(&sem->count, old, new) != old);
  177.  
  178.     if (old < 0)
  179.         rwsem_downgrade_wake(sem);
  180. }
  181.  
  182. /*
  183.  * Implement atomic add functionality.  These used to be "inline" functions, but GCC v3.1
  184.  * doesn't quite optimize this stuff right and ends up with bad calls to fetchandadd.
  185.  */
  186. #define rwsem_atomic_add(delta, sem)    atomic64_add(delta, (atomic64_t *)(&(sem)->count))
  187. #define rwsem_atomic_update(delta, sem)    atomic64_add_return(delta, (atomic64_t *)(&(sem)->count))
  188.  
  189. static inline int rwsem_is_locked(struct rw_semaphore *sem)
  190. {
  191.     return (sem->count != 0);
  192. }
  193.  
  194. #endif /* _ASM_IA64_RWSEM_H */
  195.