lock.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. #include "u.h"
  2. #include "lib.h"
  3. #include "dat.h"
  4. #include "fns.h"
  5. #include "io.h"
  6. #include "mem.h"
  7. void
  8. lock(Lock *l)
  9. {
  10. int i;
  11. ulong caller;
  12. caller = getcallerpc(&l);
  13. /*
  14. * Try the fast grab first
  15. */
  16. loop:
  17. if(tas(l) == 0) {
  18. l->pc = caller;
  19. return;
  20. }
  21. for(i = 0; i < 1000000; i++) {
  22. if(tas(l) == 0) {
  23. l->pc = caller;
  24. return;
  25. }
  26. /* If we are spl low resched */
  27. if(getstatus() & IFLAG)
  28. sched();
  29. }
  30. l->sbsem = 0;
  31. print("lock loop 0x%lux called by 0x%lux held by pc 0x%lux\n", (ulong)l,
  32. caller, l->pc);
  33. goto loop;
  34. }
  35. void
  36. ilock(Lock *l)
  37. {
  38. l->sr = splhi();
  39. lock(l);
  40. }
  41. void
  42. iunlock(Lock *l)
  43. {
  44. ulong sr;
  45. sr = l->sr;
  46. l->sbsem = 0;
  47. l->pc = 0;
  48. splx(sr);
  49. }
  50. int
  51. canlock(Lock *l)
  52. {
  53. if (tas(l) == 0)
  54. return 1;
  55. return 0;
  56. }
  57. void
  58. unlock(Lock *l)
  59. {
  60. l->pc = 0;
  61. l->sbsem = 0;
  62. }
  63. void
  64. qlock(QLock *q)
  65. {
  66. User *p;
  67. int i;
  68. lock(q);
  69. if(!q->locked){
  70. q->locked = 1;
  71. unlock(q);
  72. goto out;
  73. }
  74. if(1 && u) {
  75. for(i=0; i<NHAS; i++)
  76. if(u->has.q[i] == q) {
  77. print("circular qlock by %d at 0x%lux (other 0x%lux, 0x%lux)\n",
  78. u->pid, getcallerpc(&q), u->has.pc[i], q->pc);
  79. dumpstack(u);
  80. break;
  81. }
  82. }
  83. p = q->tail;
  84. if(p == 0)
  85. q->head = u;
  86. else
  87. p->qnext = u;
  88. q->tail = u;
  89. u->qnext = 0;
  90. u->state = Queueing;
  91. u->has.want = q;
  92. unlock(q);
  93. sched();
  94. u->has.want = 0;
  95. out:
  96. if(1 && u) {
  97. for(i=0; i<NHAS; i++)
  98. if(u->has.q[i] == 0) {
  99. u->has.q[i] = q;
  100. u->has.pc[i] = getcallerpc(&q);
  101. return;
  102. }
  103. print("NHAS(%d) too small\n", NHAS);
  104. }
  105. }
  106. int
  107. canqlock(QLock *q)
  108. {
  109. int i;
  110. lock(q);
  111. if(q->locked){
  112. unlock(q);
  113. return 0;
  114. }
  115. q->locked = 1;
  116. unlock(q);
  117. if(1 && u) {
  118. for(i=0; i<NHAS; i++)
  119. if(u->has.q[i] == 0) {
  120. u->has.q[i] = q;
  121. u->has.pc[i] = getcallerpc(&q);
  122. return 1;
  123. }
  124. print("NHAS(%d) too small\n", NHAS);
  125. }
  126. return 1;
  127. }
  128. void
  129. qunlock(QLock *q)
  130. {
  131. User *p;
  132. int i;
  133. lock(q);
  134. p = q->head;
  135. if(p) {
  136. q->head = p->qnext;
  137. if(q->head == 0)
  138. q->tail = 0;
  139. unlock(q);
  140. ready(p);
  141. } else {
  142. q->locked = 0;
  143. unlock(q);
  144. }
  145. if(1 && u) {
  146. for(i=0; i<NHAS; i++)
  147. if(u->has.q[i] == q) {
  148. u->has.q[i] = 0;
  149. return;
  150. }
  151. panic("qunlock: not there %lux, called from %lux\n",
  152. (ulong)q, getcallerpc(&q));
  153. }
  154. }
  155. /*
  156. * readers/writers lock
  157. * allows 1 writer or many readers
  158. */
  159. void
  160. rlock(RWlock *l)
  161. {
  162. QLock *q;
  163. qlock(&l->wr); /* wait here for writers and exclusion */
  164. q = &l->rd; /* first reader in, qlock(&l->rd) */
  165. lock(q);
  166. q->locked = 1;
  167. l->nread++;
  168. unlock(q);
  169. qunlock(&l->wr);
  170. if(1 && u) {
  171. int i;
  172. int found;
  173. found = 0;
  174. for(i=0; i<NHAS; i++){
  175. if(u->has.q[i] == q){
  176. print("circular rlock by %d at 0x%lux (other 0x%lux)\n",
  177. u->pid, getcallerpc(&l), u->has.pc[i]);
  178. dumpstack(u);
  179. }
  180. if(!found && u->has.q[i] == 0) {
  181. u->has.q[i] = q;
  182. u->has.pc[i] = getcallerpc(&l);
  183. found = 1;
  184. }
  185. }
  186. if(!found)
  187. print("NHAS(%d) too small\n", NHAS);
  188. }
  189. }
  190. void
  191. runlock(RWlock *l)
  192. {
  193. QLock *q;
  194. User *p;
  195. int n;
  196. q = &l->rd;
  197. lock(q);
  198. n = l->nread - 1;
  199. l->nread = n;
  200. if(n == 0) { /* last reader out, qunlock(&l->rd) */
  201. p = q->head;
  202. if(p) {
  203. q->head = p->qnext;
  204. if(q->head == 0)
  205. q->tail = 0;
  206. unlock(q);
  207. ready(p);
  208. goto accounting;
  209. }
  210. q->locked = 0;
  211. }
  212. unlock(q);
  213. accounting:
  214. if(1 && u) {
  215. int i;
  216. for(i=0; i<NHAS; i++)
  217. if(u->has.q[i] == q) {
  218. u->has.q[i] = 0;
  219. return;
  220. }
  221. panic("runlock: not there %lux, called from %lux\n",
  222. (ulong)q, getcallerpc(&l));
  223. }
  224. }
  225. void
  226. wlock(RWlock *l)
  227. {
  228. qlock(&l->wr); /* wait here for writers and exclusion */
  229. qlock(&l->rd); /* wait here for last reader */
  230. }
  231. void
  232. wunlock(RWlock *l)
  233. {
  234. qunlock(&l->rd);
  235. qunlock(&l->wr);
  236. }