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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: debuglocks.c,v 1.11 2001/09/20 00:35:31 davem Exp $
  2.  * debuglocks.c: Debugging versions of SMP locking primitives.
  3.  *
  4.  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  5.  * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au)
  6.  */
  7. #include <linux/kernel.h>
  8. #include <linux/sched.h>
  9. #include <linux/threads.h> /* For NR_CPUS */
  10. #include <linux/spinlock.h>
  11. #include <asm/psr.h>
  12. #include <asm/system.h>
  13. /* To enable this code, just define SPIN_LOCK_DEBUG in asm/spinlock.h */
  14. #ifdef SPIN_LOCK_DEBUG
  15. /* Some notes on how these debugging routines work.  When a lock is acquired
  16.  * an extra debugging member lock->owner_pc is set to the caller of the lock
  17.  * acquisition routine.  Right before releasing a lock, the debugging program
  18.  * counter is cleared to zero.
  19.  *
  20.  * Furthermore, since PC's are 4 byte aligned on Sparc, we stuff the CPU
  21.  * number of the owner in the lowest two bits.
  22.  */
  23. #define STORE_CALLER(A) __asm__ __volatile__("mov %%i7, %0" : "=r" (A));
  24. static inline void show(char *str, spinlock_t *lock, unsigned long caller)
  25. {
  26. int cpu = smp_processor_id();
  27. printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)n",str,
  28. lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
  29. }
  30. static inline void show_read(char *str, rwlock_t *lock, unsigned long caller)
  31. {
  32. int cpu = smp_processor_id();
  33. printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)n", str,
  34. lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
  35. }
  36. static inline void show_write(char *str, rwlock_t *lock, unsigned long caller)
  37. {
  38. int cpu = smp_processor_id();
  39. int i;
  40. printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)", str,
  41. lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
  42. for(i = 0; i < NR_CPUS; i++)
  43. printk(" reader[%d]=%08lx", i, lock->reader_pc[i]);
  44. printk("n");
  45. }
  46. #undef INIT_STUCK
  47. #define INIT_STUCK 100000000
  48. void _do_spin_lock(spinlock_t *lock, char *str)
  49. {
  50. unsigned long caller;
  51. unsigned long val;
  52. int cpu = smp_processor_id();
  53. int stuck = INIT_STUCK;
  54. STORE_CALLER(caller);
  55. again:
  56. __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
  57. if(val) {
  58. while(lock->lock) {
  59. if (!--stuck) {
  60. show(str, lock, caller);
  61. stuck = INIT_STUCK;
  62. }
  63. barrier();
  64. }
  65. goto again;
  66. }
  67. lock->owner_pc = (cpu & 3) | (caller & ~3);
  68. }
  69. int _spin_trylock(spinlock_t *lock)
  70. {
  71. unsigned long val;
  72. unsigned long caller;
  73. int cpu = smp_processor_id();
  74. STORE_CALLER(caller);
  75. __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
  76. if(!val) {
  77. /* We got it, record our identity for debugging. */
  78. lock->owner_pc = (cpu & 3) | (caller & ~3);
  79. }
  80. return val == 0;
  81. }
  82. void _do_spin_unlock(spinlock_t *lock)
  83. {
  84. lock->owner_pc = 0;
  85. barrier();
  86. lock->lock = 0;
  87. }
  88. void _do_read_lock(rwlock_t *rw, char *str)
  89. {
  90. unsigned long caller;
  91. unsigned long val;
  92. int cpu = smp_processor_id();
  93. int stuck = INIT_STUCK;
  94. STORE_CALLER(caller);
  95. wlock_again:
  96. __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
  97. if(val) {
  98. while(rw->lock & 0xff) {
  99. if (!--stuck) {
  100. show_read(str, rw, caller);
  101. stuck = INIT_STUCK;
  102. }
  103. barrier();
  104. }
  105. goto wlock_again;
  106. }
  107. rw->reader_pc[cpu] = caller;
  108. barrier();
  109. rw->lock++;
  110. }
  111. void _do_read_unlock(rwlock_t *rw, char *str)
  112. {
  113. unsigned long caller;
  114. unsigned long val;
  115. int cpu = smp_processor_id();
  116. int stuck = INIT_STUCK;
  117. STORE_CALLER(caller);
  118. wlock_again:
  119. __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
  120. if(val) {
  121. while(rw->lock & 0xff) {
  122. if (!--stuck) {
  123. show_read(str, rw, caller);
  124. stuck = INIT_STUCK;
  125. }
  126. barrier();
  127. }
  128. goto wlock_again;
  129. }
  130. rw->reader_pc[cpu] = 0;
  131. barrier();
  132. rw->lock -= 0x1ff;
  133. }
  134. void _do_write_lock(rwlock_t *rw, char *str)
  135. {
  136. unsigned long caller;
  137. unsigned long val;
  138. int cpu = smp_processor_id();
  139. int stuck = INIT_STUCK;
  140. STORE_CALLER(caller);
  141. wlock_again:
  142. __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
  143. if(val) {
  144. wlock_wait:
  145. while(rw->lock) {
  146. if (!--stuck) {
  147. show_write(str, rw, caller);
  148. stuck = INIT_STUCK;
  149. }
  150. barrier();
  151. }
  152. goto wlock_again;
  153. }
  154. if (rw->lock & ~0xff) {
  155. *(((unsigned char *)&rw->lock)+3) = 0;
  156. barrier();
  157. goto wlock_wait;
  158. }
  159. barrier();
  160. rw->owner_pc = (cpu & 3) | (caller & ~3);
  161. }
  162. void _do_write_unlock(rwlock_t *rw)
  163. {
  164. rw->owner_pc = 0;
  165. barrier();
  166. rw->lock = 0;
  167. }
  168. #endif /* SPIN_LOCK_DEBUG */