lock.c 3.5 KB

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