queue.c 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <venti.h>
  4. #include "queue.h"
  5. typedef struct Qel Qel;
  6. struct Qel
  7. {
  8. Qel *next;
  9. void *p;
  10. };
  11. struct Queue
  12. {
  13. int ref;
  14. int hungup;
  15. QLock lk;
  16. Rendez r;
  17. Qel *head;
  18. Qel *tail;
  19. };
  20. Queue*
  21. _vtqalloc(void)
  22. {
  23. Queue *q;
  24. q = vtmallocz(sizeof(Queue));
  25. q->r.l = &q->lk;
  26. q->ref = 1;
  27. return q;
  28. }
  29. Queue*
  30. _vtqincref(Queue *q)
  31. {
  32. qlock(&q->lk);
  33. q->ref++;
  34. qunlock(&q->lk);
  35. return q;
  36. }
  37. void
  38. _vtqdecref(Queue *q)
  39. {
  40. Qel *e;
  41. qlock(&q->lk);
  42. if(--q->ref > 0){
  43. qunlock(&q->lk);
  44. return;
  45. }
  46. assert(q->ref == 0);
  47. qunlock(&q->lk);
  48. /* Leaks the pointers e->p! */
  49. while(q->head){
  50. e = q->head;
  51. q->head = e->next;
  52. free(e);
  53. }
  54. free(q);
  55. }
  56. int
  57. _vtqsend(Queue *q, void *p)
  58. {
  59. Qel *e;
  60. e = vtmalloc(sizeof(Qel));
  61. qlock(&q->lk);
  62. if(q->hungup){
  63. werrstr("hungup queue");
  64. qunlock(&q->lk);
  65. return -1;
  66. }
  67. e->p = p;
  68. e->next = nil;
  69. if(q->head == nil)
  70. q->head = e;
  71. else
  72. q->tail->next = e;
  73. q->tail = e;
  74. rwakeup(&q->r);
  75. qunlock(&q->lk);
  76. return 0;
  77. }
  78. void*
  79. _vtqrecv(Queue *q)
  80. {
  81. void *p;
  82. Qel *e;
  83. qlock(&q->lk);
  84. while(q->head == nil && !q->hungup)
  85. rsleep(&q->r);
  86. if(q->hungup){
  87. qunlock(&q->lk);
  88. return nil;
  89. }
  90. e = q->head;
  91. q->head = e->next;
  92. qunlock(&q->lk);
  93. p = e->p;
  94. vtfree(e);
  95. return p;
  96. }
  97. void*
  98. _vtnbqrecv(Queue *q)
  99. {
  100. void *p;
  101. Qel *e;
  102. qlock(&q->lk);
  103. if(q->head == nil){
  104. qunlock(&q->lk);
  105. return nil;
  106. }
  107. e = q->head;
  108. q->head = e->next;
  109. qunlock(&q->lk);
  110. p = e->p;
  111. vtfree(e);
  112. return p;
  113. }
  114. void
  115. _vtqhangup(Queue *q)
  116. {
  117. qlock(&q->lk);
  118. q->hungup = 1;
  119. rwakeupall(&q->r);
  120. qunlock(&q->lk);
  121. }