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

Linux/Unix编程

开发平台:

Unix_Linux

  1. #ifndef __ASM_SPINLOCK_H
  2. #define __ASM_SPINLOCK_H
  3. /*
  4.  * Simple spin lock operations.  
  5.  *
  6.  * Copyright (C) 2001 Paul Mackerras <paulus@au.ibm.com>, IBM
  7.  * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
  8.  *
  9.  * Type of int is used as a full 64b word is not necessary.
  10.  *
  11.  * This program is free software; you can redistribute it and/or
  12.  * modify it under the terms of the GNU General Public License
  13.  * as published by the Free Software Foundation; either version
  14.  * 2 of the License, or (at your option) any later version.
  15.  */
  16. typedef struct {
  17. volatile unsigned int lock;
  18. } spinlock_t;
  19. #ifdef __KERNEL__
  20. #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
  21. #define spin_is_locked(x) ((x)->lock != 0)
  22. static __inline__ int spin_trylock(spinlock_t *lock)
  23. {
  24. unsigned int tmp;
  25. __asm__ __volatile__(
  26. "1: lwarx %0,0,%1 # spin_trylockn
  27. cmpwi 0,%0,0n
  28. li %0,0n
  29. bne- 2fn
  30. li %0,1n
  31. stwcx. %0,0,%1n
  32. bne- 1bn
  33. isyncn
  34. 2:" : "=&r"(tmp)
  35. : "r"(&lock->lock)
  36. : "cr0", "memory");
  37. return tmp;
  38. }
  39. static __inline__ void spin_lock(spinlock_t *lock)
  40. {
  41. unsigned int tmp;
  42. __asm__ __volatile__(
  43. "b 2f # spin_lockn
  44. 1: or 1,1,1 # spin at low priorityn
  45. lwzx %0,0,%1n
  46. cmpwi 0,%0,0n
  47. bne+ 1bn
  48. or 2,2,2 # back to medium priorityn
  49. 2: lwarx %0,0,%1n
  50. cmpwi 0,%0,0n
  51. bne- 1bn
  52. stwcx. %2,0,%1n
  53. bne- 2bn
  54. isync"
  55. : "=&r"(tmp)
  56. : "r"(&lock->lock), "r"(1)
  57. : "cr0", "memory");
  58. }
  59. static __inline__ void spin_unlock(spinlock_t *lock)
  60. {
  61. __asm__ __volatile__("lwsync # spin_unlock": : :"memory");
  62. lock->lock = 0;
  63. }
  64. /*
  65.  * Read-write spinlocks, allowing multiple readers
  66.  * but only one writer.
  67.  *
  68.  * NOTE! it is quite common to have readers in interrupts
  69.  * but no interrupt writers. For those circumstances we
  70.  * can "mix" irq-safe locks - any writer needs to get a
  71.  * irq-safe write-lock, but readers can get non-irqsafe
  72.  * read-locks.
  73.  */
  74. typedef struct {
  75. volatile signed int lock;
  76. } rwlock_t;
  77. #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
  78. static __inline__ int read_trylock(rwlock_t *rw)
  79. {
  80. unsigned int tmp;
  81. unsigned int ret;
  82. __asm__ __volatile__(
  83. "1: lwarx %0,0,%2 # read_trylockn
  84. li %1,0n
  85. extsw %0,%0n
  86. addic. %0,%0,1n
  87. ble- 2fn
  88. stwcx. %0,0,%2n
  89. bne- 1bn
  90. li %1,1n
  91. isyncn
  92. 2:" : "=&r"(tmp), "=&r"(ret)
  93. : "r"(&rw->lock)
  94. : "cr0", "memory");
  95. return ret;
  96. }
  97. static __inline__ void read_lock(rwlock_t *rw)
  98. {
  99. unsigned int tmp;
  100. __asm__ __volatile__(
  101. "b 2f # read_lockn
  102. 1: or 1,1,1 # spin at low priorityn
  103. lwax %0,0,%1n
  104. cmpwi 0,%0,0n
  105. blt+ 1bn
  106. or 2,2,2 # back to medium priorityn
  107. 2: lwarx %0,0,%1n
  108. extsw %0,%0n
  109. addic. %0,%0,1n
  110. ble- 1bn
  111. stwcx. %0,0,%1n
  112. bne- 2bn
  113. isync"
  114. : "=&r"(tmp)
  115. : "r"(&rw->lock)
  116. : "cr0", "memory");
  117. }
  118. static __inline__ void read_unlock(rwlock_t *rw)
  119. {
  120. unsigned int tmp;
  121. __asm__ __volatile__(
  122. "lwsync # read_unlockn
  123. 1: lwarx %0,0,%1n
  124. addic %0,%0,-1n
  125. stwcx. %0,0,%1n
  126. bne- 1b"
  127. : "=&r"(tmp)
  128. : "r"(&rw->lock)
  129. : "cr0", "memory");
  130. }
  131. static __inline__ int write_trylock(rwlock_t *rw)
  132. {
  133. unsigned int tmp;
  134. unsigned int ret;
  135. __asm__ __volatile__(
  136. "1: lwarx %0,0,%2 # write_trylockn
  137. cmpwi 0,%0,0n
  138. li %1,0n
  139. bne- 2fn
  140. stwcx. %3,0,%2n
  141. bne- 1bn
  142. li %1,1n
  143. isyncn
  144. 2:" : "=&r"(tmp), "=&r"(ret)
  145. : "r"(&rw->lock), "r"(-1)
  146. : "cr0", "memory");
  147. return ret;
  148. }
  149. static __inline__ void write_lock(rwlock_t *rw)
  150. {
  151. unsigned int tmp;
  152. __asm__ __volatile__(
  153. "b 2f # write_lockn
  154. 1: or 1,1,1 # spin at low priorityn
  155. lwax %0,0,%1n
  156. cmpwi 0,%0,0n
  157. bne+ 1bn
  158. or 2,2,2 # back to medium priorityn
  159. 2: lwarx %0,0,%1n
  160. cmpwi 0,%0,0n
  161. bne- 1bn
  162. stwcx. %2,0,%1n
  163. bne- 2bn
  164. isync"
  165. : "=&r"(tmp)
  166. : "r"(&rw->lock), "r"(-1)
  167. : "cr0", "memory");
  168. }
  169. static __inline__ void write_unlock(rwlock_t *rw)
  170. {
  171. __asm__ __volatile__("lwsync # write_unlock": : :"memory");
  172. rw->lock = 0;
  173. }
  174. static __inline__ int is_read_locked(rwlock_t *rw)
  175. {
  176. return rw->lock > 0;
  177. }
  178. static __inline__ int is_write_locked(rwlock_t *rw)
  179. {
  180. return rw->lock < 0;
  181. }
  182. #define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
  183. #define spin_unlock_wait(x)    do { barrier(); } while(spin_is_locked(x))
  184. #define rwlock_init(x)         do { *(x) = RW_LOCK_UNLOCKED; } while(0)
  185. #endif /* __KERNEL__ */
  186. #endif /* __ASM_SPINLOCK_H */