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

Linux/Unix编程

开发平台:

Unix_Linux

  1. #ifndef _ALPHA_RWSEM_H
  2. #define _ALPHA_RWSEM_H
  3. /*
  4.  * Written by Ivan Kokshaysky <ink@jurassic.park.msu.ru>, 2001.
  5.  * Based on asm-alpha/semaphore.h and asm-i386/rwsem.h
  6.  */
  7. #ifndef _LINUX_RWSEM_H
  8. #error please dont include asm/rwsem.h directly, use linux/rwsem.h instead
  9. #endif
  10. #ifdef __KERNEL__
  11. #include <linux/compiler.h>
  12. #include <linux/list.h>
  13. #include <linux/spinlock.h>
  14. struct rwsem_waiter;
  15. extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
  16. extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
  17. extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *);
  18. /*
  19.  * the semaphore definition
  20.  */
  21. struct rw_semaphore {
  22. long count;
  23. #define RWSEM_UNLOCKED_VALUE 0x0000000000000000L
  24. #define RWSEM_ACTIVE_BIAS 0x0000000000000001L
  25. #define RWSEM_ACTIVE_MASK 0x00000000ffffffffL
  26. #define RWSEM_WAITING_BIAS (-0x0000000100000000L)
  27. #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
  28. #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
  29. spinlock_t wait_lock;
  30. struct list_head wait_list;
  31. #if RWSEM_DEBUG
  32. int debug;
  33. #endif
  34. };
  35. #if RWSEM_DEBUG
  36. #define __RWSEM_DEBUG_INIT      , 0
  37. #else
  38. #define __RWSEM_DEBUG_INIT /* */
  39. #endif
  40. #define __RWSEM_INITIALIZER(name) 
  41. { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, 
  42. LIST_HEAD_INIT((name).wait_list) __RWSEM_DEBUG_INIT }
  43. #define DECLARE_RWSEM(name) 
  44. struct rw_semaphore name = __RWSEM_INITIALIZER(name)
  45. static inline void init_rwsem(struct rw_semaphore *sem)
  46. {
  47. sem->count = RWSEM_UNLOCKED_VALUE;
  48. spin_lock_init(&sem->wait_lock);
  49. INIT_LIST_HEAD(&sem->wait_list);
  50. #if RWSEM_DEBUG
  51. sem->debug = 0;
  52. #endif
  53. }
  54. static inline void __down_read(struct rw_semaphore *sem)
  55. {
  56. long oldcount;
  57. #ifndef CONFIG_SMP
  58. oldcount = sem->count;
  59. sem->count += RWSEM_ACTIVE_READ_BIAS;
  60. #else
  61. long temp;
  62. __asm__ __volatile__(
  63. "1: ldq_l %0,%1n"
  64. " addq %0,%3,%2n"
  65. " stq_c %2,%1n"
  66. " beq %2,2fn"
  67. " mbn"
  68. ".subsection 2n"
  69. "2: br 1bn"
  70. ".previous"
  71. :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
  72. :"Ir" (RWSEM_ACTIVE_READ_BIAS), "m" (sem->count) : "memory");
  73. #endif
  74. if (__builtin_expect(oldcount < 0, 0))
  75. rwsem_down_read_failed(sem);
  76. }
  77. /*
  78.  * trylock for reading -- returns 1 if successful, 0 if contention
  79.  */
  80. static inline int __down_read_trylock(struct rw_semaphore *sem)
  81. {
  82. long old, new, res;
  83. res = sem->count;
  84. do {
  85. new = res + RWSEM_ACTIVE_READ_BIAS;
  86. if (new <= 0)
  87. break;
  88. old = res;
  89. res = cmpxchg(&sem->count, old, new);
  90. } while (res != old);
  91. return res >= 0 ? 1 : 0;
  92. }
  93. static inline void __down_write(struct rw_semaphore *sem)
  94. {
  95. long oldcount;
  96. #ifndef CONFIG_SMP
  97. oldcount = sem->count;
  98. sem->count += RWSEM_ACTIVE_WRITE_BIAS;
  99. #else
  100. long temp;
  101. __asm__ __volatile__(
  102. "1: ldq_l %0,%1n"
  103. " addq %0,%3,%2n"
  104. " stq_c %2,%1n"
  105. " beq %2,2fn"
  106. " mbn"
  107. ".subsection 2n"
  108. "2: br 1bn"
  109. ".previous"
  110. :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
  111. :"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory");
  112. #endif
  113. if (__builtin_expect(oldcount, 0))
  114. rwsem_down_write_failed(sem);
  115. }
  116. /*
  117.  * trylock for writing -- returns 1 if successful, 0 if contention
  118.  */
  119. static inline int __down_write_trylock(struct rw_semaphore *sem)
  120. {
  121. long ret = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
  122.    RWSEM_ACTIVE_WRITE_BIAS);
  123. if (ret == RWSEM_UNLOCKED_VALUE)
  124. return 1;
  125. return 0;
  126. }
  127. static inline void __up_read(struct rw_semaphore *sem)
  128. {
  129. long oldcount;
  130. #ifndef CONFIG_SMP
  131. oldcount = sem->count;
  132. sem->count -= RWSEM_ACTIVE_READ_BIAS;
  133. #else
  134. long temp;
  135. __asm__ __volatile__(
  136. " mbn"
  137. "1: ldq_l %0,%1n"
  138. " subq %0,%3,%2n"
  139. " stq_c %2,%1n"
  140. " beq %2,2fn"
  141. ".subsection 2n"
  142. "2: br 1bn"
  143. ".previous"
  144. :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
  145. :"Ir" (RWSEM_ACTIVE_READ_BIAS), "m" (sem->count) : "memory");
  146. #endif
  147. if (__builtin_expect(oldcount < 0, 0)) 
  148. if ((int)oldcount - RWSEM_ACTIVE_READ_BIAS == 0)
  149. rwsem_wake(sem);
  150. }
  151. static inline void __up_write(struct rw_semaphore *sem)
  152. {
  153. long count;
  154. #ifndef CONFIG_SMP
  155. sem->count -= RWSEM_ACTIVE_WRITE_BIAS;
  156. count = sem->count;
  157. #else
  158. long temp;
  159. __asm__ __volatile__(
  160. " mbn"
  161. "1: ldq_l %0,%1n"
  162. " subq %0,%3,%2n"
  163. " stq_c %2,%1n"
  164. " beq %2,2fn"
  165. " subq %0,%3,%0n"
  166. ".subsection 2n"
  167. "2: br 1bn"
  168. ".previous"
  169. :"=&r" (count), "=m" (sem->count), "=&r" (temp)
  170. :"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory");
  171. #endif
  172. if (__builtin_expect(count, 0))
  173. if ((int)count == 0)
  174. rwsem_wake(sem);
  175. }
  176. static inline void rwsem_atomic_add(long val, struct rw_semaphore *sem)
  177. {
  178. #ifndef CONFIG_SMP
  179. sem->count += val;
  180. #else
  181. long temp;
  182. __asm__ __volatile__(
  183. "1: ldq_l %0,%1n"
  184. " addq %0,%2,%0n"
  185. " stq_c %0,%1n"
  186. " beq %0,2fn"
  187. ".subsection 2n"
  188. "2: br 1bn"
  189. ".previous"
  190. :"=&r" (temp), "=m" (sem->count)
  191. :"Ir" (val), "m" (sem->count));
  192. #endif
  193. }
  194. static inline long rwsem_atomic_update(long val, struct rw_semaphore *sem)
  195. {
  196. #ifndef CONFIG_SMP
  197. sem->count += val;
  198. return sem->count;
  199. #else
  200. long ret, temp;
  201. __asm__ __volatile__(
  202. "1: ldq_l %0,%1n"
  203. " addq  %0,%3,%2n"
  204. " addq %0,%3,%0n"
  205. " stq_c %2,%1n"
  206. " beq %2,2fn"
  207. ".subsection 2n"
  208. "2: br 1bn"
  209. ".previous"
  210. :"=&r" (ret), "=m" (sem->count), "=&r" (temp)
  211. :"Ir" (val), "m" (sem->count));
  212. return ret;
  213. #endif
  214. }
  215. #endif /* __KERNEL__ */
  216. #endif /* _ALPHA_RWSEM_H */