queue.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. * Queue of void pointers. See queue.h for details.
  3. */
  4. #include <types.h>
  5. #include <kern/errno.h>
  6. #include <lib.h>
  7. #include <queue.h>
  8. struct queue {
  9. int size;
  10. int nextwrite; // next element to write to (was head)
  11. int nextread; // next element to read from (was tail)
  12. void **data;
  13. };
  14. static
  15. int
  16. q_grow(struct queue *q, int targetsize)
  17. {
  18. void **olddata = q->data;
  19. int onr = q->nextread;
  20. int onw = q->nextwrite;
  21. int osize = q->size;
  22. int nsize;
  23. void **ndata;
  24. int i, result;
  25. nsize = q->size;
  26. while (nsize < targetsize) {
  27. nsize *= 2;
  28. /* prevent infinite loop */
  29. KASSERT(nsize > 0);
  30. }
  31. ndata = kmalloc(nsize * sizeof(void *));
  32. if (ndata == NULL) {
  33. return ENOMEM;
  34. }
  35. q->size = nsize;
  36. q->data = ndata;
  37. q->nextread = q->nextwrite = 0;
  38. for (i=onr; i!=onw; i = (i+1)%osize) {
  39. result = q_addtail(q, olddata[i]);
  40. KASSERT(result==0);
  41. }
  42. kfree(olddata);
  43. return 0;
  44. }
  45. struct queue *
  46. q_create(int size)
  47. {
  48. struct queue *q = kmalloc(sizeof(struct queue));
  49. if (q==NULL) {
  50. return NULL;
  51. }
  52. q->size = size;
  53. q->data = kmalloc(size * sizeof(void *));
  54. if (q->data==NULL) {
  55. kfree(q);
  56. return NULL;
  57. }
  58. q->nextread = q->nextwrite = 0;
  59. return q;
  60. }
  61. int
  62. q_preallocate(struct queue *q, int size)
  63. {
  64. int result = 0;
  65. KASSERT(q->size > 0);
  66. if (size > q->size) {
  67. result = q_grow(q, size);
  68. }
  69. return result;
  70. }
  71. inline
  72. int
  73. q_empty(struct queue *q)
  74. {
  75. return q->nextwrite == q->nextread;
  76. }
  77. int
  78. q_addtail(struct queue *q, void *ptr)
  79. {
  80. int nextnext, result;
  81. KASSERT(q->size > 0);
  82. nextnext = (q->nextwrite+1) % q->size;
  83. if (nextnext==q->nextread) {
  84. result = q_grow(q, q->size+1);
  85. if (result) {
  86. return result;
  87. }
  88. nextnext = (q->nextwrite+1) % q->size;
  89. }
  90. q->data[q->nextwrite] = ptr;
  91. q->nextwrite = nextnext;
  92. return 0;
  93. }
  94. void *
  95. q_remhead(struct queue *q)
  96. {
  97. void *ret;
  98. KASSERT(q->size > 0);
  99. KASSERT(!q_empty(q));
  100. ret = q->data[q->nextread];
  101. q->nextread = (q->nextread+1)%q->size;
  102. return ret;
  103. }
  104. void
  105. q_destroy(struct queue *q)
  106. {
  107. KASSERT(q_empty(q));
  108. kfree(q->data);
  109. kfree(q);
  110. }
  111. /* These are really intended only for debugging. */
  112. int
  113. q_getstart(struct queue *q)
  114. {
  115. return q->nextread;
  116. }
  117. int
  118. q_getend(struct queue *q)
  119. {
  120. return q->nextwrite;
  121. }
  122. int
  123. q_getsize(struct queue *q)
  124. {
  125. return q->size;
  126. }
  127. void *
  128. q_getguy(struct queue *q, int index)
  129. {
  130. // note that we don't check to make sure the access isn't in the
  131. // unused part of the queue space. we probably should.
  132. KASSERT(index>=0 && index<q->size);
  133. return q->data[index];
  134. }
  135. void *
  136. q_peek(struct queue *q)
  137. {
  138. void *ret;
  139. KASSERT(q);
  140. KASSERT(q->size > 0);
  141. if (q_empty(q)) {
  142. ret = 0;
  143. } else {
  144. ret = q->data[q->nextread];
  145. }
  146. return ret;
  147. }
  148. int
  149. q_len(struct queue *theq)
  150. {
  151. int count = 0;
  152. int tmp = theq->nextread;
  153. while (tmp != theq->nextwrite) {
  154. tmp = (tmp+1) % theq->size;
  155. count++;
  156. }
  157. return count;
  158. }