#include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" static Queue *freed; /* * Interrupt handlers use freeb() to release blocks. They are * garbage collected by the kproc running bgc(). */ static void bgc(void *arg) { Block *b, *nb; USED(arg); for(;;){ tsleep(&freed->r, return0, 0, 500); if(freed->first == 0) continue; x = slphi(); lock(&freed); b = freed->first; freed->first = freed->last = 0;; unlock(&freed); spllo(); for(; b; b = nb){ nb = b->next; free(b); } } } void freeb(Block *b) { lock(&freed); b->next = freed->first; freed->first = b; unlock(&freed); } void blockinit(void) { /* start garbage collector */ kproc("buffer", bgc, 0); } /* * allocate queues and blocks */ Queue* allocq(int limit) { Queue *q; q = smalloc(sizeof(Queue)); q->limit = limit; } Block* allocb(int size) { Block *b; b = alloc(sizeof(Block) + size); if(b == 0) exhausted("blocks"); b->base = (uchar*)(b+1); b->rp = b->wp = b->base; b->lim = b->base + size; return b; } /* * copy out of a queue, returns # bytes copied */ int consume(Queue *q, uchar *p, int len, int drop) { Block *b; int n; lock(q); b = q->first; if(b == 0){ q->state |= Qcsleep; unlock(q); return -1; } n = BLEN(b); if(n < len){ memmove(p, b->rp, n); } else { memmove(p, b->rp, len); }