qlock.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. #define _LOCK_EXTENSION
  2. #define _QLOCK_EXTENSION
  3. #define _RESEARCH_SOURCE
  4. #include <u.h>
  5. #include <lock.h>
  6. #include <qlock.h>
  7. #include <stdlib.h>
  8. #include "sys9.h"
  9. #define rendezvous _RENDEZVOUS
  10. #define _rendezvousp rendezvous
  11. #define _tas tas
  12. #define nelem(x) (sizeof(x)/sizeof((x)[0]))
  13. static struct {
  14. QLp *p;
  15. QLp x[1024];
  16. } ql = {
  17. ql.x
  18. };
  19. enum
  20. {
  21. Queuing,
  22. QueuingR,
  23. QueuingW,
  24. Sleeping,
  25. };
  26. /* find a free shared memory location to queue ourselves in */
  27. static QLp*
  28. getqlp(void)
  29. {
  30. QLp *p, *op;
  31. op = ql.p;
  32. for(p = op+1; ; p++){
  33. if(p == &ql.x[nelem(ql.x)])
  34. p = ql.x;
  35. if(p == op)
  36. abort();
  37. if(_tas(&(p->inuse)) == 0){
  38. ql.p = p;
  39. p->next = nil;
  40. break;
  41. }
  42. }
  43. return p;
  44. }
  45. void
  46. qlock(QLock *q)
  47. {
  48. QLp *p, *mp;
  49. lock(&q->lock);
  50. if(!q->locked){
  51. q->locked = 1;
  52. unlock(&q->lock);
  53. return;
  54. }
  55. /* chain into waiting list */
  56. mp = getqlp();
  57. p = q->tail;
  58. if(p == nil)
  59. q->head = mp;
  60. else
  61. p->next = mp;
  62. q->tail = mp;
  63. mp->state = Queuing;
  64. unlock(&q->lock);
  65. /* wait */
  66. while((*_rendezvousp)((ulong)mp, 1) == ~0)
  67. ;
  68. mp->inuse = 0;
  69. }
  70. void
  71. qunlock(QLock *q)
  72. {
  73. QLp *p;
  74. lock(&q->lock);
  75. p = q->head;
  76. if(p != nil){
  77. /* wakeup head waiting process */
  78. q->head = p->next;
  79. if(q->head == nil)
  80. q->tail = nil;
  81. unlock(&q->lock);
  82. while((*_rendezvousp)((ulong)p, 0x12345) == ~0)
  83. ;
  84. return;
  85. }
  86. q->locked = 0;
  87. unlock(&q->lock);
  88. }
  89. int
  90. canqlock(QLock *q)
  91. {
  92. if(!canlock(&q->lock))
  93. return 0;
  94. if(!q->locked){
  95. q->locked = 1;
  96. unlock(&q->lock);
  97. return 1;
  98. }
  99. unlock(&q->lock);
  100. return 0;
  101. }
  102. #if 0
  103. void
  104. rlock(RWLock *q)
  105. {
  106. QLp *p, *mp;
  107. lock(&q->lock);
  108. if(q->writer == 0 && q->head == nil){
  109. /* no writer, go for it */
  110. q->readers++;
  111. unlock(&q->lock);
  112. return;
  113. }
  114. mp = getqlp();
  115. p = q->tail;
  116. if(p == 0)
  117. q->head = mp;
  118. else
  119. p->next = mp;
  120. q->tail = mp;
  121. mp->next = nil;
  122. mp->state = QueuingR;
  123. unlock(&q->lock);
  124. /* wait in kernel */
  125. while((*_rendezvousp)((ulong)mp, 1) == ~0)
  126. ;
  127. mp->inuse = 0;
  128. }
  129. int
  130. canrlock(RWLock *q)
  131. {
  132. lock(&q->lock);
  133. if (q->writer == 0 && q->head == nil) {
  134. /* no writer; go for it */
  135. q->readers++;
  136. unlock(&q->lock);
  137. return 1;
  138. }
  139. unlock(&q->lock);
  140. return 0;
  141. }
  142. void
  143. runlock(RWLock *q)
  144. {
  145. QLp *p;
  146. lock(&q->lock);
  147. if(q->readers <= 0)
  148. abort();
  149. p = q->head;
  150. if(--(q->readers) > 0 || p == nil){
  151. unlock(&q->lock);
  152. return;
  153. }
  154. /* start waiting writer */
  155. if(p->state != QueuingW)
  156. abort();
  157. q->head = p->next;
  158. if(q->head == 0)
  159. q->tail = 0;
  160. q->writer = 1;
  161. unlock(&q->lock);
  162. /* wakeup waiter */
  163. while((*_rendezvousp)((ulong)p, 0) == ~0)
  164. ;
  165. }
  166. void
  167. wlock(RWLock *q)
  168. {
  169. QLp *p, *mp;
  170. lock(&q->lock);
  171. if(q->readers == 0 && q->writer == 0){
  172. /* noone waiting, go for it */
  173. q->writer = 1;
  174. unlock(&q->lock);
  175. return;
  176. }
  177. /* wait */
  178. p = q->tail;
  179. mp = getqlp();
  180. if(p == nil)
  181. q->head = mp;
  182. else
  183. p->next = mp;
  184. q->tail = mp;
  185. mp->next = nil;
  186. mp->state = QueuingW;
  187. unlock(&q->lock);
  188. /* wait in kernel */
  189. while((*_rendezvousp)((ulong)mp, 1) == ~0)
  190. ;
  191. mp->inuse = 0;
  192. }
  193. int
  194. canwlock(RWLock *q)
  195. {
  196. lock(&q->lock);
  197. if (q->readers == 0 && q->writer == 0) {
  198. /* no one waiting; go for it */
  199. q->writer = 1;
  200. unlock(&q->lock);
  201. return 1;
  202. }
  203. unlock(&q->lock);
  204. return 0;
  205. }
  206. void
  207. wunlock(RWLock *q)
  208. {
  209. QLp *p;
  210. lock(&q->lock);
  211. if(q->writer == 0)
  212. abort();
  213. p = q->head;
  214. if(p == nil){
  215. q->writer = 0;
  216. unlock(&q->lock);
  217. return;
  218. }
  219. if(p->state == QueuingW){
  220. /* start waiting writer */
  221. q->head = p->next;
  222. if(q->head == nil)
  223. q->tail = nil;
  224. unlock(&q->lock);
  225. while((*_rendezvousp)((ulong)p, 0) == ~0)
  226. ;
  227. return;
  228. }
  229. if(p->state != QueuingR)
  230. abort();
  231. /* wake waiting readers */
  232. while(q->head != nil && q->head->state == QueuingR){
  233. p = q->head;
  234. q->head = p->next;
  235. q->readers++;
  236. while((*_rendezvousp)((ulong)p, 0) == ~0)
  237. ;
  238. }
  239. if(q->head == nil)
  240. q->tail = nil;
  241. q->writer = 0;
  242. unlock(&q->lock);
  243. }
  244. void
  245. rsleep(Rendez *r)
  246. {
  247. QLp *t, *me;
  248. if(!r->l)
  249. abort();
  250. lock(&r->l->lock);
  251. /* we should hold the qlock */
  252. if(!r->l->locked)
  253. abort();
  254. /* add ourselves to the wait list */
  255. me = getqlp();
  256. me->state = Sleeping;
  257. if(r->head == nil)
  258. r->head = me;
  259. else
  260. r->tail->next = me;
  261. me->next = nil;
  262. r->tail = me;
  263. /* pass the qlock to the next guy */
  264. t = r->l->head;
  265. if(t){
  266. r->l->head = t->next;
  267. if(r->l->head == nil)
  268. r->l->tail = nil;
  269. unlock(&r->l->lock);
  270. while((*_rendezvousp)((ulong)t, 0x12345) == ~0)
  271. ;
  272. }else{
  273. r->l->locked = 0;
  274. unlock(&r->l->lock);
  275. }
  276. /* wait for a wakeup */
  277. while((*_rendezvousp)((ulong)me, 1) == ~0)
  278. ;
  279. me->inuse = 0;
  280. }
  281. int
  282. rwakeup(Rendez *r)
  283. {
  284. QLp *t;
  285. /*
  286. * take off wait and put on front of queue
  287. * put on front so guys that have been waiting will not get starved
  288. */
  289. if(!r->l)
  290. abort();
  291. lock(&r->l->lock);
  292. if(!r->l->locked)
  293. abort();
  294. t = r->head;
  295. if(t == nil){
  296. unlock(&r->l->lock);
  297. return 0;
  298. }
  299. r->head = t->next;
  300. if(r->head == nil)
  301. r->tail = nil;
  302. t->next = r->l->head;
  303. r->l->head = t;
  304. if(r->l->tail == nil)
  305. r->l->tail = t;
  306. t->state = Queuing;
  307. unlock(&r->l->lock);
  308. return 1;
  309. }
  310. int
  311. rwakeupall(Rendez *r)
  312. {
  313. int i;
  314. for(i=0; rwakeup(r); i++)
  315. ;
  316. return i;
  317. }
  318. #endif