taslock.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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. #include "edf.h"
  8. long maxlockcycles;
  9. long maxilockcycles;
  10. long cumlockcycles;
  11. long cumilockcycles;
  12. ulong maxlockpc;
  13. ulong maxilockpc;
  14. struct
  15. {
  16. ulong locks;
  17. ulong glare;
  18. ulong inglare;
  19. } lockstats;
  20. static void
  21. inccnt(Ref *r)
  22. {
  23. _xinc(&r->ref);
  24. }
  25. static int
  26. deccnt(Ref *r)
  27. {
  28. int x;
  29. x = _xdec(&r->ref);
  30. if(x < 0)
  31. panic("deccnt pc=0x%lux", getcallerpc(&r));
  32. return x;
  33. }
  34. static void
  35. dumplockmem(char *tag, Lock *l)
  36. {
  37. uchar *cp;
  38. int i;
  39. iprint("%s: ", tag);
  40. cp = (uchar*)l;
  41. for(i = 0; i < 64; i++)
  42. iprint("%2.2ux ", cp[i]);
  43. iprint("\n");
  44. }
  45. void
  46. lockloop(Lock *l, ulong pc)
  47. {
  48. Proc *p;
  49. p = l->p;
  50. print("lock 0x%lux loop key 0x%lux pc 0x%lux held by pc 0x%lux proc %lud\n",
  51. l, l->key, pc, l->pc, p ? p->pid : 0);
  52. dumpaproc(up);
  53. if(p != nil)
  54. dumpaproc(p);
  55. }
  56. int
  57. lock(Lock *l)
  58. {
  59. int i;
  60. ulong pc;
  61. pc = getcallerpc(&l);
  62. lockstats.locks++;
  63. if(up)
  64. inccnt(&up->nlocks); /* prevent being scheded */
  65. if(tas(&l->key) == 0){
  66. if(up)
  67. up->lastlock = l;
  68. l->pc = pc;
  69. l->p = up;
  70. l->isilock = 0;
  71. #ifdef LOCKCYCLES
  72. l->lockcycles = -lcycles();
  73. #endif
  74. return 0;
  75. }
  76. if(up)
  77. deccnt(&up->nlocks);
  78. lockstats.glare++;
  79. for(;;){
  80. lockstats.inglare++;
  81. i = 0;
  82. while(l->key){
  83. if(conf.nmach < 2 && up && up->edf && (up->edf->flags & Admitted)){
  84. /*
  85. * Priority inversion, yield on a uniprocessor; on a
  86. * multiprocessor, the other processor will unlock
  87. */
  88. print("inversion 0x%lux pc 0x%lux proc %lud held by pc 0x%lux proc %lud\n",
  89. l, pc, up ? up->pid : 0, l->pc, l->p ? l->p->pid : 0);
  90. up->edf->d = todget(nil); /* yield to process with lock */
  91. }
  92. if(i++ > 100000000){
  93. i = 0;
  94. lockloop(l, pc);
  95. }
  96. }
  97. if(up)
  98. inccnt(&up->nlocks);
  99. if(tas(&l->key) == 0){
  100. if(up)
  101. up->lastlock = l;
  102. l->pc = pc;
  103. l->p = up;
  104. l->isilock = 0;
  105. #ifdef LOCKCYCLES
  106. l->lockcycles = -lcycles();
  107. #endif
  108. return 1;
  109. }
  110. if(up)
  111. deccnt(&up->nlocks);
  112. }
  113. }
  114. void
  115. ilock(Lock *l)
  116. {
  117. ulong x;
  118. ulong pc;
  119. pc = getcallerpc(&l);
  120. lockstats.locks++;
  121. x = splhi();
  122. if(tas(&l->key) != 0){
  123. lockstats.glare++;
  124. /*
  125. * Cannot also check l->pc and l->m here because
  126. * they might just not be set yet, or the lock might
  127. * even have been let go.
  128. */
  129. if(!l->isilock){
  130. dumplockmem("ilock:", l);
  131. panic("corrupt ilock %p pc=%luX m=%p isilock=%d",
  132. l, l->pc, l->m, l->isilock);
  133. }
  134. for(;;){
  135. lockstats.inglare++;
  136. splx(x);
  137. while(l->key)
  138. ;
  139. x = splhi();
  140. if(tas(&l->key) == 0)
  141. goto acquire;
  142. }
  143. }
  144. acquire:
  145. m->ilockdepth++;
  146. if(up)
  147. up->lastilock = l;
  148. l->sr = x;
  149. l->pc = pc;
  150. l->p = up;
  151. l->isilock = 1;
  152. l->m = MACHP(m->machno);
  153. #ifdef LOCKCYCLES
  154. l->lockcycles = -lcycles();
  155. #endif
  156. }
  157. int
  158. canlock(Lock *l)
  159. {
  160. if(up)
  161. inccnt(&up->nlocks);
  162. if(tas(&l->key)){
  163. if(up)
  164. deccnt(&up->nlocks);
  165. return 0;
  166. }
  167. if(up)
  168. up->lastlock = l;
  169. l->pc = getcallerpc(&l);
  170. l->p = up;
  171. l->m = MACHP(m->machno);
  172. l->isilock = 0;
  173. #ifdef LOCKCYCLES
  174. l->lockcycles = -lcycles();
  175. #endif
  176. return 1;
  177. }
  178. void
  179. unlock(Lock *l)
  180. {
  181. #ifdef LOCKCYCLES
  182. l->lockcycles += lcycles();
  183. cumlockcycles += l->lockcycles;
  184. if(l->lockcycles > maxlockcycles){
  185. maxlockcycles = l->lockcycles;
  186. maxlockpc = l->pc;
  187. }
  188. #endif
  189. if(l->key == 0)
  190. print("unlock: not locked: pc %luX\n", getcallerpc(&l));
  191. if(l->isilock)
  192. print("unlock of ilock: pc %lux, held by %lux\n", getcallerpc(&l), l->pc);
  193. if(l->p != up)
  194. 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);
  195. l->m = nil;
  196. l->key = 0;
  197. coherence();
  198. if(up && deccnt(&up->nlocks) == 0 && up->delaysched && islo()){
  199. /*
  200. * Call sched if the need arose while locks were held
  201. * But, don't do it from interrupt routines, hence the islo() test
  202. */
  203. sched();
  204. }
  205. }
  206. ulong ilockpcs[0x100] = { [0xff] = 1 };
  207. static int n;
  208. void
  209. iunlock(Lock *l)
  210. {
  211. ulong sr;
  212. #ifdef LOCKCYCLES
  213. l->lockcycles += lcycles();
  214. cumilockcycles += l->lockcycles;
  215. if(l->lockcycles > maxilockcycles){
  216. maxilockcycles = l->lockcycles;
  217. maxilockpc = l->pc;
  218. }
  219. if(l->lockcycles > 2400)
  220. ilockpcs[n++ & 0xff] = l->pc;
  221. #endif
  222. if(l->key == 0)
  223. print("iunlock: not locked: pc %luX\n", getcallerpc(&l));
  224. if(!l->isilock)
  225. print("iunlock of lock: pc %lux, held by %lux\n", getcallerpc(&l), l->pc);
  226. if(islo())
  227. print("iunlock while lo: pc %lux, held by %lux\n", getcallerpc(&l), l->pc);
  228. sr = l->sr;
  229. l->m = nil;
  230. l->key = 0;
  231. coherence();
  232. m->ilockdepth--;
  233. if(up)
  234. up->lastilock = nil;
  235. splx(sr);
  236. }