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

Linux/Unix编程

开发平台:

Unix_Linux

  1. #ifndef __LINUX_BRLOCK_H
  2. #define __LINUX_BRLOCK_H
  3. /*
  4.  * 'Big Reader' read-write spinlocks.
  5.  *
  6.  * super-fast read/write locks, with write-side penalty. The point
  7.  * is to have a per-CPU read/write lock. Readers lock their CPU-local
  8.  * readlock, writers must lock all locks to get write access. These
  9.  * CPU-read-write locks are semantically identical to normal rwlocks.
  10.  * Memory usage is higher as well. (NR_CPUS*L1_CACHE_BYTES bytes)
  11.  *
  12.  * The most important feature is that these spinlocks do not cause
  13.  * cacheline ping-pong in the 'most readonly data' case.
  14.  *
  15.  * Copyright 2000, Ingo Molnar <mingo@redhat.com>
  16.  *
  17.  * Registry idea and naming [ crutial! :-) ] by:
  18.  *
  19.  *                 David S. Miller <davem@redhat.com>
  20.  *
  21.  * David has an implementation that doesn't use atomic operations in
  22.  * the read branch via memory ordering tricks - i guess we need to
  23.  * split this up into a per-arch thing? The atomicity issue is a
  24.  * secondary item in profiles, at least on x86 platforms.
  25.  *
  26.  * The atomic op version overhead is indeed a big deal on
  27.  * load-locked/store-conditional cpus (ALPHA/MIPS/PPC) and
  28.  * compare-and-swap cpus (Sparc64).  So we control which
  29.  * implementation to use with a __BRLOCK_USE_ATOMICS define. -DaveM
  30.  */
  31. /* Register bigreader lock indices here. */
  32. enum brlock_indices {
  33. BR_GLOBALIRQ_LOCK,
  34. BR_NETPROTO_LOCK,
  35. __BR_END
  36. };
  37. #include <linux/config.h>
  38. #ifdef CONFIG_SMP
  39. #include <linux/cache.h>
  40. #include <linux/spinlock.h>
  41. #if defined(__i386__) || defined(__ia64__) || defined(__x86_64__)
  42. #define __BRLOCK_USE_ATOMICS
  43. #else
  44. #undef __BRLOCK_USE_ATOMICS
  45. #endif
  46. #ifdef __BRLOCK_USE_ATOMICS
  47. typedef rwlock_t brlock_read_lock_t;
  48. #else
  49. typedef unsigned int brlock_read_lock_t;
  50. #endif
  51. /*
  52.  * align last allocated index to the next cacheline:
  53.  */
  54. #define __BR_IDX_MAX 
  55. (((sizeof(brlock_read_lock_t)*__BR_END + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) / sizeof(brlock_read_lock_t))
  56. extern brlock_read_lock_t __brlock_array[NR_CPUS][__BR_IDX_MAX];
  57. #ifndef __BRLOCK_USE_ATOMICS
  58. struct br_wrlock {
  59. spinlock_t lock;
  60. } __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
  61. extern struct br_wrlock __br_write_locks[__BR_IDX_MAX];
  62. #endif
  63. extern void __br_lock_usage_bug (void);
  64. #ifdef __BRLOCK_USE_ATOMICS
  65. static inline void br_read_lock (enum brlock_indices idx)
  66. {
  67. /*
  68.  * This causes a link-time bug message if an
  69.  * invalid index is used:
  70.  */
  71. if (idx >= __BR_END)
  72. __br_lock_usage_bug();
  73. read_lock(&__brlock_array[smp_processor_id()][idx]);
  74. }
  75. static inline void br_read_unlock (enum brlock_indices idx)
  76. {
  77. if (idx >= __BR_END)
  78. __br_lock_usage_bug();
  79. read_unlock(&__brlock_array[smp_processor_id()][idx]);
  80. }
  81. #else /* ! __BRLOCK_USE_ATOMICS */
  82. static inline void br_read_lock (enum brlock_indices idx)
  83. {
  84. unsigned int *ctr;
  85. spinlock_t *lock;
  86. /*
  87.  * This causes a link-time bug message if an
  88.  * invalid index is used:
  89.  */
  90. if (idx >= __BR_END)
  91. __br_lock_usage_bug();
  92. ctr = &__brlock_array[smp_processor_id()][idx];
  93. lock = &__br_write_locks[idx].lock;
  94. again:
  95. (*ctr)++;
  96. mb();
  97. if (spin_is_locked(lock)) {
  98. (*ctr)--;
  99. wmb(); /*
  100. * The release of the ctr must become visible
  101. * to the other cpus eventually thus wmb(),
  102. * we don't care if spin_is_locked is reordered
  103. * before the releasing of the ctr.
  104. * However IMHO this wmb() is superflous even in theory.
  105. * It would not be superflous only if on the
  106. * other CPUs doing a ldl_l instead of an ldl
  107. * would make a difference and I don't think this is
  108. * the case.
  109. * I'd like to clarify this issue further
  110. * but for now this is a slow path so adding the
  111. * wmb() will keep us on the safe side.
  112. */
  113. while (spin_is_locked(lock))
  114. barrier();
  115. goto again;
  116. }
  117. }
  118. static inline void br_read_unlock (enum brlock_indices idx)
  119. {
  120. unsigned int *ctr;
  121. if (idx >= __BR_END)
  122. __br_lock_usage_bug();
  123. ctr = &__brlock_array[smp_processor_id()][idx];
  124. wmb();
  125. (*ctr)--;
  126. }
  127. #endif /* __BRLOCK_USE_ATOMICS */
  128. /* write path not inlined - it's rare and larger */
  129. extern void FASTCALL(__br_write_lock (enum brlock_indices idx));
  130. extern void FASTCALL(__br_write_unlock (enum brlock_indices idx));
  131. static inline void br_write_lock (enum brlock_indices idx)
  132. {
  133. if (idx >= __BR_END)
  134. __br_lock_usage_bug();
  135. __br_write_lock(idx);
  136. }
  137. static inline void br_write_unlock (enum brlock_indices idx)
  138. {
  139. if (idx >= __BR_END)
  140. __br_lock_usage_bug();
  141. __br_write_unlock(idx);
  142. }
  143. #else
  144. # define br_read_lock(idx) ((void)(idx))
  145. # define br_read_unlock(idx) ((void)(idx))
  146. # define br_write_lock(idx) ((void)(idx))
  147. # define br_write_unlock(idx) ((void)(idx))
  148. #endif
  149. /*
  150.  * Now enumerate all of the possible sw/hw IRQ protected
  151.  * versions of the interfaces.
  152.  */
  153. #define br_read_lock_irqsave(idx, flags) 
  154. do { local_irq_save(flags); br_read_lock(idx); } while (0)
  155. #define br_read_lock_irq(idx) 
  156. do { local_irq_disable(); br_read_lock(idx); } while (0)
  157. #define br_read_lock_bh(idx) 
  158. do { local_bh_disable(); br_read_lock(idx); } while (0)
  159. #define br_write_lock_irqsave(idx, flags) 
  160. do { local_irq_save(flags); br_write_lock(idx); } while (0)
  161. #define br_write_lock_irq(idx) 
  162. do { local_irq_disable(); br_write_lock(idx); } while (0)
  163. #define br_write_lock_bh(idx) 
  164. do { local_bh_disable(); br_write_lock(idx); } while (0)
  165. #define br_read_unlock_irqrestore(idx, flags) 
  166. do { br_read_unlock(irx); local_irq_restore(flags); } while (0)
  167. #define br_read_unlock_irq(idx) 
  168. do { br_read_unlock(idx); local_irq_enable(); } while (0)
  169. #define br_read_unlock_bh(idx) 
  170. do { br_read_unlock(idx); local_bh_enable(); } while (0)
  171. #define br_write_unlock_irqrestore(idx, flags) 
  172. do { br_write_unlock(irx); local_irq_restore(flags); } while (0)
  173. #define br_write_unlock_irq(idx) 
  174. do { br_write_unlock(idx); local_irq_enable(); } while (0)
  175. #define br_write_unlock_bh(idx) 
  176. do { br_write_unlock(idx); local_bh_enable(); } while (0)
  177. #endif /* __LINUX_BRLOCK_H */