rwsem.h
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
源码类别:

嵌入式Linux

开发平台:

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. static inline void __down_write(struct rw_semaphore *sem)
  78. {
  79. long oldcount;
  80. #ifndef CONFIG_SMP
  81. oldcount = sem->count;
  82. sem->count += RWSEM_ACTIVE_WRITE_BIAS;
  83. #else
  84. long temp;
  85. __asm__ __volatile__(
  86. "1: ldq_l %0,%1n"
  87. " addq %0,%3,%2n"
  88. " stq_c %2,%1n"
  89. " beq %2,2fn"
  90. " mbn"
  91. ".subsection 2n"
  92. "2: br 1bn"
  93. ".previous"
  94. :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
  95. :"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory");
  96. #endif
  97. if (__builtin_expect(oldcount, 0))
  98. rwsem_down_write_failed(sem);
  99. }
  100. static inline void __up_read(struct rw_semaphore *sem)
  101. {
  102. long oldcount;
  103. #ifndef CONFIG_SMP
  104. oldcount = sem->count;
  105. sem->count -= RWSEM_ACTIVE_READ_BIAS;
  106. #else
  107. long temp;
  108. __asm__ __volatile__(
  109. " mbn"
  110. "1: ldq_l %0,%1n"
  111. " subq %0,%3,%2n"
  112. " stq_c %2,%1n"
  113. " beq %2,2fn"
  114. ".subsection 2n"
  115. "2: br 1bn"
  116. ".previous"
  117. :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
  118. :"Ir" (RWSEM_ACTIVE_READ_BIAS), "m" (sem->count) : "memory");
  119. #endif
  120. if (__builtin_expect(oldcount < 0, 0)) 
  121. if ((int)oldcount - RWSEM_ACTIVE_READ_BIAS == 0)
  122. rwsem_wake(sem);
  123. }
  124. static inline void __up_write(struct rw_semaphore *sem)
  125. {
  126. long count;
  127. #ifndef CONFIG_SMP
  128. sem->count -= RWSEM_ACTIVE_WRITE_BIAS;
  129. count = sem->count;
  130. #else
  131. long temp;
  132. __asm__ __volatile__(
  133. " mbn"
  134. "1: ldq_l %0,%1n"
  135. " subq %0,%3,%2n"
  136. " stq_c %2,%1n"
  137. " beq %2,2fn"
  138. " subq %0,%3,%0n"
  139. ".subsection 2n"
  140. "2: br 1bn"
  141. ".previous"
  142. :"=&r" (count), "=m" (sem->count), "=&r" (temp)
  143. :"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory");
  144. #endif
  145. if (__builtin_expect(count, 0))
  146. if ((int)count == 0)
  147. rwsem_wake(sem);
  148. }
  149. static inline void rwsem_atomic_add(long val, struct rw_semaphore *sem)
  150. {
  151. #ifndef CONFIG_SMP
  152. sem->count += val;
  153. #else
  154. long temp;
  155. __asm__ __volatile__(
  156. "1: ldq_l %0,%1n"
  157. " addq %0,%2,%0n"
  158. " stq_c %0,%1n"
  159. " beq %0,2fn"
  160. ".subsection 2n"
  161. "2: br 1bn"
  162. ".previous"
  163. :"=&r" (temp), "=m" (sem->count)
  164. :"Ir" (val), "m" (sem->count));
  165. #endif
  166. }
  167. static inline long rwsem_atomic_update(long val, struct rw_semaphore *sem)
  168. {
  169. #ifndef CONFIG_SMP
  170. sem->count += val;
  171. return sem->count;
  172. #else
  173. long ret, temp;
  174. __asm__ __volatile__(
  175. "1: ldq_l %0,%1n"
  176. " addq  %0,%3,%2n"
  177. " addq %0,%3,%0n"
  178. " stq_c %2,%1n"
  179. " beq %2,2fn"
  180. ".subsection 2n"
  181. "2: br 1bn"
  182. ".previous"
  183. :"=&r" (ret), "=m" (sem->count), "=&r" (temp)
  184. :"Ir" (val), "m" (sem->count));
  185. return ret;
  186. #endif
  187. }
  188. #endif /* __KERNEL__ */
  189. #endif /* _ALPHA_RWSEM_H */