qlock.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. struct {
  7. ulong rlock;
  8. ulong rlockq;
  9. ulong wlock;
  10. ulong wlockq;
  11. ulong qlock;
  12. ulong qlockq;
  13. } rwstats;
  14. void
  15. qlock(QLock *q)
  16. {
  17. Proc *p;
  18. if(m->ilockdepth != 0)
  19. print("qlock: %lux: ilockdepth %d", getcallerpc(&q), m->ilockdepth);
  20. if(up != nil && up->nlocks)
  21. print("qlock: %lux: nlocks %lud", getcallerpc(&q), up->nlocks);
  22. lock(&q->use);
  23. rwstats.qlock++;
  24. if(!q->locked) {
  25. q->locked = 1;
  26. unlock(&q->use);
  27. return;
  28. }
  29. if(up == 0)
  30. panic("qlock");
  31. rwstats.qlockq++;
  32. p = q->tail;
  33. if(p == 0)
  34. q->head = up;
  35. else
  36. p->qnext = up;
  37. q->tail = up;
  38. up->qnext = 0;
  39. up->state = Queueing;
  40. up->qpc = getcallerpc(&q);
  41. unlock(&q->use);
  42. if(edf->isedf(up))
  43. edf->edfblock(up);
  44. sched();
  45. }
  46. int
  47. canqlock(QLock *q)
  48. {
  49. if(!canlock(&q->use))
  50. return 0;
  51. if(q->locked){
  52. unlock(&q->use);
  53. return 0;
  54. }
  55. q->locked = 1;
  56. unlock(&q->use);
  57. return 1;
  58. }
  59. void
  60. qunlock(QLock *q)
  61. {
  62. Proc *p;
  63. lock(&q->use);
  64. p = q->head;
  65. if(p){
  66. q->head = p->qnext;
  67. if(q->head == 0)
  68. q->tail = 0;
  69. unlock(&q->use);
  70. ready(p);
  71. return;
  72. }
  73. q->locked = 0;
  74. unlock(&q->use);
  75. }
  76. void
  77. rlock(RWlock *q)
  78. {
  79. Proc *p;
  80. lock(&q->use);
  81. rwstats.rlock++;
  82. if(q->writer == 0 && q->head == nil){
  83. /* no writer, go for it */
  84. q->readers++;
  85. unlock(&q->use);
  86. return;
  87. }
  88. rwstats.rlockq++;
  89. p = q->tail;
  90. if(up == nil)
  91. panic("rlock");
  92. if(p == 0)
  93. q->head = up;
  94. else
  95. p->qnext = up;
  96. q->tail = up;
  97. up->qnext = 0;
  98. up->state = QueueingR;
  99. unlock(&q->use);
  100. if (edf->isedf(up))
  101. edf->edfblock(up);
  102. sched();
  103. }
  104. void
  105. runlock(RWlock *q)
  106. {
  107. Proc *p;
  108. lock(&q->use);
  109. p = q->head;
  110. if(--(q->readers) > 0 || p == nil){
  111. unlock(&q->use);
  112. return;
  113. }
  114. /* start waiting writer */
  115. if(p->state != QueueingW)
  116. panic("runlock");
  117. q->head = p->qnext;
  118. if(q->head == 0)
  119. q->tail = 0;
  120. q->writer = 1;
  121. unlock(&q->use);
  122. ready(p);
  123. }
  124. void
  125. wlock(RWlock *q)
  126. {
  127. Proc *p;
  128. lock(&q->use);
  129. rwstats.wlock++;
  130. if(q->readers == 0 && q->writer == 0){
  131. /* noone waiting, go for it */
  132. q->wpc = getcallerpc(&q);
  133. q->wproc = up;
  134. q->writer = 1;
  135. unlock(&q->use);
  136. return;
  137. }
  138. /* wait */
  139. rwstats.wlockq++;
  140. p = q->tail;
  141. if(up == nil)
  142. panic("wlock");
  143. if(p == nil)
  144. q->head = up;
  145. else
  146. p->qnext = up;
  147. q->tail = up;
  148. up->qnext = 0;
  149. up->state = QueueingW;
  150. unlock(&q->use);
  151. if (edf->isedf(up))
  152. edf->edfblock(up);
  153. sched();
  154. }
  155. void
  156. wunlock(RWlock *q)
  157. {
  158. Proc *p;
  159. lock(&q->use);
  160. p = q->head;
  161. if(p == nil){
  162. q->writer = 0;
  163. unlock(&q->use);
  164. return;
  165. }
  166. if(p->state == QueueingW){
  167. /* start waiting writer */
  168. q->head = p->qnext;
  169. if(q->head == nil)
  170. q->tail = nil;
  171. unlock(&q->use);
  172. ready(p);
  173. return;
  174. }
  175. if(p->state != QueueingR)
  176. panic("wunlock");
  177. /* waken waiting readers */
  178. while(q->head != nil && q->head->state == QueueingR){
  179. p = q->head;
  180. q->head = p->qnext;
  181. q->readers++;
  182. ready(p);
  183. }
  184. if(q->head == nil)
  185. q->tail = nil;
  186. q->writer = 0;
  187. unlock(&q->use);
  188. }
  189. /* same as rlock but punts if there are any writers waiting */
  190. int
  191. canrlock(RWlock *q)
  192. {
  193. lock(&q->use);
  194. rwstats.rlock++;
  195. if(q->writer == 0 && q->head == nil){
  196. /* no writer, go for it */
  197. q->readers++;
  198. unlock(&q->use);
  199. return 1;
  200. }
  201. unlock(&q->use);
  202. return 0;
  203. }