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

Linux/Unix编程

开发平台:

Unix_Linux

  1. #ifndef __ASM_SPINLOCK_H
  2. #define __ASM_SPINLOCK_H
  3. #include <asm/atomic.h>
  4. #include <asm/rwlock.h>
  5. #include <asm/page.h>
  6. #include <linux/config.h>
  7. extern int printk(const char * fmt, ...)
  8. __attribute__ ((format (printf, 1, 2)));
  9. /* It seems that people are forgetting to
  10.  * initialize their spinlocks properly, tsk tsk.
  11.  * Remember to turn this off in 2.4. -ben
  12.  */
  13. #if defined(CONFIG_DEBUG_SPINLOCK)
  14. #define SPINLOCK_DEBUG 1
  15. #else
  16. #define SPINLOCK_DEBUG 0
  17. #endif
  18. /*
  19.  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  20.  */
  21. typedef struct {
  22. volatile unsigned int lock;
  23. #if SPINLOCK_DEBUG
  24. unsigned magic;
  25. #endif
  26. } spinlock_t;
  27. #define SPINLOCK_MAGIC 0xdead4ead
  28. #if SPINLOCK_DEBUG
  29. #define SPINLOCK_MAGIC_INIT , SPINLOCK_MAGIC
  30. #else
  31. #define SPINLOCK_MAGIC_INIT /* */
  32. #endif
  33. #define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT }
  34. #define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
  35. /*
  36.  * Simple spin lock operations.  There are two variants, one clears IRQ's
  37.  * on the local processor, one does not.
  38.  *
  39.  * We make no fairness assumptions. They have a cost.
  40.  */
  41. #define spin_is_locked(x) (*(volatile signed char *)(&(x)->lock) <= 0)
  42. #define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
  43. #define spin_lock_string 
  44. "n1:t" 
  45. "lock ; decb %0nt" 
  46. "js 2fn" 
  47. LOCK_SECTION_START("") 
  48. "2:t" 
  49. "cmpb $0,%0nt" 
  50. "rep;nopnt" 
  51. "jle 2bnt" 
  52. "jmp 1bn" 
  53. LOCK_SECTION_END
  54. /*
  55.  * This works. Despite all the confusion.
  56.  * (except on PPro SMP or if we are using OOSTORE)
  57.  * (PPro errata 66, 92)
  58.  */
  59.  
  60. #if !defined(CONFIG_X86_OOSTORE) && !defined(CONFIG_X86_PPRO_FENCE)
  61. #define spin_unlock_string 
  62. "movb $1,%0" 
  63. :"=m" (lock->lock) : : "memory"
  64. static inline void spin_unlock(spinlock_t *lock)
  65. {
  66. #if SPINLOCK_DEBUG
  67. if (lock->magic != SPINLOCK_MAGIC)
  68. BUG();
  69. if (!spin_is_locked(lock))
  70. BUG();
  71. #endif
  72. __asm__ __volatile__(
  73. spin_unlock_string
  74. );
  75. }
  76. #else
  77. #define spin_unlock_string 
  78. "xchgb %b0, %1" 
  79. :"=q" (oldval), "=m" (lock->lock) 
  80. :"0" (oldval) : "memory"
  81. static inline void spin_unlock(spinlock_t *lock)
  82. {
  83. char oldval = 1;
  84. #if SPINLOCK_DEBUG
  85. if (lock->magic != SPINLOCK_MAGIC)
  86. BUG();
  87. if (!spin_is_locked(lock))
  88. BUG();
  89. #endif
  90. __asm__ __volatile__(
  91. spin_unlock_string
  92. );
  93. }
  94. #endif
  95. static inline int spin_trylock(spinlock_t *lock)
  96. {
  97. char oldval;
  98. __asm__ __volatile__(
  99. "xchgb %b0,%1"
  100. :"=q" (oldval), "=m" (lock->lock)
  101. :"0" (0) : "memory");
  102. return oldval > 0;
  103. }
  104. static inline void spin_lock(spinlock_t *lock)
  105. {
  106. #if SPINLOCK_DEBUG
  107. __label__ here;
  108. here:
  109. if (lock->magic != SPINLOCK_MAGIC) {
  110. printk("eip: %pn", &&here);
  111. BUG();
  112. }
  113. #endif
  114. __asm__ __volatile__(
  115. spin_lock_string
  116. :"=m" (lock->lock) : : "memory");
  117. }
  118. /*
  119.  * Read-write spinlocks, allowing multiple readers
  120.  * but only one writer.
  121.  *
  122.  * NOTE! it is quite common to have readers in interrupts
  123.  * but no interrupt writers. For those circumstances we
  124.  * can "mix" irq-safe locks - any writer needs to get a
  125.  * irq-safe write-lock, but readers can get non-irqsafe
  126.  * read-locks.
  127.  */
  128. typedef struct {
  129. volatile unsigned int lock;
  130. #if SPINLOCK_DEBUG
  131. unsigned magic;
  132. #endif
  133. } rwlock_t;
  134. #define RWLOCK_MAGIC 0xdeaf1eed
  135. #if SPINLOCK_DEBUG
  136. #define RWLOCK_MAGIC_INIT , RWLOCK_MAGIC
  137. #else
  138. #define RWLOCK_MAGIC_INIT /* */
  139. #endif
  140. #define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
  141. #define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
  142. /*
  143.  * On x86, we implement read-write locks as a 32-bit counter
  144.  * with the high bit (sign) being the "contended" bit.
  145.  *
  146.  * The inline assembly is non-obvious. Think about it.
  147.  *
  148.  * Changed to use the same technique as rw semaphores.  See
  149.  * semaphore.h for details.  -ben
  150.  */
  151. /* the spinlock helpers are in arch/i386/kernel/semaphore.c */
  152. static inline void read_lock(rwlock_t *rw)
  153. {
  154. #if SPINLOCK_DEBUG
  155. if (rw->magic != RWLOCK_MAGIC)
  156. BUG();
  157. #endif
  158. __build_read_lock(rw, "__read_lock_failed");
  159. }
  160. static inline void write_lock(rwlock_t *rw)
  161. {
  162. #if SPINLOCK_DEBUG
  163. if (rw->magic != RWLOCK_MAGIC)
  164. BUG();
  165. #endif
  166. __build_write_lock(rw, "__write_lock_failed");
  167. }
  168. #define read_unlock(rw) asm volatile("lock ; incl %0" :"=m" ((rw)->lock) : : "memory")
  169. #define write_unlock(rw) asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory")
  170. static inline int write_trylock(rwlock_t *lock)
  171. {
  172. atomic_t *count = (atomic_t *)lock;
  173. if (atomic_sub_and_test(RW_LOCK_BIAS, count))
  174. return 1;
  175. atomic_add(RW_LOCK_BIAS, count);
  176. return 0;
  177. }
  178. #endif /* __ASM_SPINLOCK_H */