From cd9ee403cbcd4f83ef8117ac37e17a030e4f0769 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 21 Mar 1994 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1994-03-21 --- port/portdat.h | 14 +-- port/proc.c | 12 +-- port/qio.c | 270 +++++++++++++++++-------------------------------- port/sysfile.c | 2 +- 4 files changed, 109 insertions(+), 189 deletions(-) diff --git a/port/portdat.h b/port/portdat.h index a2ba42a4cb02768e8bd8af9e97204db7a2ab2cf1..82f2318511a2e763d46a8ba8d096788e770ec81e 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -120,13 +120,13 @@ struct Path struct Block { - Block *next; - Block *list; - - uchar *rp; /* first unconsumed byte */ - uchar *wp; /* first empty byte */ - uchar *lim; /* 1 past the end of the buffer */ - uchar *base; /* start of the buffer */ + Block* next; + Block* list; + int size; /* power of 2 allocation list */ + uchar* rp; /* first unconsumed byte */ + uchar* wp; /* first empty byte */ + uchar* lim; /* 1 past the end of the buffer */ + uchar* base; /* start of the buffer */ uchar flag; }; #define BLEN(s) ((s)->wp - (s)->rp) diff --git a/port/proc.c b/port/proc.c index 5f4f155f5c923f651a99341b802a15b6b3f33afb..4f9111cd779f87ae39ae254b6473da47ee56ce77 100644 --- a/port/proc.c +++ b/port/proc.c @@ -105,6 +105,12 @@ sched(void) gotolabel(&up->sched); } +int +anyready(void) +{ + return m->hiq.head != 0 || m->loq.head != 0; +} + void newcallback(void (*func)(void)) { @@ -113,12 +119,6 @@ newcallback(void (*func)(void)) m->cbin = m->calls; } -int -anyready(void) -{ - return m->hiq.head != 0 || m->loq.head != 0; -} - void callbacks(void) { diff --git a/port/qio.c b/port/qio.c index d81e49fe3bd735b85c9b501822b69a3a9042d81f..c8ffe60e99c90cfa43b925651019083af17d7eb4 100644 --- a/port/qio.c +++ b/port/qio.c @@ -5,42 +5,23 @@ #include "fns.h" #include "../port/error.h" -/* - * interrupt level memory allocation - */ -typedef struct Chunk Chunk; -typedef struct Chunkl Chunkl; -typedef struct Arena Arena; enum { - Minpow= 7, - Maxpow= 16, -}; - -struct Chunk -{ - Chunk *next; + Minpow = 7, + Maxpow = 16, }; -struct Chunkl +struct Pool { Lock; - Chunk *first; + Block* list; + int had; int have; + int want; int goal; - int hist; - int wanted; }; - -struct Arena -{ - Chunkl alloc[Maxpow+1]; - Chunkl freed; - Rendez r; -}; - -static Arena arena; +Pool pool[Maxpow]; /* * IO queues @@ -51,8 +32,8 @@ struct Queue { Lock; - Block *bfirst; /* buffer */ - Block *blast; + Block* bfirst; /* buffer */ + Block* blast; int len; /* bytes in queue */ int limit; /* max bytes in queue */ @@ -60,14 +41,14 @@ struct Queue int eof; /* number of eofs read by user */ void (*kick)(void*); /* restart output */ - void *arg; /* argument to kick */ + void* arg; /* argument to kick */ QLock rlock; /* mutex for reading processes */ Rendez rr; /* process waiting to read */ QLock wlock; /* mutex for writing processes */ Rendez wr; /* process waiting to write */ - uchar *syncbuf; /* synchronous IO buffer */ + uchar* syncbuf; /* synchronous IO buffer */ int synclen; /* syncbuf length */ }; @@ -112,190 +93,129 @@ poison(Block *b) * Manage interrupt level memory allocation. */ static void -iallockproc(void *arg) +iallocmgr(void) { - Chunk *p, *first, **l; - Chunkl *cl; - int pow, x, i; - - USED(arg); - for(;;){ - tsleep(&arena.r, return0, 0, 500); + int pow; - /* really free what was freed at interrupt level */ - cl = &arena.freed; - if(cl->first){ - x = splhi(); - lock(cl); - first = cl->first; - cl->first = 0; - unlock(cl); - splx(x); - - while(first != 0) { - p = first->next; - free(first); - first = p; + attention = 0; + spllo(); + for(pow = Minpow; pow <= Maxpow; pow++) { + p = &pool[pow]; + + /* Low pass filter */ + delta = 3 * (p->had - p->have); + delta = (delta/2) + p->want; + + if(delta < 0) { + lock(p); + p->have -= delta; + bp = p->list; + while(delta--) + p->list = p->list->next; + unlock(p); + spllo(); + while(bp) { + next = bp->next; + free(bp); + bp = next; } + splhi(); } - - /* make sure we have blocks available for interrupt level */ - for(pow = Minpow; pow <= Maxpow; pow++){ - cl = &arena.alloc[pow]; - - /* - * if we've been ahead of the game for a while - * start giving blocks back to the general pool - */ - if(cl->have >= cl->goal){ - cl->hist = ((cl->hist<<1) | 1) & 0xffff; - if(cl->hist == 0xffff && cl->goal > 32) - cl->goal--; - continue; - } else - cl->hist <<= 1; - - /* - * increase goal if we've been drained. - */ - if(cl->have == 0){ - i = cl->goal>>1; - if(cl->wanted > i) - cl->goal += 2*cl->wanted; - else - cl->goal += i; - cl->wanted = 0; - if(cl->goal > 5000) - cl->goal = 5000; - } - - first = 0; - l = &first; - i = cl->goal - cl->have; - for(x = i; x > 0; x--){ - p = malloc(1<next; - } - i -= x; - if(first){ - x = splhi(); - lock(cl); - *l = cl->first; - cl->first = first; - cl->have += i; - unlock(cl); - splx(x); + addr = (ulong)b; + addr = (addr+sizeof(Block)+(BY2V-1)) & ~(BY2V-1); + b->base = (uchar*)addr; + b->rp = b->base; + b->wp = b->base; + b->lim = ((uchar*)b)+size; + b->size = pow; + n++; } + spllo(); + lock(p); + unlock(p); + splhi(); } + p->had = p->have; + p->want = 0; } } void qinit(void) { - int pow; - Chunk *p; - Chunkl *cl; - - /* start with a bunch of initial blocks */ - for(pow = Minpow; pow <= Maxpow; pow++){ - cl = &arena.alloc[pow]; - cl->goal = 4; - if(pow < 12) - cl->goal = Maxpow-pow + 32; - cl->first = 0; - for(; cl->have < cl->goal; cl->have++){ - p = malloc(1<next = cl->first; - cl->first = p; - } - } - -} - -void -iallocinit(void) -{ - /* start garbage collector/creator */ - kproc("ialloc", iallockproc, 0); } void ixsummary(void) { int pow; - Chunkl *cl; + Pool *p; print("size have/goal\n"); for(pow = Minpow; pow <= Maxpow; pow++){ - cl = &arena.alloc[pow]; - print("%d %d/%d\n", 1<have, cl->goal); + cl = &pool[pow]; + print("%d %d/%d\n", 1<have, p->goal); } print("\n"); } /* - * interrupt time allocation (round data base address to 64 bit boundary) + * interrupt time allocation */ Block* iallocb(int size) { int pow; - ulong addr; - Chunkl *cl; - Chunk *p; - Block *b; + Block *bp; - size += sizeof(Block) + 7; - for(pow = Minpow; pow <= Maxpow; pow++){ - if(size <= (1<first; - if(p == 0){ - cl->wanted++; - unlock(cl); - wakeup(&arena.r); - return 0; - } - cl->have--; - cl->first = p->next; - unlock(cl); - - b = (Block *)p; - memset(b, 0, sizeof(Block)); - addr = (ulong)b; - addr = (addr + sizeof(Block) + 7) & ~7; - b->base = (uchar*)addr; - b->wp = b->base; - b->rp = b->base; - b->lim = ((uchar*)b) + (1<= (1<list; + if(p == 0) { + p->want++; + unlock(p); + if(attention == 0) { + attention++; + newcallback(iallocmgr); } + return 0; } - - panic("iallocb %d\n", size); - return 0; /* not reached */ + p->have--; + p->list = bp->next; + unlock(p); + bp->wp = b->base; + bp->rp = b->base; + bp->list = 0; + bp->next = 0; + return bp; } void -ifree(void *a) +ifreeb(Block *bp) { - Chunk *p; - Chunkl *cl; - - cl = &arena.freed; - p = a; - lock(cl); - p->next = cl->first; - cl->first = p; - unlock(cl); + Pool *p; + + p = &pool[bp->size]; + lock(p); + bp->next = p->list; + p->list = bp; + p->have++; + unlock(p); } /* diff --git a/port/sysfile.c b/port/sysfile.c index 0f98dc613499c5822bacecceec29c70779bd5303..3658e0236084681aa0f86b2c5aa08991fed562cc 100644 --- a/port/sysfile.c +++ b/port/sysfile.c @@ -85,7 +85,7 @@ openmode(ulong o) } long -syspath(ulong *arg) +sysfd2path(ulong *arg) { Chan *c;