qlock.c 3.2 KB

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