123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- /*
- * Queue of void pointers. See queue.h for details.
- */
- #include <types.h>
- #include <kern/errno.h>
- #include <lib.h>
- #include <queue.h>
- struct queue {
- int size;
- int nextwrite; // next element to write to (was head)
- int nextread; // next element to read from (was tail)
- void **data;
- };
- static
- int
- q_grow(struct queue *q, int targetsize)
- {
- void **olddata = q->data;
- int onr = q->nextread;
- int onw = q->nextwrite;
- int osize = q->size;
- int nsize;
- void **ndata;
- int i, result;
- nsize = q->size;
- while (nsize < targetsize) {
- nsize *= 2;
- /* prevent infinite loop */
- KASSERT(nsize > 0);
- }
- ndata = kmalloc(nsize * sizeof(void *));
- if (ndata == NULL) {
- return ENOMEM;
- }
- q->size = nsize;
- q->data = ndata;
- q->nextread = q->nextwrite = 0;
-
- for (i=onr; i!=onw; i = (i+1)%osize) {
- result = q_addtail(q, olddata[i]);
- KASSERT(result==0);
- }
- kfree(olddata);
- return 0;
- }
- struct queue *
- q_create(int size)
- {
- struct queue *q = kmalloc(sizeof(struct queue));
- if (q==NULL) {
- return NULL;
- }
- q->size = size;
- q->data = kmalloc(size * sizeof(void *));
- if (q->data==NULL) {
- kfree(q);
- return NULL;
- }
- q->nextread = q->nextwrite = 0;
- return q;
- }
- int
- q_preallocate(struct queue *q, int size)
- {
- int result = 0;
- KASSERT(q->size > 0);
- if (size > q->size) {
- result = q_grow(q, size);
- }
- return result;
- }
- inline
- int
- q_empty(struct queue *q)
- {
- return q->nextwrite == q->nextread;
- }
- int
- q_addtail(struct queue *q, void *ptr)
- {
- int nextnext, result;
- KASSERT(q->size > 0);
-
- nextnext = (q->nextwrite+1) % q->size;
- if (nextnext==q->nextread) {
- result = q_grow(q, q->size+1);
- if (result) {
- return result;
- }
- nextnext = (q->nextwrite+1) % q->size;
- }
- q->data[q->nextwrite] = ptr;
- q->nextwrite = nextnext;
- return 0;
- }
- void *
- q_remhead(struct queue *q)
- {
- void *ret;
- KASSERT(q->size > 0);
- KASSERT(!q_empty(q));
- ret = q->data[q->nextread];
- q->nextread = (q->nextread+1)%q->size;
- return ret;
- }
- void
- q_destroy(struct queue *q)
- {
- KASSERT(q_empty(q));
- kfree(q->data);
- kfree(q);
- }
- /* These are really intended only for debugging. */
- int
- q_getstart(struct queue *q)
- {
- return q->nextread;
- }
- int
- q_getend(struct queue *q)
- {
- return q->nextwrite;
- }
- int
- q_getsize(struct queue *q)
- {
- return q->size;
- }
- void *
- q_getguy(struct queue *q, int index)
- {
- // note that we don't check to make sure the access isn't in the
- // unused part of the queue space. we probably should.
- KASSERT(index>=0 && index<q->size);
- return q->data[index];
- }
- void *
- q_peek(struct queue *q)
- {
- void *ret;
- KASSERT(q);
- KASSERT(q->size > 0);
- if (q_empty(q)) {
- ret = 0;
- } else {
- ret = q->data[q->nextread];
- }
- return ret;
- }
- int
- q_len(struct queue *theq)
- {
- int count = 0;
- int tmp = theq->nextread;
- while (tmp != theq->nextwrite) {
- tmp = (tmp+1) % theq->size;
- count++;
- }
- return count;
- }
|