queue.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <venti.h>
  12. #include "queue.h"
  13. typedef struct Qel Qel;
  14. struct Qel
  15. {
  16. Qel *next;
  17. void *p;
  18. };
  19. struct Queue
  20. {
  21. int ref;
  22. int hungup;
  23. QLock lk;
  24. Rendez r;
  25. Qel *head;
  26. Qel *tail;
  27. };
  28. Queue*
  29. _vtqalloc(void)
  30. {
  31. Queue *q;
  32. q = vtmallocz(sizeof(Queue));
  33. q->r.l = &q->lk;
  34. q->ref = 1;
  35. return q;
  36. }
  37. Queue*
  38. _vtqincref(Queue *q)
  39. {
  40. qlock(&q->lk);
  41. q->ref++;
  42. qunlock(&q->lk);
  43. return q;
  44. }
  45. void
  46. _vtqdecref(Queue *q)
  47. {
  48. Qel *e;
  49. qlock(&q->lk);
  50. if(--q->ref > 0){
  51. qunlock(&q->lk);
  52. return;
  53. }
  54. assert(q->ref == 0);
  55. qunlock(&q->lk);
  56. /* Leaks the pointers e->p! */
  57. while(q->head){
  58. e = q->head;
  59. q->head = e->next;
  60. free(e);
  61. }
  62. free(q);
  63. }
  64. int
  65. _vtqsend(Queue *q, void *p)
  66. {
  67. Qel *e;
  68. e = vtmalloc(sizeof(Qel));
  69. qlock(&q->lk);
  70. if(q->hungup){
  71. werrstr("hungup queue");
  72. qunlock(&q->lk);
  73. return -1;
  74. }
  75. e->p = p;
  76. e->next = nil;
  77. if(q->head == nil)
  78. q->head = e;
  79. else
  80. q->tail->next = e;
  81. q->tail = e;
  82. rwakeup(&q->r);
  83. qunlock(&q->lk);
  84. return 0;
  85. }
  86. void*
  87. _vtqrecv(Queue *q)
  88. {
  89. void *p;
  90. Qel *e;
  91. qlock(&q->lk);
  92. while(q->head == nil && !q->hungup)
  93. rsleep(&q->r);
  94. if(q->hungup){
  95. qunlock(&q->lk);
  96. return nil;
  97. }
  98. e = q->head;
  99. q->head = e->next;
  100. qunlock(&q->lk);
  101. p = e->p;
  102. vtfree(e);
  103. return p;
  104. }
  105. void*
  106. _vtnbqrecv(Queue *q)
  107. {
  108. void *p;
  109. Qel *e;
  110. qlock(&q->lk);
  111. if(q->head == nil){
  112. qunlock(&q->lk);
  113. return nil;
  114. }
  115. e = q->head;
  116. q->head = e->next;
  117. qunlock(&q->lk);
  118. p = e->p;
  119. vtfree(e);
  120. return p;
  121. }
  122. void
  123. _vtqhangup(Queue *q)
  124. {
  125. qlock(&q->lk);
  126. q->hungup = 1;
  127. rwakeupall(&q->r);
  128. qunlock(&q->lk);
  129. }