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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: rwsem.h,v 1.5 2001/11/18 00:12:56 davem Exp $
  2.  * rwsem.h: R/W semaphores implemented using CAS
  3.  *
  4.  * Written by David S. Miller (davem@redhat.com), 2001.
  5.  * Derived from asm-i386/rwsem.h
  6.  */
  7. #ifndef _SPARC64_RWSEM_H
  8. #define _SPARC64_RWSEM_H
  9. #ifndef _LINUX_RWSEM_H
  10. #error please dont include asm/rwsem.h directly, use linux/rwsem.h instead
  11. #endif
  12. #ifdef __KERNEL__
  13. #include <linux/list.h>
  14. #include <linux/spinlock.h>
  15. struct rwsem_waiter;
  16. extern struct rw_semaphore *FASTCALL(rwsem_down_read_failed(struct rw_semaphore *sem));
  17. extern struct rw_semaphore *FASTCALL(rwsem_down_write_failed(struct rw_semaphore *sem));
  18. extern struct rw_semaphore *FASTCALL(rwsem_wake(struct rw_semaphore *));
  19. struct rw_semaphore {
  20. signed int count;
  21. #define RWSEM_UNLOCKED_VALUE 0x00000000
  22. #define RWSEM_ACTIVE_BIAS 0x00000001
  23. #define RWSEM_ACTIVE_MASK 0x0000ffff
  24. #define RWSEM_WAITING_BIAS 0xffff0000
  25. #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
  26. #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
  27. spinlock_t wait_lock;
  28. struct list_head wait_list;
  29. };
  30. #define __RWSEM_INITIALIZER(name) 
  31. { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) }
  32. #define DECLARE_RWSEM(name) 
  33. struct rw_semaphore name = __RWSEM_INITIALIZER(name)
  34. static inline void init_rwsem(struct rw_semaphore *sem)
  35. {
  36. sem->count = RWSEM_UNLOCKED_VALUE;
  37. spin_lock_init(&sem->wait_lock);
  38. INIT_LIST_HEAD(&sem->wait_list);
  39. }
  40. static inline void __down_read(struct rw_semaphore *sem)
  41. {
  42. __asm__ __volatile__(
  43. "! beginning __down_readn"
  44. "1:tlduw [%0], %%g5nt"
  45. "add %%g5, 1, %%g7nt"
  46. "cas [%0], %%g5, %%g7nt"
  47. "cmp %%g5, %%g7nt"
  48. "bne,pn %%icc, 1bnt"
  49. " add %%g7, 1, %%g7nt"
  50. "cmp %%g7, 0nt"
  51. "bl,pn %%icc, 3fnt"
  52. " membar #StoreLoad | #StoreStoren"
  53. "2:nt"
  54. ".subsection 2n"
  55. "3:tmov %0, %%g5nt"
  56. "save %%sp, -160, %%spnt"
  57. "mov %%g1, %%l1nt"
  58. "mov %%g2, %%l2nt"
  59. "mov %%g3, %%l3nt"
  60. "call %1nt"
  61. " mov %%g5, %%o0nt"
  62. "mov %%l1, %%g1nt"
  63. "mov %%l2, %%g2nt"
  64. "ba,pt %%xcc, 2bnt"
  65. " restore %%l3, %%g0, %%g3nt"
  66. ".previousnt"
  67. "! ending __down_read"
  68. : : "r" (sem), "i" (rwsem_down_read_failed)
  69. : "g5", "g7", "memory", "cc");
  70. }
  71. static __inline__ int __down_read_trylock(struct rw_semaphore *sem)
  72. {
  73. int result;
  74. __asm__ __volatile__(
  75. "! beginning __down_read_trylockn"
  76. "1:tlduw [%1], %%g5nt"
  77. "add %%g5, 1, %%g7nt"
  78. "cmp %%g7, 0nt"
  79. "bl,pn %%icc, 2fnt"
  80. " mov 0, %0nt"
  81. "cas [%1], %%g5, %%g7nt"
  82. "cmp %%g5, %%g7nt"
  83. "bne,pn %%icc, 1bnt"
  84. " mov 1, %0nt"
  85. "membar #StoreLoad | #StoreStoren"
  86. "2:nt"
  87. "! ending __down_read_trylock"
  88. : "=&r" (result)
  89.                 : "r" (sem)
  90. : "g5", "g7", "memory", "cc");
  91. return result;
  92. }
  93. static inline void __down_write(struct rw_semaphore *sem)
  94. {
  95. __asm__ __volatile__(
  96. "! beginning __down_writent"
  97. "sethi %%hi(%2), %%g1nt"
  98. "or %%g1, %%lo(%2), %%g1n"
  99. "1:tlduw [%0], %%g5nt"
  100. "add %%g5, %%g1, %%g7nt"
  101. "cas [%0], %%g5, %%g7nt"
  102. "cmp %%g5, %%g7nt"
  103. "bne,pn %%icc, 1bnt"
  104. " cmp %%g7, 0nt"
  105. "bne,pn %%icc, 3fnt"
  106. " membar #StoreLoad | #StoreStoren"
  107. "2:nt"
  108. ".subsection 2n"
  109. "3:tmov %0, %%g5nt"
  110. "save %%sp, -160, %%spnt"
  111. "mov %%g2, %%l2nt"
  112. "mov %%g3, %%l3nt"
  113. "call %1nt"
  114. " mov %%g5, %%o0nt"
  115. "mov %%l2, %%g2nt"
  116. "ba,pt %%xcc, 2bnt"
  117. " restore %%l3, %%g0, %%g3nt"
  118. ".previousnt"
  119. "! ending __down_write"
  120. : : "r" (sem), "i" (rwsem_down_write_failed),
  121.     "i" (RWSEM_ACTIVE_WRITE_BIAS)
  122. : "g1", "g5", "g7", "memory", "cc");
  123. }
  124. static __inline__ int __down_write_trylock(struct rw_semaphore *sem)
  125. {
  126. int result;
  127. __asm__ __volatile__(
  128. "! beginning __down_write_trylocknt"
  129. "sethi %%hi(%2), %%g1nt"
  130. "or %%g1, %%lo(%2), %%g1n"
  131. "1:tlduw [%1], %%g5nt"
  132. "cmp %%g5, 0nt"
  133. "bne,pn %%icc, 2fnt"
  134. " mov 0, %0nt"
  135. "add %%g5, %%g1, %%g7nt"
  136. "cas [%1], %%g5, %%g7nt"
  137. "cmp %%g5, %%g7nt"
  138. "bne,pn %%icc, 1bnt"
  139. " mov 1, %0nt"
  140. "membar #StoreLoad | #StoreStoren"
  141. "2:nt"
  142. "! ending __down_write_trylock"
  143. : "=&r" (result)
  144. : "r" (sem), "i" (RWSEM_ACTIVE_WRITE_BIAS)
  145. : "g1", "g5", "g7", "memory", "cc");
  146. return result;
  147. }
  148. static inline void __up_read(struct rw_semaphore *sem)
  149. {
  150. __asm__ __volatile__(
  151. "! beginning __up_readnt"
  152. "1:tlduw [%0], %%g5nt"
  153. "sub %%g5, 1, %%g7nt"
  154. "cas [%0], %%g5, %%g7nt"
  155. "cmp %%g5, %%g7nt"
  156. "bne,pn %%icc, 1bnt"
  157. " cmp %%g7, 0nt"
  158. "bl,pn %%icc, 3fnt"
  159. " membar #StoreLoad | #StoreStoren"
  160. "2:nt"
  161. ".subsection 2n"
  162. "3:tsethi %%hi(%2), %%g1nt"
  163. "sub %%g7, 1, %%g7nt"
  164. "or %%g1, %%lo(%2), %%g1nt"
  165. "andcc %%g7, %%g1, %%g0nt"
  166. "bne,pn %%icc, 2bnt"
  167. " mov %0, %%g5nt"
  168. "save %%sp, -160, %%spnt"
  169. "mov %%g2, %%l2nt"
  170. "mov %%g3, %%l3nt"
  171. "call %1nt"
  172. " mov %%g5, %%o0nt"
  173. "mov %%l2, %%g2nt"
  174. "ba,pt %%xcc, 2bnt"
  175. " restore %%l3, %%g0, %%g3nt"
  176. ".previousnt"
  177. "! ending __up_read"
  178. : : "r" (sem), "i" (rwsem_wake),
  179.     "i" (RWSEM_ACTIVE_MASK)
  180. : "g1", "g5", "g7", "memory", "cc");
  181. }
  182. static inline void __up_write(struct rw_semaphore *sem)
  183. {
  184. __asm__ __volatile__(
  185. "! beginning __up_writent"
  186. "sethi %%hi(%2), %%g1nt"
  187. "or %%g1, %%lo(%2), %%g1n"
  188. "1:tlduw [%0], %%g5nt"
  189. "sub %%g5, %%g1, %%g7nt"
  190. "cas [%0], %%g5, %%g7nt"
  191. "cmp %%g5, %%g7nt"
  192. "bne,pn %%icc, 1bnt"
  193. " sub %%g7, %%g1, %%g7nt"
  194. "cmp %%g7, 0nt"
  195. "bl,pn %%icc, 3fnt"
  196. " membar #StoreLoad | #StoreStoren"
  197. "2:nt"
  198. ".subsection 2n"
  199. "3:tmov %0, %%g5nt"
  200. "save %%sp, -160, %%spnt"
  201. "mov %%g2, %%l2nt"
  202. "mov %%g3, %%l3nt"
  203. "call %1nt"
  204. " mov %%g5, %%o0nt"
  205. "mov %%l2, %%g2nt"
  206. "ba,pt %%xcc, 2bnt"
  207. " restore %%l3, %%g0, %%g3nt"
  208. ".previousnt"
  209. "! ending __up_write"
  210. : : "r" (sem), "i" (rwsem_wake),
  211.     "i" (RWSEM_ACTIVE_WRITE_BIAS)
  212. : "g1", "g5", "g7", "memory", "cc");
  213. }
  214. static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
  215. {
  216. int tmp = delta;
  217. __asm__ __volatile__(
  218. "1:tlduw [%2], %%g5nt"
  219. "add %%g5, %1, %%g7nt"
  220. "cas [%2], %%g5, %%g7nt"
  221. "cmp %%g5, %%g7nt"
  222. "bne,pn %%icc, 1bnt"
  223. " membar #StoreLoad | #StoreStorent"
  224. "mov %%g7, %0nt"
  225. : "=&r" (tmp)
  226. : "0" (tmp), "r" (sem)
  227. : "g5", "g7", "memory");
  228. return tmp + delta;
  229. }
  230. #define rwsem_atomic_add rwsem_atomic_update
  231. static inline __u16 rwsem_cmpxchgw(struct rw_semaphore *sem, __u16 __old, __u16 __new)
  232. {
  233. u32 old = (sem->count & 0xffff0000) | (u32) __old;
  234. u32 new = (old & 0xffff0000) | (u32) __new;
  235. u32 prev;
  236. again:
  237. __asm__ __volatile__("cas [%2], %3, %0nt"
  238.      "membar #StoreLoad | #StoreStore"
  239.      : "=&r" (prev)
  240.      : "0" (new), "r" (sem), "r" (old)
  241.      : "memory");
  242. /* To give the same semantics as x86 cmpxchgw, keep trying
  243.  * if only the upper 16-bits changed.
  244.  */
  245. if (prev != old &&
  246.     ((prev & 0xffff) == (old & 0xffff)))
  247. goto again;
  248. return prev & 0xffff;
  249. }
  250. static inline signed long rwsem_cmpxchg(struct rw_semaphore *sem, signed long old, signed long new)
  251. {
  252. return cmpxchg(&sem->count,old,new);
  253. }
  254. #endif /* __KERNEL__ */
  255. #endif /* _SPARC64_RWSEM_H */