From 75d90bb5b7dfe29c85fbe05091c09cfc3e640de7 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 28 Aug 1991 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1991-08-28 --- gnot/mmu.c | 12 ++- pc/main.c | 6 +- port/devdk.c | 2 +- port/devlance.c | 37 +++++-- port/devsrv.c | 241 ++++++++++++++-------------------------------- port/filsys.c | 250 ------------------------------------------------ port/service.c | 222 ------------------------------------------ 7 files changed, 112 insertions(+), 658 deletions(-) delete mode 100644 port/filsys.c delete mode 100644 port/service.c diff --git a/gnot/mmu.c b/gnot/mmu.c index 75067dfb42683c73f19fdb4c100cf420cca664bc..b7113a2abb7b233c9091878da89059966db2c6a5 100644 --- a/gnot/mmu.c +++ b/gnot/mmu.c @@ -143,9 +143,13 @@ KMap* kmap(Page *pg) { KMap *k; - int s; + int s = 0; - s = splhi(); + if(u) { + s = u->p->state; + u->p->state = MMUing; + } + lock(&kmapalloc); k = kmapalloc.free; if(k == 0){ @@ -154,10 +158,12 @@ kmap(Page *pg) } kmapalloc.free = k->next; unlock(&kmapalloc); - splx(s); k->pa = pg->pa; putkmmu(k->va, PPN(k->pa) | PTEVALID | PTEKERNEL); + if(s) + u->p->state = s; + return k; } diff --git a/pc/main.c b/pc/main.c index b994647c7eaa7e40e0026ae359dbe967a309e71f..01da2e1c732b9fac6c5a971444d8f649ecc7f7a1 100644 --- a/pc/main.c +++ b/pc/main.c @@ -181,14 +181,14 @@ confinit(void) conf.maxialloc = 2*1024*1024; mul = 1; - conf.nproc = 10 + 10*mul; + conf.nproc = 10 + 20*mul; conf.npgrp = conf.nproc/2; conf.nseg = conf.nproc*3; conf.npagetab = (conf.nseg*14)/10; conf.nswap = conf.nproc*80; conf.nimage = 50; conf.nalarm = 1000; - conf.nchan = 4*conf.nproc; + conf.nchan = 6*conf.nproc; conf.nenv = 4*conf.nproc; conf.nenvchar = 8000*mul; conf.npgenv = 200*mul; @@ -198,7 +198,7 @@ confinit(void) conf.nmntbuf = conf.nmntdev+3; conf.nmnthdr = 2*conf.nmntdev; conf.nsrv = 16*mul; /* was 32 */ - conf.nbitmap = 256*mul; + conf.nbitmap = 512*mul; conf.nbitbyte = conf.nbitmap*1024*screenbits(); conf.nfont = 10*mul; conf.nnoifc = 1; diff --git a/port/devdk.c b/port/devdk.c index e2f5872e9b6e1901eb9f896fe999be762c8167b3..254a592f69ab1ab42e569479271c664ae8500472 100644 --- a/port/devdk.c +++ b/port/devdk.c @@ -1469,7 +1469,7 @@ dkcsckproc(void *a) case T_RESTART: /* datakit reboot */ if(line >=0 && linelines) - dp->lines=line+1; + dp->lines = line+1; break; default: diff --git a/port/devlance.c b/port/devlance.c index b9d7947127c3faed3a5b4bf906cc3427f94c99f9..3b1148b3e531a435e15ac4ed850b51d98701f788 100644 --- a/port/devlance.c +++ b/port/devlance.c @@ -183,7 +183,9 @@ static SoftLance l; * predeclared */ static void lancekproc(void *); -static void lancestart(int); +static void lancestart(int, int); +static void lancedump(void); + /* * lance stream module definition */ @@ -228,7 +230,7 @@ lancestclose(Queue *q) qlock(&l); l.prom--; if(l.prom == 0) - lancestart(0); + lancestart(0, 1); qunlock(&l); } qlock(et); @@ -266,7 +268,7 @@ lanceoput(Queue *q, Block *bp ) qlock(&l); l.prom++; if(l.prom == 1) - lancestart(PROM); + lancestart(PROM, 1); qunlock(&l); } freeb(bp); @@ -283,13 +285,15 @@ lanceoput(Queue *q, Block *bp ) * only one transmitter at a time */ qlock(&l.tlock); + if(waserror()){ + qunlock(&l.tlock); + nexterror(); + } /* * Wait till we get an output buffer */ - if(TSUCC(l.tc) == l.tl){ - sleep(&l.tr, isobuf, (void *)0); - } + sleep(&l.tr, isobuf, (void *)0); p = &l.tp[l.tc]; /* @@ -335,6 +339,7 @@ lanceoput(Queue *q, Block *bp ) *l.rdp = INEA|TDMD; /**/ wbflush(); qunlock(&l.tlock); + poperror(); } /* @@ -377,7 +382,7 @@ lancereset(void) * It may be used to restart a dead lance. */ static void -lancestart(int mode) +lancestart(int mode, int dolock) { int i; Etherpkt *p; @@ -388,8 +393,10 @@ lancestart(int mode) * wait till both receiver and transmitter are * quiescent */ - qlock(&l.tlock); - qlock(&l.rlock); + if(dolock){ + qlock(&l.tlock); + qlock(&l.rlock); + } lancereset(); l.rl = 0; @@ -509,7 +516,7 @@ lanceattach(char *spec) if(l.kstarted == 0){ kproc("lancekproc", lancekproc, 0);/**/ l.kstarted = 1; - lancestart(0); + lancestart(0, 1); } return devattach('l', spec); } @@ -625,6 +632,7 @@ lanceintr(void) int i; ushort csr; Lancemem *lm = LANCEMEM; + static int misses; csr = *l.rdp; @@ -638,6 +646,8 @@ lanceintr(void) */ if(csr & (BABL|MISS|MERR)){ print("lance err %ux\n", csr); + if(csr & MISS) + lancedump(); } if(csr & IDON){ @@ -650,6 +660,7 @@ lanceintr(void) * look for rcv'd packets, just wakeup the input process */ if(l.rl!=l.rc && (MPus(lm->rmr[l.rl].flags) & OWN)==0){ + misses = 0; wakeup(&l.rr); } @@ -757,3 +768,9 @@ stage: sleep(&l.rr, isinput, 0); } } + +static void +lancedump(void) +{ + print("l.rl %d l.rc %d l.tl %d l.tc %d\n", l.rl, l.rc, l.tl, l.tc); +} diff --git a/port/devsrv.c b/port/devsrv.c index e7288f551cfc5224da33b83bda397841d98d01a3..48116f7a75c7accb42e00f0907e6596167f350db 100644 --- a/port/devsrv.c +++ b/port/devsrv.c @@ -4,27 +4,26 @@ #include "dat.h" #include "fns.h" #include "errno.h" -#include "devtab.h" -#include "fcall.h" -void *calloc(unsigned, unsigned); -void free(void *); +#include "devtab.h" -/* This structure holds the contents of a directory entry. Entries are kept - * in a linked list. - */ -typedef struct Entry Entry; -struct Entry { +typedef struct Srv Srv; +struct Srv{ Lock; - Entry *next; /* next entry */ - Entry **back; /* entry pointer */ - Entry *parent; /* parent directory */ - Dir dir; /* dir structure */ - union{ - Chan *chan; /* if not a subdirectory */ - Entry *entries; /* directory entries */ - }; -}; + char *name; + Chan **chan; +}srv; + +int +srvgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) +{ + if(s >= conf.nsrv) + return -1; + if(srv.chan[s] == 0) + return 0; + devdir(c, (Qid){s, 0}, &srv.name[s*NAMELEN], 0, 0666, dp); + return 1; +} void srvinit(void) @@ -34,92 +33,40 @@ srvinit(void) void srvreset(void) { -} - -Entry * -srvalloc(int mode){ - Entry *e; - static Lock qidlock; - static nextqid; - - e = calloc(1, sizeof(Entry)); - e->dir.atime = e->dir.mtime = seconds(); - lock(&qidlock); /* for qid allocation */ - e->dir.qid = (Qid){mode|nextqid++, 0}; - unlock(&qidlock); - return e; + srv.chan = ialloc(conf.nsrv*sizeof(Chan*), 0); + srv.name = ialloc(conf.nsrv*NAMELEN, 0); } Chan * srvattach(char *spec) { - Chan *c; - static Lock rootlock; - static Entry *root; - - lock(&rootlock); - if(root==0){ - root = srvalloc(CHDIR); - root->dir.mode = CHDIR | 0777; - } - unlock(&rootlock); - c = devattach('s', spec); - c->qid = root->dir.qid; - c->aux = root; - return c; + return devattach('s', spec); } Chan * srvclone(Chan *c, Chan *nc) { - nc = devclone(c, nc); - return nc; + return devclone(c, nc); } int srvwalk(Chan *c, char *name) { - Entry *dir, *e; - - isdir(c); - if(strcmp(name, ".") == 0) - return 1; - if((dir=c->aux) == 0) - panic("bad aux pointer in srvwalk"); - if(strcmp(name, "..") == 0) - e = dir->parent; - else{ - lock(dir); - for(e=dir->entries; e; e=e->next) - if (strcmp(name, e->dir.name) == 0) - break; - unlock(dir); - } - if(e==0){ - strncpy(u->error, errstrtab[Enonexist], NAMELEN); - return 0; - } - c->qid = e->dir.qid; - c->aux = e; - return 1; + return devwalk(c, name, 0, 0, srvgen); } void srvstat(Chan *c, char *db) { - Entry *e; - - e = c->aux; - convD2M(&e->dir, db); + devstat(c, db, 0, 0, srvgen); } Chan * srvopen(Chan *c, int omode) { - Entry *e; Chan *f; - if(c->qid.path & CHDIR){ + if(c->qid.path == CHDIR){ if(omode != OREAD) error(Eisdir); c->mode = omode; @@ -127,78 +74,77 @@ srvopen(Chan *c, int omode) c->offset = 0; return c; } - if((e=c->aux) == 0) - error(Egreg); - if((f=e->chan) == 0) + lock(&srv); + if(waserror()){ + unlock(&srv); + nexterror(); + } + f = srv.chan[c->qid.path]; + if(f == 0) error(Eshutdown); - if(omode & OTRUNC) + if(omode&OTRUNC) error(Eperm); if(omode!=f->mode && f->mode!=ORDWR) error(Eperm); close(c); incref(f); + unlock(&srv); + poperror(); return f; } void srvcreate(Chan *c, char *name, int omode, ulong perm) { - Entry *parent, *e; + int j, i; - parent = c->aux; - isdir(c); - lock(parent); - if (waserror()){ - unlock(parent); + if(omode != OWRITE) + error(Eperm); + lock(&srv); + if(waserror()){ + unlock(&srv); nexterror(); } - for(e=parent->entries; e; e=e->next) - if(strcmp(name, e->dir.name) == 0) + j = -1; + for(i=0; iparent = parent; - strcpy(e->dir.name, name); - e->dir.mode = perm & parent->dir.mode; - strcpy(e->dir.gid, parent->dir.gid); - if(e->next = parent->entries) /* assign = */ - e->next->back = &e->next; - e->back = &parent->entries; - *e->back = e; - parent->dir.mtime = e->dir.mtime; - unlock(parent); + } + if(j == -1) + error(Enosrv); + srv.chan[j] = c; + unlock(&srv); poperror(); - c->qid = e->dir.qid; - c->aux = e; + strcpy(&srv.name[j*NAMELEN], name); + c->qid.path = j; c->flag |= COPEN; - c->mode = omode; + c->mode = OWRITE; } void srvremove(Chan *c) { - Entry *e; + Chan *f; - e = c->aux; - if(e->parent == 0) + if(c->qid.path == CHDIR) error(Eperm); - lock(e->parent); + lock(&srv); if(waserror()){ - unlock(e->parent); + unlock(&srv); nexterror(); } - if(e->dir.mode & CHDIR){ - if (e->entries != 0) - error(Eperm); - }else{ - if(e->chan == 0) - error(Eshutdown); - close(e->chan); - } - if(*e->back = e->next) /* assign = */ - e->next->back = e->back; - unlock(e->parent); + f = srv.chan[c->qid.path]; + if(f == 0) + error(Eshutdown); + if(strcmp(&srv.name[c->qid.path*NAMELEN], "boot") == 0) + error(Eperm); + srv.chan[c->qid.path] = 0; + unlock(&srv); poperror(); - free(e); + close(f); } void @@ -212,72 +158,29 @@ srvclose(Chan *c) { } -/* A directory is being read. The entries must be synthesized. e points - * to a list of entries in this directory. Count is the size to be - * read. - */ -int -srvdirentry(Entry *e, char *a, long count){ - Dir dir; - int n; - - n = 0; - while(n!=count && e!=0){ - n += convD2M(&e->dir, a + n); - e = e->next; - } - return n; -} - long srvread(Chan *c, void *va, long n, ulong offset) { - Entry *dir, *e; - - dir = c->aux; isdir(c); - if(n <= 0) - return 0; - if(offset%DIRLEN || n%DIRLEN) - error(Ebaddirread); - lock(dir); - for(e=dir->entries; e; e=e->next) - if(offset <= 0){ - n = srvdirentry(e, va, n); - unlock(dir); - c->offset += n; - return n; - }else - offset -= DIRLEN; - unlock(dir); - return 0; + return devdirread(c, va, n, 0, 0, srvgen); } long srvwrite(Chan *c, void *va, long n, ulong offset) { - Entry *e; int i, fd; char buf[32]; - e = c->aux; - if(e->dir.mode & CHDIR) - panic("write to directory"); - lock(e); - if(waserror()){ - unlock(e); - nexterror(); - } - if(e->chan) + i = c->qid.path; + if(srv.chan[i] != c) /* already been written to */ error(Egreg); if(n >= sizeof buf) error(Egreg); memmove(buf, va, n); /* so we can NUL-terminate */ buf[n] = 0; fd = strtoul(buf, 0, 0); - e->chan = fdtochan(fd, -1); - incref(e->chan); - unlock(e); - poperror(); + fdtochan(fd, -1); /* error check only */ + srv.chan[i] = u->p->fgrp->fd[fd]; + incref(u->p->fgrp->fd[fd]); return n; } diff --git a/port/filsys.c b/port/filsys.c deleted file mode 100644 index bebe542dca38a73c59c5eabf6ac6c3d83aa52f5c..0000000000000000000000000000000000000000 --- a/port/filsys.c +++ /dev/null @@ -1,250 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "errno.h" - -#include "devtab.h" - -#include "fcall.h" - -#define PRINT print - -enum { - Rreadhlen = 8, /* number of chars in Rread message hdr */ -}; - -typedef struct Ftrans Ftrans; - -struct Ftrans{ - long fid; - Chan *c; - Chan *pc; -}; - -static Ftrans *fsyshash; -static Lock fsyslock; - -static void fsysnewchan(Chan *, long, Chan *); -static Chan *fsyschan(Chan *, long); -static int fsyserr(void); - -void -filsysinit(void) -{ - fsyshash = ialloc(conf.nfsyschan * sizeof(Ftrans), 0); -} - -void -filsys(Chan *protoc, char *msg, long msgn) -{ - Fcall r, t, *rf, *tf; - Chan *c, *c0; - long fid, n; - - if(!convM2S(msg, &r, msgn)){ - error(Ebadmsg); - } - rf = &r; - tf = &t; - if(waserror()){ - tf->type = Rerror; - strncpy(tf->ename, u->error, sizeof(tf->ename)); - goto Errret; - } - fid = rf->fid; - if(rf->type != Tattach) - c = fsyschan(protoc, fid); - switch(rf->type){ - case Tattach: - c = clone(u->slash, 0); - fsysnewchan(protoc, fid, c); - break; - case Tclone: - c0 = clone(c, 0); - c0 = domount(c0); - fsysnewchan(protoc, rf->newfid, c0); - break; - case Twalk: - if((c0 = walk(c, rf->name, 1)) == 0) - error(Enonexist); - if(c != c0) - fsysnewchan(protoc, fid, c0); - tf->qid = c0->qid; - break; - case Topen: - c0 = (*devtab[c->type].open)(c, rf->mode); - if(c != c0) - fsysnewchan(protoc, fid, c0); - if(rf->mode & OCEXEC) - c0->flag |= CCEXEC; - break; - case Tcreate: - if((c->flag&(CMOUNT|CCREATE)) == CMOUNT) - c0 = createdir(c); - (*devtab[c->type].create)(c, rf->name, rf->mode, rf->perm); - if(rf->mode & OCEXEC) - c->flag |= CCEXEC; - break; - case Tread: - qlock(c); - if(waserror()){ - qunlock(c); - nexterror(); - } - n = rf->count; - tf->count = 0; - /* overwrite the input msg -- assumes buffer is big enough */ - tf->data = msg+Rreadhlen; - if(c->qid.path&CHDIR){ - n -= n%DIRLEN; - if(c->offset%DIRLEN || n==0) - error(Ebaddirread); - } - if((c->qid.path&CHDIR) && (c->flag&CMOUNT)) - n = unionread(c, tf->data, n); - else - n = (*devtab[c->type].read)(c, tf->data, n); - c->offset += n; - qunlock(c); - poperror(); - tf->count = n; - break; - case Twrite: - qlock(c); - if(waserror()){ - qunlock(c); - nexterror(); - } - if(c->qid.path & CHDIR) - error(Eisdir); - n = rf->count; - tf->count = 0; - n = (*devtab[c->type].write)(c, rf->data, n); - c->offset += n; - qunlock(c); - poperror(); - tf->count = n; - break; - case Tclunk: - close(c); - fsysnewchan(protoc, rf->fid, 0); - break; - case Tremove: - (*devtab[c->type].remove)(c); - break; - case Tstat: - (*devtab[c->type].stat)(c, tf->stat); - break; - case Twstat: - (*devtab[c->type].wstat)(c, rf->stat); - break; - case Tflush: - /* really, this message has to be handled by caller */ - break; - default: - error(Ebadmsg); - } - poperror(); - tf->type = rf->type+1; - Errret: - tf->fid = rf->fid; - tf->tag = rf->tag; - /* assume can reuse msg buf */ - n = convS2M(tf, msg); - qlock(protoc); - if(waserror()){ - qunlock(protoc); - nexterror(); - } - (*devtab[protoc->type].write)(protoc, msg, n); - qunlock(protoc); - poperror(); -} - -/* - * hash table discipline: linear probe - * a fid of 0 means 'free'; a fid of -1 means 'deleted' - * use a function as per Knuth - * only a function of fid, but protoc checked for match - */ -static int -fhash(long fid) -{ - long x; - - x = fid*29128; - if(x < 0) - x = -x; - x %= 262143; - return x % conf.nfsyschan; -} - -/* - * Register channel c for fid (if c!= 0). - * If c==0, unregister. - * The protoc argument is used to disambiguate - * identical fids from different attaches. - */ -static void -fsysnewchan(Chan *protoc, long fid, Chan *c) -{ - int i, m; - Ftrans *f, *fstop, *fend; - - i = fhash(fid); - f = fsyshash+i; - m = conf.nfsyschan; - fstop = f+(i+m-1)%m; - fend = fsyshash+m; - lock(&fsyslock); - while(f != fstop){ - if(f->fid == fid && f->pc == protoc){ - if(c) - f->c = c; - else - f->fid = -1; - break; - } - if(f->fid <= 0){ - f->c = c; - f->fid = fid; - f->pc = protoc; - break; - } - if(++f == fend) - f = fsyshash; - } - unlock(&fsyslock); - if(f == fstop) - error(Enofilsys); -} - -/* Return the channel registered for fid */ -static Chan* -fsyschan(Chan *protoc, long fid) -{ - int i, m; - Ftrans *f, *fstop, *fend; - - i = fhash(fid); - f = fsyshash+i; - if(f->fid == fid && f->pc == protoc) - return f->c; - m = conf.nfsyschan; - fstop = f; - if(++f == fend) - f = fsyshash; - fend = fsyshash+m; - while(f != fstop){ - if(f->fid == fid && f->pc == protoc) - return f->c; - if(f->fid == 0) - break; - if(++f == fend) - f = fsyshash; - } - error(Egreg); -} - diff --git a/port/service.c b/port/service.c deleted file mode 100644 index 8da9e8bd3a60203df4884b23b1ace0a695349486..0000000000000000000000000000000000000000 --- a/port/service.c +++ /dev/null @@ -1,222 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "errno.h" - -#include "fcall.h" - -#define BUFSIZE (MAXFDATA+500) /* BUG */ -typedef struct Buffer Buffer; -struct Buffer -{ - Buffer *next; - char buf[BUFSIZE]; -}; - -struct Servalloc { - Lock; - Service *all; - Service *freel; - Buffer *ball; - Buffer *bfreel; -} servalloc; - - -/* - * allocate the taks force structures and put them - * on the free list - */ -void -serviceinit(void) -{ - Service *s; - Buffer *b; - - servalloc.all = ialloc(conf.nservice * sizeof(Service), 0); - servalloc.freel = servalloc.all; - for(s = servalloc.all; s < &servalloc.all[conf.nservice-1]; s++) - s->next = s+1; - - servalloc.ball = ialloc(2*conf.nservice * sizeof(Service), 0); - servalloc.bfreel = servalloc.ball; - for(b = servalloc.ball; b < &servalloc.ball[2*conf.nservice-1]; b++) - b->next = b+1; -} - -/* - * Add a process to a service - */ -static Proc * -reinforce(Service *s) -{ - int i; - Proc *p; - - /* - * don't start one up if we already have too many, - * return our own process number - */ - lock(s); - if(s->ref == NSTUB){ - unlock(s); - return u->p; - } - s->ref++; - unlock(s); - - /* - * create it - */ - return kproc(s->name, 0, 0); -} - -/* - * resign from a service - */ -static void -resign(Service *s) -{ - int i; - - print("%lux resigning\n", u->p); - if(decref(s) == 0){ - print("freeing service\n"); - close(s->inc); - close(s->outc); - lock(&servalloc); - s->next = servalloc.freel; - servalloc.freel = s; - unlock(&servalloc); - } - pexit(0, 1); -} - -/* - * Create a service of kernel processes to handle file system requests. - * (*doit)() is a function that handles that event. Service - * dynamicly creates new processes (up to MAXTASK) to ensure that 1 process - * is always awaiting while others are doing. - */ -void -service(char *name, Chan *cin, Chan *cout, void (*doit)(Chan*, char*, long)) -{ - void *a; - Service *s; - Buffer *b; - long n; - - b = 0; - - /* - * allocate a service - */ - lock(&servalloc); - s = servalloc.freel; - if(s == 0) - panic("no more services"); - servalloc.freel = s->next; - unlock(&servalloc); - memset(s, 0, sizeof(Service)); - if(name==0 || *name==0) - strcpy(name, "filsys"); - else - strncpy(s->name, name, sizeof(s->name)); - s->inc = cin; - s->outc = cout; - s->die = 0; - incref(cin); - incref(cout); - - if(waserror()){ - /* - * tell everyone else to die - */ - s->die = 1; - - /* - * wake up the next guy - */ - qunlock(&s->alock); - - /* - * free the buffer if we have one - */ - if(b){ - lock(&servalloc); - b->next = servalloc.bfreel; - servalloc.bfreel = b; - unlock(&servalloc); - } - resign(s); - } - - /* - * Create the first process in the service. The - * caller returns. - */ - if(reinforce(s)){ - poperror(); - return; - } - - /* - * first process enters the infinite loop - */ - for(;;){ - b = 0; - qlock(&s->alock); - - /* - * if there's more than 1 process waiting, we're - * superfluous - */ - if(s->die || s->alock.head && s->alock.head!=s->alock.tail){ - qunlock(&s->alock); - resign(s); - } - - /* - * get a buffer - */ - lock(&servalloc); - b = servalloc.bfreel; - if(b == 0){ - print("no serv buffers\n"); - unlock(&servalloc); - continue; - } - servalloc.bfreel = b->next; - unlock(&servalloc); - - /* - * wait for something to happen - */ - n = (*devtab[cin->type].read)(cin, b->buf, sizeof(b->buf)); - if(n <= 0) - error(Ehungup); - - /* - * create a new process if none are waiting to - * take over - */ - if(s->alock.head == 0) - if(reinforce(s) == 0) - continue; - qunlock(&s->alock); - - /* - * process an event - */ - (*doit)(cout, b->buf, n); - - /* - * release the buffer - */ - lock(&servalloc); - b->next = servalloc.bfreel; - servalloc.bfreel = b; - unlock(&servalloc); - } -}