rwsem.h
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. #ifndef _S390X_RWSEM_H
  2. #define _S390X_RWSEM_H
  3. /*
  4.  *  include/asm-s390x/rwsem.h
  5.  *
  6.  *  S390 version
  7.  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
  8.  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  9.  *
  10.  *  Based on asm-alpha/semaphore.h and asm-i386/rwsem.h
  11.  */
  12. /*
  13.  *
  14.  * The MSW of the count is the negated number of active writers and waiting
  15.  * lockers, and the LSW is the total number of active locks
  16.  *
  17.  * The lock count is initialized to 0 (no active and no waiting lockers).
  18.  *
  19.  * When a writer subtracts WRITE_BIAS, it'll get 0xffff0001 for the case of an
  20.  * uncontended lock. This can be determined because XADD returns the old value.
  21.  * Readers increment by 1 and see a positive value when uncontended, negative
  22.  * if there are writers (and maybe) readers waiting (in which case it goes to
  23.  * sleep).
  24.  *
  25.  * The value of WAITING_BIAS supports up to 32766 waiting processes. This can
  26.  * be extended to 65534 by manually checking the whole MSW rather than relying
  27.  * on the S flag.
  28.  *
  29.  * The value of ACTIVE_BIAS supports up to 65535 active processes.
  30.  *
  31.  * This should be totally fair - if anything is waiting, a process that wants a
  32.  * lock will go to the back of the queue. When the currently active lock is
  33.  * released, if there's a writer at the front of the queue, then that and only
  34.  * that will be woken up; if there's a bunch of consequtive readers at the
  35.  * front, then they'll all be woken up, but no other readers will be.
  36.  */
  37. #ifndef _LINUX_RWSEM_H
  38. #error please dont include asm/rwsem.h directly, use linux/rwsem.h instead
  39. #endif
  40. #ifdef __KERNEL__
  41. #include <linux/list.h>
  42. #include <linux/spinlock.h>
  43. struct rwsem_waiter;
  44. extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
  45. extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
  46. extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *);
  47. /*
  48.  * the semaphore definition
  49.  */
  50. struct rw_semaphore {
  51. signed long count;
  52. spinlock_t wait_lock;
  53. struct list_head wait_list;
  54. };
  55. #define RWSEM_UNLOCKED_VALUE 0x0000000000000000L
  56. #define RWSEM_ACTIVE_BIAS 0x0000000000000001L
  57. #define RWSEM_ACTIVE_MASK 0x00000000ffffffffL
  58. #define RWSEM_WAITING_BIAS (-0x0000000100000000L)
  59. #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
  60. #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
  61. /*
  62.  * initialisation
  63.  */
  64. #define __RWSEM_INITIALIZER(name) 
  65. { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) }
  66. #define DECLARE_RWSEM(name) 
  67. struct rw_semaphore name = __RWSEM_INITIALIZER(name)
  68. static inline void init_rwsem(struct rw_semaphore *sem)
  69. {
  70. sem->count = RWSEM_UNLOCKED_VALUE;
  71. spin_lock_init(&sem->wait_lock);
  72. INIT_LIST_HEAD(&sem->wait_list);
  73. }
  74. /*
  75.  * lock for reading
  76.  */
  77. static inline void __down_read(struct rw_semaphore *sem)
  78. {
  79. signed long old, new;
  80. __asm__ __volatile__(
  81. "   lg   %0,0(%2)n"
  82. "0: lgr  %1,%0n"
  83. "   aghi %1,%3n"
  84. "   csg  %0,%1,0(%2)n"
  85. "   jl   0b"
  86.                 : "=&d" (old), "=&d" (new)
  87. : "a" (&sem->count), "i" (RWSEM_ACTIVE_READ_BIAS)
  88. : "cc", "memory" );
  89. if (old < 0)
  90. rwsem_down_read_failed(sem);
  91. }
  92. /*
  93.  * lock for writing
  94.  */
  95. static inline void __down_write(struct rw_semaphore *sem)
  96. {
  97. signed long old, new, tmp;
  98. tmp = RWSEM_ACTIVE_WRITE_BIAS;
  99. __asm__ __volatile__(
  100. "   lg   %0,0(%2)n"
  101. "0: lgr  %1,%0n"
  102. "   ag   %1,%3n"
  103. "   csg  %0,%1,0(%2)n"
  104. "   jl   0b"
  105.                 : "=&d" (old), "=&d" (new)
  106. : "a" (&sem->count), "m" (tmp)
  107. : "cc", "memory" );
  108. if (old != 0)
  109. rwsem_down_write_failed(sem);
  110. }
  111. /*
  112.  * unlock after reading
  113.  */
  114. static inline void __up_read(struct rw_semaphore *sem)
  115. {
  116. signed long old, new;
  117. __asm__ __volatile__(
  118. "   lg   %0,0(%2)n"
  119. "0: lgr  %1,%0n"
  120. "   aghi %1,%3n"
  121. "   csg  %0,%1,0(%2)n"
  122. "   jl   0b"
  123.                 : "=&d" (old), "=&d" (new)
  124. : "a" (&sem->count), "i" (-RWSEM_ACTIVE_READ_BIAS)
  125. : "cc", "memory" );
  126. if (new < 0)
  127. if ((int) new == 0)
  128. rwsem_wake(sem);
  129. }
  130. /*
  131.  * unlock after writing
  132.  */
  133. static inline void __up_write(struct rw_semaphore *sem)
  134. {
  135. signed long old, new, tmp;
  136. tmp = -RWSEM_ACTIVE_WRITE_BIAS;
  137. __asm__ __volatile__(
  138. "   lg   %0,0(%2)n"
  139. "0: lgr  %1,%0n"
  140. "   ag   %1,%3n"
  141. "   csg  %0,%1,0(%2)n"
  142. "   jl   0b"
  143.                 : "=&d" (old), "=&d" (new)
  144. : "a" (&sem->count), "m" (tmp)
  145. : "cc", "memory" );
  146. if (new < 0)
  147. if ((int) new == 0)
  148. rwsem_wake(sem);
  149. }
  150. /*
  151.  * implement atomic add functionality
  152.  */
  153. static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
  154. {
  155. signed long old, new;
  156. __asm__ __volatile__(
  157. "   lg   %0,0(%2)n"
  158. "0: lgr  %1,%0n"
  159. "   agr  %1,%3n"
  160. "   csg  %0,%1,0(%2)n"
  161. "   jl   0b"
  162.                 : "=&d" (old), "=&d" (new)
  163. : "a" (&sem->count), "d" (delta)
  164. : "cc", "memory" );
  165. }
  166. /*
  167.  * implement exchange and add functionality
  168.  */
  169. static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
  170. {
  171. signed long old, new;
  172. __asm__ __volatile__(
  173. "   lg   %0,0(%2)n"
  174. "0: lgr  %1,%0n"
  175. "   agr  %1,%3n"
  176. "   csg  %0,%1,0(%2)n"
  177. "   jl   0b"
  178.                 : "=&d" (old), "=&d" (new)
  179. : "a" (&sem->count), "d" (delta)
  180. : "cc", "memory" );
  181. return new;
  182. }
  183. #endif /* __KERNEL__ */
  184. #endif /* _S390X_RWSEM_H */