| #include <u.h> |
| #include <libc.h> |
| #include <venti.h> |
| #include <libsec.h> |
| |
| typedef struct Mem Mem; |
| typedef struct Frag Frag; |
| |
| enum { |
| BigMemSize = MaxFragSize, |
| SmallMemSize = BigMemSize/8, |
| NLocalFrag = 2 |
| }; |
| |
| /* position to carve out of a Mem */ |
| enum { |
| PFront, |
| PMiddle, |
| PEnd |
| }; |
| |
| struct Mem |
| { |
| Lock lk; |
| int ref; |
| uchar *bp; |
| uchar *ep; |
| uchar *rp; |
| uchar *wp; |
| Mem *next; |
| }; |
| |
| enum { |
| FragLocalFree, |
| FragLocalAlloc, |
| FragGlobal |
| }; |
| |
| struct Frag |
| { |
| int state; |
| Mem *mem; |
| uchar *rp; |
| uchar *wp; |
| Frag *next; |
| void (*free)(void*); |
| void *a; |
| Packet *p; /* parent packet, for debugging only */ |
| }; |
| |
| struct Packet |
| { |
| int size; |
| int asize; /* allocated memory - greater than size unless foreign frags */ |
| ulong pc; |
| |
| Packet *next; |
| |
| Frag *first; |
| Frag *last; |
| |
| Frag local[NLocalFrag]; |
| }; |
| |
| static Frag *fragalloc(Packet*, int n, int pos, Frag *next); |
| static Frag *fragdup(Packet*, Frag*); |
| static void fragfree(Frag*); |
| |
| static Mem *memalloc(int, int); |
| static void memfree(Mem*); |
| static int memhead(Mem *m, uchar *rp, int n); |
| static int memtail(Mem *m, uchar *wp, int n); |
| |
| static char EPacketSize[] = "bad packet size"; |
| static char EPacketOffset[] = "bad packet offset"; |
| static char EBadSize[] = "bad size"; |
| |
| #ifdef NOTDEF |
| static void checkpacket(Packet*); |
| #endif |
| |
| /* |
| * the free list is primarily for speed, but it is |
| * also necessary for packetsplit that packets |
| * are never freed -- a packet can contain a different |
| * packet's local fragments, thanks to packetsplit! |
| */ |
| static struct { |
| Lock lk; |
| Packet *packet; |
| int npacket; |
| Frag *frag; |
| int nfrag; |
| Mem *bigmem; |
| int nbigmem; |
| Mem *smallmem; |
| int nsmallmem; |
| } freelist; |
| |
| #define FRAGSIZE(f) ((f)->wp - (f)->rp) |
| #define FRAGASIZE(f) ((f)->mem ? (f)->mem->ep - (f)->mem->bp : 0) |
| |
| #define NOTFREE(p) assert((p)->size>=0)/*; checkpacket(p)*/ |
| |
| Packet * |
| packetalloc(void) |
| { |
| Packet *p; |
| |
| lock(&freelist.lk); |
| p = freelist.packet; |
| if(p != nil) |
| freelist.packet = p->next; |
| else |
| freelist.npacket++; |
| unlock(&freelist.lk); |
| |
| if(p == nil) |
| p = vtbrk(sizeof(Packet)); |
| else |
| assert(p->size == -1); |
| p->size = 0; |
| p->asize = 0; |
| p->first = nil; |
| p->last = nil; |
| p->next = nil; |
| p->pc = getcallerpc((char*)&p+8); /* might not work, but fine */ |
| |
| NOTFREE(p); |
| return p; |
| } |
| |
| void |
| packetfree(Packet *p) |
| { |
| Frag *f, *ff; |
| |
| if(p == nil) |
| return; |
| |
| NOTFREE(p); |
| p->pc = getcallerpc(&p); |
| |
| for(f=p->first; f!=nil; f=ff) { |
| ff = f->next; |
| fragfree(f); |
| } |
| p->first = (void*)0xDeadBeef; |
| p->last = (void*)0xDeadBeef; |
| p->size = -1; |
| |
| lock(&freelist.lk); |
| p->next = freelist.packet; |
| freelist.packet = p; |
| unlock(&freelist.lk); |
| } |
| |
| Packet * |
| packetdup(Packet *p, int offset, int n) |
| { |
| Frag *f, *ff; |
| Packet *pp; |
| |
| NOTFREE(p); |
| if(offset < 0 || n < 0 || offset+n > p->size) { |
| werrstr(EBadSize); |
| return nil; |
| } |
| |
| pp = packetalloc(); |
| pp->pc = getcallerpc(&p); |
| if(n == 0){ |
| NOTFREE(pp); |
| return pp; |
| } |
| |
| pp->size = n; |
| |
| /* skip offset */ |
| for(f=p->first; offset >= FRAGSIZE(f); f=f->next) |
| offset -= FRAGSIZE(f); |
| |
| /* first frag */ |
| ff = fragdup(pp, f); |
| ff->rp += offset; |
| pp->first = ff; |
| n -= FRAGSIZE(ff); |
| pp->asize += FRAGASIZE(ff); |
| |
| /* the remaining */ |
| while(n > 0) { |
| f = f->next; |
| ff->next = fragdup(pp, f); |
| ff = ff->next; |
| n -= FRAGSIZE(ff); |
| pp->asize += FRAGASIZE(ff); |
| } |
| |
| /* fix up last frag: note n <= 0 */ |
| ff->wp += n; |
| ff->next = nil; |
| pp->last = ff; |
| |
| NOTFREE(pp); |
| NOTFREE(p); |
| return pp; |
| } |
| |
| Packet * |
| packetsplit(Packet *p, int n) |
| { |
| Packet *pp; |
| Frag *f, *ff; |
| |
| NOTFREE(p); |
| if(n < 0 || n > p->size) { |
| werrstr(EPacketSize); |
| return nil; |
| } |
| |
| pp = packetalloc(); |
| pp->pc = getcallerpc(&p); |
| if(n == 0){ |
| NOTFREE(pp); |
| return pp; |
| } |
| |
| pp->size = n; |
| p->size -= n; |
| ff = nil; |
| for(f=p->first; n > 0 && n >= FRAGSIZE(f); f=f->next) { |
| n -= FRAGSIZE(f); |
| p->asize -= FRAGASIZE(f); |
| pp->asize += FRAGASIZE(f); |
| f->p = pp; |
| ff = f; |
| } |
| |
| /* split shared frag */ |
| if(n > 0) { |
| f->p = pp; |
| ff = f; |
| f = fragdup(p, ff); |
| pp->asize += FRAGASIZE(ff); |
| ff->wp = ff->rp + n; |
| f->rp += n; |
| } |
| |
| pp->first = p->first; |
| pp->last = ff; |
| ff->next = nil; |
| p->first = f; |
| if(f == nil || f->next == nil) |
| p->last = f; |
| NOTFREE(pp); |
| NOTFREE(p); |
| return pp; |
| } |
| |
| int |
| packetconsume(Packet *p, uchar *buf, int n) |
| { |
| NOTFREE(p); |
| if(buf && packetcopy(p, buf, 0, n) < 0) |
| return -1; |
| return packettrim(p, n, p->size-n); |
| } |
| |
| int |
| packettrim(Packet *p, int offset, int n) |
| { |
| Frag *f, *ff; |
| |
| NOTFREE(p); |
| if(offset < 0 || offset > p->size) { |
| werrstr(EPacketOffset); |
| return -1; |
| } |
| |
| if(n < 0 || offset + n > p->size) { |
| werrstr(EPacketOffset); |
| return -1; |
| } |
| |
| p->size = n; |
| |
| /* easy case */ |
| if(n == 0) { |
| for(f=p->first; f != nil; f=ff) { |
| ff = f->next; |
| fragfree(f); |
| } |
| p->first = p->last = nil; |
| p->asize = 0; |
| NOTFREE(p); |
| return 0; |
| } |
| |
| /* free before offset */ |
| for(f=p->first; offset >= FRAGSIZE(f); f=ff) { |
| p->asize -= FRAGASIZE(f); |
| offset -= FRAGSIZE(f); |
| ff = f->next; |
| fragfree(f); |
| } |
| |
| /* adjust frag */ |
| f->rp += offset; |
| p->first = f; |
| |
| /* skip middle */ |
| for(; n > 0 && n > FRAGSIZE(f); f=f->next) |
| n -= FRAGSIZE(f); |
| |
| /* adjust end */ |
| f->wp = f->rp + n; |
| p->last = f; |
| ff = f->next; |
| f->next = nil; |
| |
| /* free after */ |
| for(f=ff; f != nil; f=ff) { |
| p->asize -= FRAGASIZE(f); |
| ff = f->next; |
| fragfree(f); |
| } |
| NOTFREE(p); |
| return 0; |
| } |
| |
| uchar * |
| packetheader(Packet *p, int n) |
| { |
| Frag *f; |
| Mem *m; |
| |
| NOTFREE(p); |
| if(n <= 0 || n > MaxFragSize) { |
| werrstr(EPacketSize); |
| return nil; |
| } |
| |
| p->size += n; |
| |
| /* try and fix in current frag */ |
| f = p->first; |
| if(f != nil) { |
| m = f->mem; |
| if(n <= f->rp - m->bp) |
| if(m->ref == 1 || memhead(m, f->rp, n) >= 0) { |
| f->rp -= n; |
| NOTFREE(p); |
| return f->rp; |
| } |
| } |
| |
| /* add frag to front */ |
| f = fragalloc(p, n, PEnd, p->first); |
| p->asize += FRAGASIZE(f); |
| if(p->first == nil) |
| p->last = f; |
| p->first = f; |
| NOTFREE(p); |
| return f->rp; |
| } |
| |
| uchar * |
| packettrailer(Packet *p, int n) |
| { |
| Mem *m; |
| Frag *f; |
| |
| NOTFREE(p); |
| if(n <= 0 || n > MaxFragSize) { |
| werrstr(EPacketSize); |
| return nil; |
| } |
| |
| p->size += n; |
| |
| /* try and fix in current frag */ |
| if(p->first != nil) { |
| f = p->last; |
| m = f->mem; |
| if(n <= m->ep - f->wp) |
| if(m->ref == 1 || memtail(m, f->wp, n) >= 0) { |
| f->wp += n; |
| NOTFREE(p); |
| return f->wp - n; |
| } |
| } |
| |
| /* add frag to end */ |
| f = fragalloc(p, n, (p->first == nil)?PMiddle:PFront, nil); |
| p->asize += FRAGASIZE(f); |
| if(p->first == nil) |
| p->first = f; |
| else |
| p->last->next = f; |
| p->last = f; |
| NOTFREE(p); |
| return f->rp; |
| } |
| |
| void |
| packetprefix(Packet *p, uchar *buf, int n) |
| { |
| Frag *f; |
| int nn; |
| Mem *m; |
| |
| NOTFREE(p); |
| if(n <= 0) |
| return; |
| |
| p->size += n; |
| |
| /* try and fix in current frag */ |
| f = p->first; |
| if(f != nil) { |
| m = f->mem; |
| nn = f->rp - m->bp; |
| if(nn > n) |
| nn = n; |
| if(m->ref == 1 || memhead(m, f->rp, nn) >= 0) { |
| f->rp -= nn; |
| n -= nn; |
| memmove(f->rp, buf+n, nn); |
| } |
| } |
| |
| while(n > 0) { |
| nn = n; |
| if(nn > MaxFragSize) |
| nn = MaxFragSize; |
| f = fragalloc(p, nn, PEnd, p->first); |
| p->asize += FRAGASIZE(f); |
| if(p->first == nil) |
| p->last = f; |
| p->first = f; |
| n -= nn; |
| memmove(f->rp, buf+n, nn); |
| } |
| NOTFREE(p); |
| } |
| |
| void |
| packetappend(Packet *p, uchar *buf, int n) |
| { |
| Frag *f; |
| int nn; |
| Mem *m; |
| |
| NOTFREE(p); |
| if(n <= 0) |
| return; |
| |
| p->size += n; |
| /* try and fix in current frag */ |
| if(p->first != nil) { |
| f = p->last; |
| m = f->mem; |
| nn = m->ep - f->wp; |
| if(nn > n) |
| nn = n; |
| if(m->ref == 1 || memtail(m, f->wp, nn) >= 0) { |
| memmove(f->wp, buf, nn); |
| f->wp += nn; |
| buf += nn; |
| n -= nn; |
| } |
| } |
| |
| while(n > 0) { |
| nn = n; |
| if(nn > MaxFragSize) |
| nn = MaxFragSize; |
| f = fragalloc(p, nn, (p->first == nil)?PMiddle:PFront, nil); |
| p->asize += FRAGASIZE(f); |
| if(p->first == nil) |
| p->first = f; |
| else |
| p->last->next = f; |
| p->last = f; |
| memmove(f->rp, buf, nn); |
| buf += nn; |
| n -= nn; |
| } |
| NOTFREE(p); |
| } |
| |
| void |
| packetconcat(Packet *p, Packet *pp) |
| { |
| Frag *f; |
| |
| NOTFREE(p); |
| NOTFREE(pp); |
| if(pp->size == 0) |
| return; |
| p->size += pp->size; |
| p->asize += pp->asize; |
| for(f=pp->first; f; f=f->next) |
| f->p = p; |
| |
| if(p->first != nil) |
| p->last->next = pp->first; |
| else |
| p->first = pp->first; |
| |
| p->last = pp->last; |
| pp->size = 0; |
| pp->asize = 0; |
| pp->first = nil; |
| pp->last = nil; |
| NOTFREE(p); |
| NOTFREE(pp); |
| } |
| |
| uchar * |
| packetpeek(Packet *p, uchar *buf, int offset, int n) |
| { |
| Frag *f; |
| int nn; |
| uchar *b; |
| |
| NOTFREE(p); |
| if(n == 0) |
| return buf; |
| |
| if(offset < 0 || offset >= p->size) { |
| werrstr(EPacketOffset); |
| return nil; |
| } |
| |
| if(n < 0 || offset + n > p->size) { |
| werrstr(EPacketSize); |
| return nil; |
| } |
| |
| /* skip up to offset */ |
| for(f=p->first; offset >= FRAGSIZE(f); f=f->next) |
| offset -= FRAGSIZE(f); |
| |
| /* easy case */ |
| if(offset + n <= FRAGSIZE(f)){ |
| NOTFREE(p); |
| return f->rp + offset; |
| } |
| |
| for(b=buf; n>0; n -= nn) { |
| nn = FRAGSIZE(f) - offset; |
| if(nn > n) |
| nn = n; |
| memmove(b, f->rp+offset, nn); |
| offset = 0; |
| f = f->next; |
| b += nn; |
| } |
| |
| NOTFREE(p); |
| return buf; |
| } |
| |
| int |
| packetcopy(Packet *p, uchar *buf, int offset, int n) |
| { |
| uchar *b; |
| |
| NOTFREE(p); |
| b = packetpeek(p, buf, offset, n); |
| if(b == nil) |
| return -1; |
| if(b != buf) |
| memmove(buf, b, n); |
| return 0; |
| } |
| |
| int |
| packetfragments(Packet *p, IOchunk *io, int nio, int offset) |
| { |
| Frag *f; |
| int size; |
| IOchunk *eio; |
| |
| NOTFREE(p); |
| if(p->size == 0 || nio <= 0) |
| return 0; |
| |
| if(offset < 0 || offset > p->size) { |
| werrstr(EPacketOffset); |
| return -1; |
| } |
| |
| for(f=p->first; offset >= FRAGSIZE(f); f=f->next) |
| offset -= FRAGSIZE(f); |
| |
| size = 0; |
| eio = io + nio; |
| for(; f != nil && io < eio; f=f->next) { |
| io->addr = f->rp + offset; |
| io->len = f->wp - (f->rp + offset); |
| offset = 0; |
| size += io->len; |
| io++; |
| } |
| for(; io < eio; io++){ |
| io->addr = nil; |
| io->len = 0; |
| } |
| return size; |
| } |
| |
| void |
| packetstats(void) |
| { |
| Packet *p; |
| Frag *f; |
| Mem *m; |
| |
| int np, nf, nsm, nbm; |
| |
| lock(&freelist.lk); |
| np = 0; |
| for(p=freelist.packet; p; p=p->next) |
| np++; |
| nf = 0; |
| for(f=freelist.frag; f; f=f->next) |
| nf++; |
| nsm = 0; |
| for(m=freelist.smallmem; m; m=m->next) |
| nsm++; |
| nbm = 0; |
| for(m=freelist.bigmem; m; m=m->next) |
| nbm++; |
| |
| fprint(2, "packet: %d/%d frag: %d/%d small mem: %d/%d big mem: %d/%d\n", |
| np, freelist.npacket, |
| nf, freelist.nfrag, |
| nsm, freelist.nsmallmem, |
| nbm, freelist.nbigmem); |
| |
| unlock(&freelist.lk); |
| } |
| |
| |
| uint |
| packetsize(Packet *p) |
| { |
| NOTFREE(p); |
| if(1) { |
| Frag *f; |
| int size = 0; |
| |
| for(f=p->first; f; f=f->next) |
| size += FRAGSIZE(f); |
| if(size != p->size) |
| fprint(2, "packetsize %d %d\n", size, p->size); |
| assert(size == p->size); |
| } |
| return p->size; |
| } |
| |
| uint |
| packetasize(Packet *p) |
| { |
| NOTFREE(p); |
| if(0) { |
| Frag *f; |
| int asize = 0; |
| |
| for(f=p->first; f; f=f->next) |
| asize += FRAGASIZE(f); |
| if(asize != p->asize) |
| fprint(2, "packetasize %d %d\n", asize, p->asize); |
| assert(asize == p->asize); |
| } |
| return p->asize; |
| } |
| |
| void |
| packetsha1(Packet *p, uchar digest[VtScoreSize]) |
| { |
| DigestState ds; |
| Frag *f; |
| int size; |
| |
| NOTFREE(p); |
| memset(&ds, 0, sizeof ds); |
| size = p->size; |
| for(f=p->first; f; f=f->next) { |
| sha1(f->rp, FRAGSIZE(f), nil, &ds); |
| size -= FRAGSIZE(f); |
| } |
| assert(size == 0); |
| sha1(nil, 0, digest, &ds); |
| } |
| |
| int |
| packetcmp(Packet *pkt0, Packet *pkt1) |
| { |
| Frag *f0, *f1; |
| int n0, n1, x; |
| |
| NOTFREE(pkt0); |
| NOTFREE(pkt1); |
| f0 = pkt0->first; |
| f1 = pkt1->first; |
| |
| if(f0 == nil) |
| return (f1 == nil)?0:-1; |
| if(f1 == nil) |
| return 1; |
| n0 = FRAGSIZE(f0); |
| n1 = FRAGSIZE(f1); |
| |
| for(;;) { |
| if(n0 < n1) { |
| x = memcmp(f0->wp - n0, f1->wp - n1, n0); |
| if(x != 0) |
| return x; |
| n1 -= n0; |
| f0 = f0->next; |
| if(f0 == nil) |
| return -1; |
| n0 = FRAGSIZE(f0); |
| } else if (n0 > n1) { |
| x = memcmp(f0->wp - n0, f1->wp - n1, n1); |
| if(x != 0) |
| return x; |
| n0 -= n1; |
| f1 = f1->next; |
| if(f1 == nil) |
| return 1; |
| n1 = FRAGSIZE(f1); |
| } else { /* n0 == n1 */ |
| x = memcmp(f0->wp - n0, f1->wp - n1, n0); |
| if(x != 0) |
| return x; |
| f0 = f0->next; |
| f1 = f1->next; |
| if(f0 == nil) |
| return (f1 == nil)?0:-1; |
| if(f1 == nil) |
| return 1; |
| n0 = FRAGSIZE(f0); |
| n1 = FRAGSIZE(f1); |
| } |
| } |
| } |
| |
| static Frag * |
| fragalloc(Packet *p, int n, int pos, Frag *next) |
| { |
| Frag *f, *ef; |
| Mem *m; |
| |
| /* look for local frag */ |
| f = &p->local[0]; |
| ef = &p->local[NLocalFrag]; |
| for(;f<ef; f++) { |
| if(f->state == FragLocalFree) { |
| f->state = FragLocalAlloc; |
| goto Found; |
| } |
| } |
| lock(&freelist.lk); |
| f = freelist.frag; |
| if(f != nil) |
| freelist.frag = f->next; |
| else |
| freelist.nfrag++; |
| unlock(&freelist.lk); |
| |
| if(f == nil) { |
| f = vtbrk(sizeof(Frag)); |
| f->state = FragGlobal; |
| } |
| |
| Found: |
| f->next = next; |
| f->p = p; |
| |
| if(n == 0){ |
| f->mem = 0; |
| f->rp = 0; |
| f->wp = 0; |
| return f; |
| } |
| |
| if(pos == PEnd && next == nil) |
| pos = PMiddle; |
| m = memalloc(n, pos); |
| f->mem = m; |
| f->rp = m->rp; |
| f->wp = m->wp; |
| return f; |
| } |
| |
| Packet* |
| packetforeign(uchar *buf, int n, void (*free)(void *a), void *a) |
| { |
| Packet *p; |
| Frag *f; |
| |
| p = packetalloc(); |
| p->pc = getcallerpc(&buf); |
| f = fragalloc(p, 0, 0, nil); |
| f->free = free; |
| f->a = a; |
| f->next = nil; |
| f->rp = buf; |
| f->wp = buf+n; |
| |
| p->first = f; |
| p->last = f; |
| p->size = n; |
| NOTFREE(p); |
| return p; |
| } |
| |
| static Frag * |
| fragdup(Packet *p, Frag *f) |
| { |
| Frag *ff; |
| Mem *m; |
| |
| m = f->mem; |
| |
| /* |
| * m->rp && m->wp can be out of date when ref == 1 |
| * also, potentially reclaims space from previous frags |
| */ |
| if(m && m->ref == 1) { |
| m->rp = f->rp; |
| m->wp = f->wp; |
| } |
| |
| ff = fragalloc(p, 0, 0, nil); |
| ff->mem = f->mem; |
| ff->rp = f->rp; |
| ff->wp = f->wp; |
| ff->next = f->next; |
| |
| /* |
| * We can't duplicate these -- there's no dup function. |
| */ |
| assert(f->free==nil && f->a==nil); |
| |
| if(m){ |
| lock(&m->lk); |
| m->ref++; |
| unlock(&m->lk); |
| } |
| |
| |
| return ff; |
| } |
| |
| |
| static void |
| fragfree(Frag *f) |
| { |
| if(f->mem == nil){ |
| if(f->free) |
| (*f->free)(f->a); |
| }else{ |
| memfree(f->mem); |
| f->mem = 0; |
| } |
| |
| if(f->state == FragLocalAlloc) { |
| f->state = FragLocalFree; |
| return; |
| } |
| |
| lock(&freelist.lk); |
| f->next = freelist.frag; |
| freelist.frag = f; |
| unlock(&freelist.lk); |
| } |
| |
| static Mem * |
| memalloc(int n, int pos) |
| { |
| Mem *m; |
| int nn; |
| |
| if(n < 0 || n > MaxFragSize) { |
| werrstr(EPacketSize); |
| return nil; |
| } |
| if(n <= SmallMemSize) { |
| lock(&freelist.lk); |
| m = freelist.smallmem; |
| if(m != nil) |
| freelist.smallmem = m->next; |
| else |
| freelist.nsmallmem++; |
| unlock(&freelist.lk); |
| nn = SmallMemSize; |
| } else { |
| lock(&freelist.lk); |
| m = freelist.bigmem; |
| if(m != nil) |
| freelist.bigmem = m->next; |
| else |
| freelist.nbigmem++; |
| unlock(&freelist.lk); |
| nn = BigMemSize; |
| } |
| |
| if(m == nil) { |
| m = vtbrk(sizeof(Mem)); |
| m->bp = vtbrk(nn); |
| m->ep = m->bp + nn; |
| } |
| assert(m->ref == 0); |
| m->ref = 1; |
| |
| switch(pos) { |
| default: |
| assert(0); |
| case PFront: |
| m->rp = m->bp; |
| break; |
| case PMiddle: |
| /* leave a little bit at end */ |
| m->rp = m->ep - n - 32; |
| break; |
| case PEnd: |
| m->rp = m->ep - n; |
| break; |
| } |
| /* check we did not blow it */ |
| if(m->rp < m->bp) |
| m->rp = m->bp; |
| m->wp = m->rp + n; |
| assert(m->rp >= m->bp && m->wp <= m->ep); |
| return m; |
| } |
| |
| static void |
| memfree(Mem *m) |
| { |
| lock(&m->lk); |
| m->ref--; |
| if(m->ref > 0) { |
| unlock(&m->lk); |
| return; |
| } |
| unlock(&m->lk); |
| assert(m->ref == 0); |
| |
| /* memset(m->bp, 0xEF, m->ep-m->bp); */ |
| switch(m->ep - m->bp) { |
| default: |
| assert(0); |
| case SmallMemSize: |
| lock(&freelist.lk); |
| m->next = freelist.smallmem; |
| freelist.smallmem = m; |
| unlock(&freelist.lk); |
| break; |
| case BigMemSize: |
| lock(&freelist.lk); |
| m->next = freelist.bigmem; |
| freelist.bigmem = m; |
| unlock(&freelist.lk); |
| break; |
| } |
| } |
| |
| static int |
| memhead(Mem *m, uchar *rp, int n) |
| { |
| fprint(2, "memhead called\n"); |
| abort(); |
| lock(&m->lk); |
| if(m->rp != rp) { |
| unlock(&m->lk); |
| return -1; |
| } |
| m->rp -= n; |
| unlock(&m->lk); |
| return 0; |
| } |
| |
| static int |
| memtail(Mem *m, uchar *wp, int n) |
| { |
| fprint(2, "memtail called\n"); |
| abort(); |
| lock(&m->lk); |
| if(m->wp != wp) { |
| unlock(&m->lk); |
| return -1; |
| } |
| m->wp += n; |
| unlock(&m->lk); |
| return 0; |
| } |
| |
| #ifdef NOTDEF |
| static void |
| checkpacket(Packet *p) |
| { |
| int s, as; |
| Frag *f; |
| Frag *ff; |
| |
| s = 0; |
| as = 0; |
| ff=p->first; |
| for(f=p->first; f; ff=f,f=f->next){ |
| assert(f->p == p); |
| s += FRAGSIZE(f); |
| as += FRAGASIZE(f); |
| } |
| assert(s == p->size); |
| assert(as == p->asize); |
| if(p->first) |
| assert(ff==p->last); |
| } |
| #endif |