6 typedef struct Mem Mem;
7 typedef struct Frag Frag;
10 BigMemSize = MaxFragSize,
11 SmallMemSize = BigMemSize/8,
15 /* position to carve out of a Mem */
48 Packet *p; /* parent packet, for debugging only */
54 int asize; /* allocated memory - greater than size unless foreign frags */
62 Frag local[NLocalFrag];
65 static Frag *fragalloc(Packet*, int n, int pos, Frag *next);
66 static Frag *fragdup(Packet*, Frag*);
67 static void fragfree(Frag*);
69 static Mem *memalloc(int, int);
70 static void memfree(Mem*);
71 static int memhead(Mem *m, uchar *rp, int n);
72 static int memtail(Mem *m, uchar *wp, int n);
74 static char EPacketSize[] = "bad packet size";
75 static char EPacketOffset[] = "bad packet offset";
76 static char EBadSize[] = "bad size";
79 static void checkpacket(Packet*);
83 * the free list is primarily for speed, but it is
84 * also necessary for packetsplit that packets
85 * are never freed -- a packet can contain a different
86 * packet's local fragments, thanks to packetsplit!
100 #define FRAGSIZE(f) ((f)->wp - (f)->rp)
101 #define FRAGASIZE(f) ((f)->mem ? (f)->mem->ep - (f)->mem->bp : 0)
103 #define NOTFREE(p) assert((p)->size>=0)/*; checkpacket(p)*/
113 freelist.packet = p->next;
116 unlock(&freelist.lk);
119 p = vtbrk(sizeof(Packet));
121 assert(p->size == -1);
127 p->pc = getcallerpc((char*)&p+8); /* might not work, but fine */
134 packetfree(Packet *p)
142 p->pc = getcallerpc(&p);
144 for(f=p->first; f!=nil; f=ff) {
148 p->first = (void*)0xDeadBeef;
149 p->last = (void*)0xDeadBeef;
153 p->next = freelist.packet;
155 unlock(&freelist.lk);
159 packetdup(Packet *p, int offset, int n)
165 if(offset < 0 || n < 0 || offset+n > p->size) {
171 pp->pc = getcallerpc(&p);
180 for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
181 offset -= FRAGSIZE(f);
188 pp->asize += FRAGASIZE(ff);
193 ff->next = fragdup(pp, f);
196 pp->asize += FRAGASIZE(ff);
199 /* fix up last frag: note n <= 0 */
210 packetsplit(Packet *p, int n)
216 if(n < 0 || n > p->size) {
217 werrstr(EPacketSize);
222 pp->pc = getcallerpc(&p);
231 for(f=p->first; n > 0 && n >= FRAGSIZE(f); f=f->next) {
233 p->asize -= FRAGASIZE(f);
234 pp->asize += FRAGASIZE(f);
239 /* split shared frag */
244 pp->asize += FRAGASIZE(ff);
249 pp->first = p->first;
253 if(f == nil || f->next == nil)
261 packetconsume(Packet *p, uchar *buf, int n)
264 if(buf && packetcopy(p, buf, 0, n) < 0)
266 return packettrim(p, n, p->size-n);
270 packettrim(Packet *p, int offset, int n)
275 if(offset < 0 || offset > p->size) {
276 werrstr(EPacketOffset);
280 if(n < 0 || offset + n > p->size) {
281 werrstr(EPacketOffset);
289 for(f=p->first; f != nil; f=ff) {
293 p->first = p->last = nil;
299 /* free before offset */
300 for(f=p->first; offset >= FRAGSIZE(f); f=ff) {
301 p->asize -= FRAGASIZE(f);
302 offset -= FRAGSIZE(f);
312 for(; n > 0 && n > FRAGSIZE(f); f=f->next)
322 for(f=ff; f != nil; f=ff) {
323 p->asize -= FRAGASIZE(f);
332 packetheader(Packet *p, int n)
338 if(n <= 0 || n > MaxFragSize) {
339 werrstr(EPacketSize);
345 /* try and fix in current frag */
349 if(n <= f->rp - m->bp)
350 if(m->ref == 1 || memhead(m, f->rp, n) >= 0) {
357 /* add frag to front */
358 f = fragalloc(p, n, PEnd, p->first);
359 p->asize += FRAGASIZE(f);
368 packettrailer(Packet *p, int n)
374 if(n <= 0 || n > MaxFragSize) {
375 werrstr(EPacketSize);
381 /* try and fix in current frag */
382 if(p->first != nil) {
385 if(n <= m->ep - f->wp)
386 if(m->ref == 1 || memtail(m, f->wp, n) >= 0) {
393 /* add frag to end */
394 f = fragalloc(p, n, (p->first == nil)?PMiddle:PFront, nil);
395 p->asize += FRAGASIZE(f);
406 packetprefix(Packet *p, uchar *buf, int n)
418 /* try and fix in current frag */
425 if(m->ref == 1 || memhead(m, f->rp, nn) >= 0) {
428 memmove(f->rp, buf+n, nn);
436 f = fragalloc(p, nn, PEnd, p->first);
437 p->asize += FRAGASIZE(f);
442 memmove(f->rp, buf+n, nn);
448 packetappend(Packet *p, uchar *buf, int n)
459 /* try and fix in current frag */
460 if(p->first != nil) {
466 if(m->ref == 1 || memtail(m, f->wp, nn) >= 0) {
467 memmove(f->wp, buf, nn);
478 f = fragalloc(p, nn, (p->first == nil)?PMiddle:PFront, nil);
479 p->asize += FRAGASIZE(f);
485 memmove(f->rp, buf, nn);
493 packetconcat(Packet *p, Packet *pp)
502 p->asize += pp->asize;
503 for(f=pp->first; f; f=f->next)
507 p->last->next = pp->first;
509 p->first = pp->first;
521 packetpeek(Packet *p, uchar *buf, int offset, int n)
531 if(offset < 0 || offset >= p->size) {
532 werrstr(EPacketOffset);
536 if(n < 0 || offset + n > p->size) {
537 werrstr(EPacketSize);
541 /* skip up to offset */
542 for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
543 offset -= FRAGSIZE(f);
546 if(offset + n <= FRAGSIZE(f)){
548 return f->rp + offset;
551 for(b=buf; n>0; n -= nn) {
552 nn = FRAGSIZE(f) - offset;
555 memmove(b, f->rp+offset, nn);
566 packetcopy(Packet *p, uchar *buf, int offset, int n)
571 b = packetpeek(p, buf, offset, n);
580 packetfragments(Packet *p, IOchunk *io, int nio, int offset)
587 if(p->size == 0 || nio <= 0)
590 if(offset < 0 || offset > p->size) {
591 werrstr(EPacketOffset);
595 for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
596 offset -= FRAGSIZE(f);
600 for(; f != nil && io < eio; f=f->next) {
601 io->addr = f->rp + offset;
602 io->len = f->wp - (f->rp + offset);
607 for(; io < eio; io++){
621 int np, nf, nsm, nbm;
625 for(p=freelist.packet; p; p=p->next)
628 for(f=freelist.frag; f; f=f->next)
631 for(m=freelist.smallmem; m; m=m->next)
634 for(m=freelist.bigmem; m; m=m->next)
637 fprint(2, "packet: %d/%d frag: %d/%d small mem: %d/%d big mem: %d/%d\n",
638 np, freelist.npacket,
640 nsm, freelist.nsmallmem,
641 nbm, freelist.nbigmem);
643 unlock(&freelist.lk);
648 packetsize(Packet *p)
655 for(f=p->first; f; f=f->next)
658 fprint(2, "packetsize %d %d\n", size, p->size);
659 assert(size == p->size);
665 packetasize(Packet *p)
672 for(f=p->first; f; f=f->next)
673 asize += FRAGASIZE(f);
674 if(asize != p->asize)
675 fprint(2, "packetasize %d %d\n", asize, p->asize);
676 assert(asize == p->asize);
682 packetsha1(Packet *p, uchar digest[VtScoreSize])
689 memset(&ds, 0, sizeof ds);
691 for(f=p->first; f; f=f->next) {
692 sha1(f->rp, FRAGSIZE(f), nil, &ds);
696 sha1(nil, 0, digest, &ds);
700 packetcmp(Packet *pkt0, Packet *pkt1)
711 return (f1 == nil)?0:-1;
719 x = memcmp(f0->wp - n0, f1->wp - n1, n0);
727 } else if (n0 > n1) {
728 x = memcmp(f0->wp - n0, f1->wp - n1, n1);
736 } else { /* n0 == n1 */
737 x = memcmp(f0->wp - n0, f1->wp - n1, n0);
743 return (f1 == nil)?0:-1;
753 fragalloc(Packet *p, int n, int pos, Frag *next)
758 /* look for local frag */
760 ef = &p->local[NLocalFrag];
762 if(f->state == FragLocalFree) {
763 f->state = FragLocalAlloc;
770 freelist.frag = f->next;
773 unlock(&freelist.lk);
776 f = vtbrk(sizeof(Frag));
777 f->state = FragGlobal;
791 if(pos == PEnd && next == nil)
793 m = memalloc(n, pos);
801 packetforeign(uchar *buf, int n, void (*free)(void *a), void *a)
807 p->pc = getcallerpc(&buf);
808 f = fragalloc(p, 0, 0, nil);
823 fragdup(Packet *p, Frag *f)
831 * m->rp && m->wp can be out of date when ref == 1
832 * also, potentially reclaims space from previous frags
834 if(m && m->ref == 1) {
839 ff = fragalloc(p, 0, 0, nil);
846 * We can't duplicate these -- there's no dup function.
848 assert(f->free==nil && f->a==nil);
872 if(f->state == FragLocalAlloc) {
873 f->state = FragLocalFree;
878 f->next = freelist.frag;
880 unlock(&freelist.lk);
884 memalloc(int n, int pos)
889 if(n < 0 || n > MaxFragSize) {
890 werrstr(EPacketSize);
893 if(n <= SmallMemSize) {
895 m = freelist.smallmem;
897 freelist.smallmem = m->next;
899 freelist.nsmallmem++;
900 unlock(&freelist.lk);
906 freelist.bigmem = m->next;
909 unlock(&freelist.lk);
914 m = vtbrk(sizeof(Mem));
928 /* leave a little bit at end */
929 m->rp = m->ep - n - 32;
935 /* check we did not blow it */
939 assert(m->rp >= m->bp && m->wp <= m->ep);
955 /* memset(m->bp, 0xEF, m->ep-m->bp); */
956 switch(m->ep - m->bp) {
961 m->next = freelist.smallmem;
962 freelist.smallmem = m;
963 unlock(&freelist.lk);
967 m->next = freelist.bigmem;
969 unlock(&freelist.lk);
975 memhead(Mem *m, uchar *rp, int n)
977 fprint(2, "memhead called\n");
990 memtail(Mem *m, uchar *wp, int n)
992 fprint(2, "memtail called\n");
1006 checkpacket(Packet *p)
1015 for(f=p->first; f; ff=f,f=f->next){
1020 assert(s == p->size);
1021 assert(as == p->asize);
1023 assert(ff==p->last);