taslock.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. struct
  8. {
  9. ulong locks;
  10. ulong glare;
  11. ulong inglare;
  12. } lockstats;
  13. static void
  14. dumplockmem(char *tag, Lock *l)
  15. {
  16. uchar *cp;
  17. int i;
  18. iprint("%s: ", tag);
  19. cp = (uchar*)l;
  20. for(i = 0; i < 64; i++)
  21. iprint("%2.2ux ", cp[i]);
  22. iprint("\n");
  23. }
  24. void
  25. lockloop(Lock *l, ulong pc)
  26. {
  27. Proc *p;
  28. p = l->p;
  29. print("lock 0x%lux loop key 0x%lux pc 0x%lux held by pc 0x%lux proc %lud\n",
  30. l, l->key, pc, l->pc, p ? p->pid : 0);
  31. dumpaproc(up);
  32. if(p != nil)
  33. dumpaproc(p);
  34. }
  35. int
  36. lock(Lock *l)
  37. {
  38. int i;
  39. ulong pc;
  40. pc = getcallerpc(&l);
  41. lockstats.locks++;
  42. if(up)
  43. up->nlocks++; /* prevent being scheded */
  44. if(tas(&l->key) == 0){
  45. if(up)
  46. up->lastlock = l;
  47. l->pc = pc;
  48. l->p = up;
  49. l->isilock = 0;
  50. return 0;
  51. }
  52. if(up)
  53. up->nlocks--; /* didn't get the lock, allow scheding */
  54. lockstats.glare++;
  55. for(;;){
  56. lockstats.inglare++;
  57. i = 0;
  58. while(l->key){
  59. if(i++ > 100000000){
  60. i = 0;
  61. lockloop(l, pc);
  62. }
  63. }
  64. if(up)
  65. up->nlocks++;
  66. if(tas(&l->key) == 0){
  67. if(up)
  68. up->lastlock = l;
  69. l->pc = pc;
  70. l->p = up;
  71. l->isilock = 0;
  72. return 1;
  73. }
  74. if(up)
  75. up->nlocks--;
  76. }
  77. return 0; /* For the compiler */
  78. }
  79. void
  80. ilock(Lock *l)
  81. {
  82. ulong x;
  83. ulong pc;
  84. pc = getcallerpc(&l);
  85. lockstats.locks++;
  86. x = splhi();
  87. if(tas(&l->key) == 0){
  88. m->ilockdepth++;
  89. if(up)
  90. up->lastilock = l;
  91. l->sr = x;
  92. l->pc = pc;
  93. l->p = up;
  94. l->isilock = 1;
  95. return;
  96. }
  97. lockstats.glare++;
  98. if(conf.nmach < 2){
  99. dumplockmem("ilock:", l);
  100. panic("ilock: no way out: pc %luX\n", pc);
  101. }
  102. for(;;){
  103. lockstats.inglare++;
  104. splx(x);
  105. while(l->key)
  106. ;
  107. x = splhi();
  108. if(tas(&l->key) == 0){
  109. m->ilockdepth++;
  110. if(up)
  111. up->lastilock = l;
  112. l->sr = x;
  113. l->pc = pc;
  114. l->p = up;
  115. l->isilock = 1;
  116. return;
  117. }
  118. }
  119. }
  120. int
  121. canlock(Lock *l)
  122. {
  123. if(up)
  124. up->nlocks++;
  125. if(tas(&l->key)){
  126. if(up)
  127. up->nlocks--;
  128. return 0;
  129. }
  130. if(up)
  131. up->lastlock = l;
  132. l->pc = getcallerpc(&l);
  133. l->p = up;
  134. l->isilock = 0;
  135. return 1;
  136. }
  137. void
  138. unlock(Lock *l)
  139. {
  140. if(l->key == 0)
  141. print("unlock: not locked: pc %luX\n", getcallerpc(&l));
  142. if(l->isilock)
  143. print("unlock of ilock: pc %lux, held by %lux\n", getcallerpc(&l), l->pc);
  144. if(l->p != up)
  145. print("unlock: up changed: pc %lux, acquired at pc %lux, lock p 0x%p, unlock up 0x%p\n", getcallerpc(&l), l->pc, l->p, up);
  146. l->key = 0;
  147. coherence();
  148. if(up)
  149. --up->nlocks;
  150. }
  151. void
  152. iunlock(Lock *l)
  153. {
  154. ulong sr;
  155. if(l->key == 0)
  156. print("iunlock: not locked: pc %luX\n", getcallerpc(&l));
  157. if(!l->isilock)
  158. print("iunlock of lock: pc %lux, held by %lux\n", getcallerpc(&l), l->pc);
  159. if(islo())
  160. print("iunlock while lo: pc %lux, held by %lux\n", getcallerpc(&l), l->pc);
  161. sr = l->sr;
  162. l->key = 0;
  163. coherence();
  164. m->splpc = getcallerpc(&l);
  165. m->ilockdepth--;
  166. if(up)
  167. up->lastilock = nil;
  168. splxpc(sr);
  169. }