taslock.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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=%#p", 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 %#p loop key %#lux pc %#lux held by pc %#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 %#p pc %#lux proc %lud held by pc %#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, l->m, or l->isilock here
  126. * because they might just not be set yet, or
  127. * (for pc and m) the lock might have just been unlocked.
  128. */
  129. for(;;){
  130. lockstats.inglare++;
  131. splx(x);
  132. while(l->key)
  133. ;
  134. x = splhi();
  135. if(tas(&l->key) == 0)
  136. goto acquire;
  137. }
  138. }
  139. acquire:
  140. m->ilockdepth++;
  141. if(up)
  142. up->lastilock = l;
  143. l->sr = x;
  144. l->pc = pc;
  145. l->p = up;
  146. l->isilock = 1;
  147. l->m = MACHP(m->machno);
  148. #ifdef LOCKCYCLES
  149. l->lockcycles = -lcycles();
  150. #endif
  151. }
  152. int
  153. canlock(Lock *l)
  154. {
  155. if(up)
  156. inccnt(&up->nlocks);
  157. if(tas(&l->key)){
  158. if(up)
  159. deccnt(&up->nlocks);
  160. return 0;
  161. }
  162. if(up)
  163. up->lastlock = l;
  164. l->pc = getcallerpc(&l);
  165. l->p = up;
  166. l->m = MACHP(m->machno);
  167. l->isilock = 0;
  168. #ifdef LOCKCYCLES
  169. l->lockcycles = -lcycles();
  170. #endif
  171. return 1;
  172. }
  173. void
  174. unlock(Lock *l)
  175. {
  176. #ifdef LOCKCYCLES
  177. l->lockcycles += lcycles();
  178. cumlockcycles += l->lockcycles;
  179. if(l->lockcycles > maxlockcycles){
  180. maxlockcycles = l->lockcycles;
  181. maxlockpc = l->pc;
  182. }
  183. #endif
  184. if(l->key == 0)
  185. print("unlock: not locked: pc %#p\n", getcallerpc(&l));
  186. if(l->isilock)
  187. print("unlock of ilock: pc %lux, held by %lux\n", getcallerpc(&l), l->pc);
  188. if(l->p != up)
  189. print("unlock: up changed: pc %#p, acquired at pc %lux, lock p %#p, unlock up %#p\n", getcallerpc(&l), l->pc, l->p, up);
  190. l->m = nil;
  191. l->key = 0;
  192. coherence();
  193. if(up && deccnt(&up->nlocks) == 0 && up->delaysched && islo()){
  194. /*
  195. * Call sched if the need arose while locks were held
  196. * But, don't do it from interrupt routines, hence the islo() test
  197. */
  198. sched();
  199. }
  200. }
  201. ulong ilockpcs[0x100] = { [0xff] = 1 };
  202. static int n;
  203. void
  204. iunlock(Lock *l)
  205. {
  206. ulong sr;
  207. #ifdef LOCKCYCLES
  208. l->lockcycles += lcycles();
  209. cumilockcycles += l->lockcycles;
  210. if(l->lockcycles > maxilockcycles){
  211. maxilockcycles = l->lockcycles;
  212. maxilockpc = l->pc;
  213. }
  214. if(l->lockcycles > 2400)
  215. ilockpcs[n++ & 0xff] = l->pc;
  216. #endif
  217. if(l->key == 0)
  218. print("iunlock: not locked: pc %#p\n", getcallerpc(&l));
  219. if(!l->isilock)
  220. print("iunlock of lock: pc %#p, held by %#lux\n", getcallerpc(&l), l->pc);
  221. if(islo())
  222. print("iunlock while lo: pc %#p, held by %#lux\n", getcallerpc(&l), l->pc);
  223. sr = l->sr;
  224. l->m = nil;
  225. l->key = 0;
  226. coherence();
  227. m->ilockdepth--;
  228. if(up)
  229. up->lastilock = nil;
  230. splx(sr);
  231. }