plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

packet.c (15872B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <venti.h>
      4 #include <libsec.h>
      5 
      6 typedef struct Mem Mem;
      7 typedef struct Frag Frag;
      8 
      9 enum {
     10 	BigMemSize = MaxFragSize,
     11 	SmallMemSize = BigMemSize/8,
     12 	NLocalFrag = 2
     13 };
     14 
     15 /* position to carve out of a Mem */
     16 enum {
     17 	PFront,
     18 	PMiddle,
     19 	PEnd
     20 };
     21 
     22 struct Mem
     23 {
     24 	Lock lk;
     25 	int ref;
     26 	uchar *bp;
     27 	uchar *ep;
     28 	uchar *rp;
     29 	uchar *wp;
     30 	Mem *next;
     31 };
     32 
     33 enum {
     34 	FragLocalFree,
     35 	FragLocalAlloc,
     36 	FragGlobal
     37 };
     38 
     39 struct Frag
     40 {
     41 	int state;
     42 	Mem *mem;
     43 	uchar *rp;
     44 	uchar *wp;
     45 	Frag *next;
     46 	void (*free)(void*);
     47 	void *a;
     48 	Packet *p;	/* parent packet, for debugging only */
     49 };
     50 
     51 struct Packet
     52 {
     53 	int size;
     54 	int asize;  /* allocated memory - greater than size unless foreign frags */
     55 	ulong pc;
     56 
     57 	Packet *next;
     58 
     59 	Frag *first;
     60 	Frag *last;
     61 
     62 	Frag local[NLocalFrag];
     63 };
     64 
     65 static Frag *fragalloc(Packet*, int n, int pos, Frag *next);
     66 static Frag *fragdup(Packet*, Frag*);
     67 static void fragfree(Frag*);
     68 
     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);
     73 
     74 static char EPacketSize[] = "bad packet size";
     75 static char EPacketOffset[] = "bad packet offset";
     76 static char EBadSize[] = "bad size";
     77 
     78 #ifdef NOTDEF
     79 static void checkpacket(Packet*);
     80 #endif
     81 
     82 /*
     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!
     87  */
     88 static struct {
     89 	Lock lk;
     90 	Packet *packet;
     91 	int npacket;
     92 	Frag *frag;
     93 	int nfrag;
     94 	Mem *bigmem;
     95 	int nbigmem;
     96 	Mem *smallmem;
     97 	int nsmallmem;
     98 } freelist;
     99 
    100 #define FRAGSIZE(f) ((f)->wp - (f)->rp)
    101 #define FRAGASIZE(f) ((f)->mem ? (f)->mem->ep - (f)->mem->bp : 0)
    102 
    103 #define NOTFREE(p) assert((p)->size>=0)/*; checkpacket(p)*/
    104 
    105 Packet *
    106 packetalloc(void)
    107 {
    108 	Packet *p;
    109 
    110 	lock(&freelist.lk);
    111 	p = freelist.packet;
    112 	if(p != nil)
    113 		freelist.packet = p->next;
    114 	else
    115 		freelist.npacket++;
    116 	unlock(&freelist.lk);
    117 
    118 	if(p == nil)
    119 		p = vtbrk(sizeof(Packet));
    120 	else
    121 		assert(p->size == -1);
    122 	p->size = 0;
    123 	p->asize = 0;
    124 	p->first = nil;
    125 	p->last = nil;
    126 	p->next = nil;
    127 	p->pc = getcallerpc((char*)&p+8);	/* might not work, but fine */
    128 
    129 	NOTFREE(p);
    130 	return p;
    131 }
    132 
    133 void
    134 packetfree(Packet *p)
    135 {
    136 	Frag *f, *ff;
    137 
    138 	if(p == nil)
    139 		return;
    140 
    141 	NOTFREE(p);
    142 	p->pc = getcallerpc(&p);
    143 
    144 	for(f=p->first; f!=nil; f=ff) {
    145 		ff = f->next;
    146 		fragfree(f);
    147 	}
    148 	p->first = (void*)0xDeadBeef;
    149 	p->last = (void*)0xDeadBeef;
    150 	p->size = -1;
    151 
    152 	lock(&freelist.lk);
    153 	p->next = freelist.packet;
    154 	freelist.packet = p;
    155 	unlock(&freelist.lk);
    156 }
    157 
    158 Packet *
    159 packetdup(Packet *p, int offset, int n)
    160 {
    161 	Frag *f, *ff;
    162 	Packet *pp;
    163 
    164 	NOTFREE(p);
    165 	if(offset < 0 || n < 0 || offset+n > p->size) {
    166 		werrstr(EBadSize);
    167 		return nil;
    168 	}
    169 
    170 	pp = packetalloc();
    171 	pp->pc = getcallerpc(&p);
    172 	if(n == 0){
    173 		NOTFREE(pp);
    174 		return pp;
    175 	}
    176 
    177 	pp->size = n;
    178 
    179 	/* skip offset */
    180 	for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
    181 		offset -= FRAGSIZE(f);
    182 
    183 	/* first frag */
    184 	ff = fragdup(pp, f);
    185 	ff->rp += offset;
    186 	pp->first = ff;
    187 	n -= FRAGSIZE(ff);
    188 	pp->asize += FRAGASIZE(ff);
    189 
    190 	/* the remaining */
    191 	while(n > 0) {
    192 		f = f->next;
    193 		ff->next = fragdup(pp, f);
    194 		ff = ff->next;
    195 		n -= FRAGSIZE(ff);
    196 		pp->asize += FRAGASIZE(ff);
    197 	}
    198 
    199 	/* fix up last frag: note n <= 0 */
    200 	ff->wp += n;
    201 	ff->next = nil;
    202 	pp->last = ff;
    203 
    204 	NOTFREE(pp);
    205 	NOTFREE(p);
    206 	return pp;
    207 }
    208 
    209 Packet *
    210 packetsplit(Packet *p, int n)
    211 {
    212 	Packet *pp;
    213 	Frag *f, *ff;
    214 
    215 	NOTFREE(p);
    216 	if(n < 0 || n > p->size) {
    217 		werrstr(EPacketSize);
    218 		return nil;
    219 	}
    220 
    221 	pp = packetalloc();
    222 	pp->pc = getcallerpc(&p);
    223 	if(n == 0){
    224 		NOTFREE(pp);
    225 		return pp;
    226 	}
    227 
    228 	pp->size = n;
    229 	p->size -= n;
    230 	ff = nil;
    231 	for(f=p->first; n > 0 && n >= FRAGSIZE(f); f=f->next) {
    232 		n -= FRAGSIZE(f);
    233 		p->asize -= FRAGASIZE(f);
    234 		pp->asize += FRAGASIZE(f);
    235 		f->p = pp;
    236 		ff = f;
    237 	}
    238 
    239 	/* split shared frag */
    240 	if(n > 0) {
    241 		f->p = pp;
    242 		ff = f;
    243 		f = fragdup(p, ff);
    244 		pp->asize += FRAGASIZE(ff);
    245 		ff->wp = ff->rp + n;
    246 		f->rp += n;
    247 	}
    248 
    249 	pp->first = p->first;
    250 	pp->last = ff;
    251 	ff->next = nil;
    252 	p->first = f;
    253 	if(f == nil || f->next == nil)
    254 		p->last = f;
    255 	NOTFREE(pp);
    256 	NOTFREE(p);
    257 	return pp;
    258 }
    259 
    260 int
    261 packetconsume(Packet *p, uchar *buf, int n)
    262 {
    263 	NOTFREE(p);
    264 	if(buf && packetcopy(p, buf, 0, n) < 0)
    265 		return -1;
    266 	return packettrim(p, n, p->size-n);
    267 }
    268 
    269 int
    270 packettrim(Packet *p, int offset, int n)
    271 {
    272 	Frag *f, *ff;
    273 
    274 	NOTFREE(p);
    275 	if(offset < 0 || offset > p->size) {
    276 		werrstr(EPacketOffset);
    277 		return -1;
    278 	}
    279 
    280 	if(n < 0 || offset + n > p->size) {
    281 		werrstr(EPacketOffset);
    282 		return -1;
    283 	}
    284 
    285 	p->size = n;
    286 
    287 	/* easy case */
    288 	if(n == 0) {
    289 		for(f=p->first; f != nil; f=ff) {
    290 			ff = f->next;
    291 			fragfree(f);
    292 		}
    293 		p->first = p->last = nil;
    294 		p->asize = 0;
    295 		NOTFREE(p);
    296 		return 0;
    297 	}
    298 
    299 	/* free before offset */
    300 	for(f=p->first; offset >= FRAGSIZE(f); f=ff) {
    301 		p->asize -= FRAGASIZE(f);
    302 		offset -= FRAGSIZE(f);
    303 		ff = f->next;
    304 		fragfree(f);
    305 	}
    306 
    307 	/* adjust frag */
    308 	f->rp += offset;
    309 	p->first = f;
    310 
    311 	/* skip middle */
    312 	for(; n > 0 && n > FRAGSIZE(f); f=f->next)
    313 		n -= FRAGSIZE(f);
    314 
    315 	/* adjust end */
    316 	f->wp = f->rp + n;
    317 	p->last = f;
    318 	ff = f->next;
    319 	f->next = nil;
    320 
    321 	/* free after */
    322 	for(f=ff; f != nil; f=ff) {
    323 		p->asize -= FRAGASIZE(f);
    324 		ff = f->next;
    325 		fragfree(f);
    326 	}
    327 	NOTFREE(p);
    328 	return 0;
    329 }
    330 
    331 uchar *
    332 packetheader(Packet *p, int n)
    333 {
    334 	Frag *f;
    335 	Mem *m;
    336 
    337 	NOTFREE(p);
    338 	if(n <= 0 || n > MaxFragSize) {
    339 		werrstr(EPacketSize);
    340 		return nil;
    341 	}
    342 
    343 	p->size += n;
    344 
    345 	/* try and fix in current frag */
    346 	f = p->first;
    347 	if(f != nil) {
    348 		m = f->mem;
    349 		if(n <= f->rp - m->bp)
    350 		if(m->ref == 1 || memhead(m, f->rp, n) >= 0) {
    351 			f->rp -= n;
    352 			NOTFREE(p);
    353 			return f->rp;
    354 		}
    355 	}
    356 
    357 	/* add frag to front */
    358 	f = fragalloc(p, n, PEnd, p->first);
    359 	p->asize += FRAGASIZE(f);
    360 	if(p->first == nil)
    361 		p->last = f;
    362 	p->first = f;
    363 	NOTFREE(p);
    364 	return f->rp;
    365 }
    366 
    367 uchar *
    368 packettrailer(Packet *p, int n)
    369 {
    370 	Mem *m;
    371 	Frag *f;
    372 
    373 	NOTFREE(p);
    374 	if(n <= 0 || n > MaxFragSize) {
    375 		werrstr(EPacketSize);
    376 		return nil;
    377 	}
    378 
    379 	p->size += n;
    380 
    381 	/* try and fix in current frag */
    382 	if(p->first != nil) {
    383 		f = p->last;
    384 		m = f->mem;
    385 		if(n <= m->ep - f->wp)
    386 		if(m->ref == 1 || memtail(m, f->wp, n) >= 0) {
    387 			f->wp += n;
    388 			NOTFREE(p);
    389 			return f->wp - n;
    390 		}
    391 	}
    392 
    393 	/* add frag to end */
    394 	f = fragalloc(p, n, (p->first == nil)?PMiddle:PFront, nil);
    395 	p->asize += FRAGASIZE(f);
    396 	if(p->first == nil)
    397 		p->first = f;
    398 	else
    399 		p->last->next = f;
    400 	p->last = f;
    401 	NOTFREE(p);
    402 	return f->rp;
    403 }
    404 
    405 void
    406 packetprefix(Packet *p, uchar *buf, int n)
    407 {
    408 	Frag *f;
    409 	int nn;
    410 	Mem *m;
    411 
    412 	NOTFREE(p);
    413 	if(n <= 0)
    414 		return;
    415 
    416 	p->size += n;
    417 
    418 	/* try and fix in current frag */
    419 	f = p->first;
    420 	if(f != nil) {
    421 		m = f->mem;
    422 		nn = f->rp - m->bp;
    423 		if(nn > n)
    424 			nn = n;
    425 		if(m->ref == 1 || memhead(m, f->rp, nn) >= 0) {
    426 			f->rp -= nn;
    427 			n -= nn;
    428 			memmove(f->rp, buf+n, nn);
    429 		}
    430 	}
    431 
    432 	while(n > 0) {
    433 		nn = n;
    434 		if(nn > MaxFragSize)
    435 			nn = MaxFragSize;
    436 		f = fragalloc(p, nn, PEnd, p->first);
    437 		p->asize += FRAGASIZE(f);
    438 		if(p->first == nil)
    439 			p->last = f;
    440 		p->first = f;
    441 		n -= nn;
    442 		memmove(f->rp, buf+n, nn);
    443 	}
    444 	NOTFREE(p);
    445 }
    446 
    447 void
    448 packetappend(Packet *p, uchar *buf, int n)
    449 {
    450 	Frag *f;
    451 	int nn;
    452 	Mem *m;
    453 
    454 	NOTFREE(p);
    455 	if(n <= 0)
    456 		return;
    457 
    458 	p->size += n;
    459 	/* try and fix in current frag */
    460 	if(p->first != nil) {
    461 		f = p->last;
    462 		m = f->mem;
    463 		nn = m->ep - f->wp;
    464 		if(nn > n)
    465 			nn = n;
    466 		if(m->ref == 1 || memtail(m, f->wp, nn) >= 0) {
    467 			memmove(f->wp, buf, nn);
    468 			f->wp += nn;
    469 			buf += nn;
    470 			n -= nn;
    471 		}
    472 	}
    473 
    474 	while(n > 0) {
    475 		nn = n;
    476 		if(nn > MaxFragSize)
    477 			nn = MaxFragSize;
    478 		f = fragalloc(p, nn, (p->first == nil)?PMiddle:PFront, nil);
    479 		p->asize += FRAGASIZE(f);
    480 		if(p->first == nil)
    481 			p->first = f;
    482 		else
    483 			p->last->next = f;
    484 		p->last = f;
    485 		memmove(f->rp, buf, nn);
    486 		buf += nn;
    487 		n -= nn;
    488 	}
    489 	NOTFREE(p);
    490 }
    491 
    492 void
    493 packetconcat(Packet *p, Packet *pp)
    494 {
    495 	Frag *f;
    496 
    497 	NOTFREE(p);
    498 	NOTFREE(pp);
    499 	if(pp->size == 0)
    500 		return;
    501 	p->size += pp->size;
    502 	p->asize += pp->asize;
    503 	for(f=pp->first; f; f=f->next)
    504 		f->p = p;
    505 
    506 	if(p->first != nil)
    507 		p->last->next = pp->first;
    508 	else
    509 		p->first = pp->first;
    510 
    511 	p->last = pp->last;
    512 	pp->size = 0;
    513 	pp->asize = 0;
    514 	pp->first = nil;
    515 	pp->last = nil;
    516 	NOTFREE(p);
    517 	NOTFREE(pp);
    518 }
    519 
    520 uchar *
    521 packetpeek(Packet *p, uchar *buf, int offset, int n)
    522 {
    523 	Frag *f;
    524 	int nn;
    525 	uchar *b;
    526 
    527 	NOTFREE(p);
    528 	if(n == 0)
    529 		return buf;
    530 
    531 	if(offset < 0 || offset >= p->size) {
    532 		werrstr(EPacketOffset);
    533 		return nil;
    534 	}
    535 
    536 	if(n < 0 || offset + n > p->size) {
    537 		werrstr(EPacketSize);
    538 		return nil;
    539 	}
    540 
    541 	/* skip up to offset */
    542 	for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
    543 		offset -= FRAGSIZE(f);
    544 
    545 	/* easy case */
    546 	if(offset + n <= FRAGSIZE(f)){
    547 		NOTFREE(p);
    548 		return f->rp + offset;
    549 	}
    550 
    551 	for(b=buf; n>0; n -= nn) {
    552 		nn = FRAGSIZE(f) - offset;
    553 		if(nn > n)
    554 			nn = n;
    555 		memmove(b, f->rp+offset, nn);
    556 		offset = 0;
    557 		f = f->next;
    558 		b += nn;
    559 	}
    560 
    561 	NOTFREE(p);
    562 	return buf;
    563 }
    564 
    565 int
    566 packetcopy(Packet *p, uchar *buf, int offset, int n)
    567 {
    568 	uchar *b;
    569 
    570 	NOTFREE(p);
    571 	b = packetpeek(p, buf, offset, n);
    572 	if(b == nil)
    573 		return -1;
    574 	if(b != buf)
    575 		memmove(buf, b, n);
    576 	return 0;
    577 }
    578 
    579 int
    580 packetfragments(Packet *p, IOchunk *io, int nio, int offset)
    581 {
    582 	Frag *f;
    583 	int size;
    584 	IOchunk *eio;
    585 
    586 	NOTFREE(p);
    587 	if(p->size == 0 || nio <= 0)
    588 		return 0;
    589 
    590 	if(offset < 0 || offset > p->size) {
    591 		werrstr(EPacketOffset);
    592 		return -1;
    593 	}
    594 
    595 	for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
    596 		offset -= FRAGSIZE(f);
    597 
    598 	size = 0;
    599 	eio = io + nio;
    600 	for(; f != nil && io < eio; f=f->next) {
    601 		io->addr = f->rp + offset;
    602 		io->len = f->wp - (f->rp + offset);
    603 		offset = 0;
    604 		size += io->len;
    605 		io++;
    606 	}
    607 	for(; io < eio; io++){
    608 		io->addr = nil;
    609 		io->len = 0;
    610 	}
    611 	return size;
    612 }
    613 
    614 void
    615 packetstats(void)
    616 {
    617 	Packet *p;
    618 	Frag *f;
    619 	Mem *m;
    620 
    621 	int np, nf, nsm, nbm;
    622 
    623 	lock(&freelist.lk);
    624 	np = 0;
    625 	for(p=freelist.packet; p; p=p->next)
    626 		np++;
    627 	nf = 0;
    628 	for(f=freelist.frag; f; f=f->next)
    629 		nf++;
    630 	nsm = 0;
    631 	for(m=freelist.smallmem; m; m=m->next)
    632 		nsm++;
    633 	nbm = 0;
    634 	for(m=freelist.bigmem; m; m=m->next)
    635 		nbm++;
    636 
    637 	fprint(2, "packet: %d/%d frag: %d/%d small mem: %d/%d big mem: %d/%d\n",
    638 		np, freelist.npacket,
    639 		nf, freelist.nfrag,
    640 		nsm, freelist.nsmallmem,
    641 		nbm, freelist.nbigmem);
    642 
    643 	unlock(&freelist.lk);
    644 }
    645 
    646 
    647 uint
    648 packetsize(Packet *p)
    649 {
    650 	NOTFREE(p);
    651 	if(1) {
    652 		Frag *f;
    653 		int size = 0;
    654 
    655 		for(f=p->first; f; f=f->next)
    656 			size += FRAGSIZE(f);
    657 		if(size != p->size)
    658 			fprint(2, "packetsize %d %d\n", size, p->size);
    659 		assert(size == p->size);
    660 	}
    661 	return p->size;
    662 }
    663 
    664 uint
    665 packetasize(Packet *p)
    666 {
    667 	NOTFREE(p);
    668 	if(0) {
    669 		Frag *f;
    670 		int asize = 0;
    671 
    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);
    677 	}
    678 	return p->asize;
    679 }
    680 
    681 void
    682 packetsha1(Packet *p, uchar digest[VtScoreSize])
    683 {
    684 	DigestState ds;
    685 	Frag *f;
    686 	int size;
    687 
    688 	NOTFREE(p);
    689 	memset(&ds, 0, sizeof ds);
    690 	size = p->size;
    691 	for(f=p->first; f; f=f->next) {
    692 		sha1(f->rp, FRAGSIZE(f), nil, &ds);
    693 		size -= FRAGSIZE(f);
    694 	}
    695 	assert(size == 0);
    696 	sha1(nil, 0, digest, &ds);
    697 }
    698 
    699 int
    700 packetcmp(Packet *pkt0, Packet *pkt1)
    701 {
    702 	Frag *f0, *f1;
    703 	int n0, n1, x;
    704 
    705 	NOTFREE(pkt0);
    706 	NOTFREE(pkt1);
    707 	f0 = pkt0->first;
    708 	f1 = pkt1->first;
    709 
    710 	if(f0 == nil)
    711 		return (f1 == nil)?0:-1;
    712 	if(f1 == nil)
    713 		return 1;
    714 	n0 = FRAGSIZE(f0);
    715 	n1 = FRAGSIZE(f1);
    716 
    717 	for(;;) {
    718 		if(n0 < n1) {
    719 			x = memcmp(f0->wp - n0, f1->wp - n1, n0);
    720 			if(x != 0)
    721 				return x;
    722 			n1 -= n0;
    723 			f0 = f0->next;
    724 			if(f0 == nil)
    725 				return -1;
    726 			n0 = FRAGSIZE(f0);
    727 		} else if (n0 > n1) {
    728 			x = memcmp(f0->wp - n0, f1->wp - n1, n1);
    729 			if(x != 0)
    730 				return x;
    731 			n0 -= n1;
    732 			f1 = f1->next;
    733 			if(f1 == nil)
    734 				return 1;
    735 			n1 = FRAGSIZE(f1);
    736 		} else { /* n0 == n1 */
    737 			x = memcmp(f0->wp - n0, f1->wp - n1, n0);
    738 			if(x != 0)
    739 				return x;
    740 			f0 = f0->next;
    741 			f1 = f1->next;
    742 			if(f0 == nil)
    743 				return (f1 == nil)?0:-1;
    744 			if(f1 == nil)
    745 				return 1;
    746 			n0 = FRAGSIZE(f0);
    747 			n1 = FRAGSIZE(f1);
    748 		}
    749 	}
    750 }
    751 
    752 static Frag *
    753 fragalloc(Packet *p, int n, int pos, Frag *next)
    754 {
    755 	Frag *f, *ef;
    756 	Mem *m;
    757 
    758 	/* look for local frag */
    759 	f = &p->local[0];
    760 	ef = &p->local[NLocalFrag];
    761 	for(;f<ef; f++) {
    762 		if(f->state == FragLocalFree) {
    763 			f->state = FragLocalAlloc;
    764 			goto Found;
    765 		}
    766 	}
    767 	lock(&freelist.lk);
    768 	f = freelist.frag;
    769 	if(f != nil)
    770 		freelist.frag = f->next;
    771 	else
    772 		freelist.nfrag++;
    773 	unlock(&freelist.lk);
    774 
    775 	if(f == nil) {
    776 		f = vtbrk(sizeof(Frag));
    777 		f->state = FragGlobal;
    778 	}
    779 
    780 Found:
    781 	f->next = next;
    782 	f->p = p;
    783 
    784 	if(n == 0){
    785 		f->mem = 0;
    786 		f->rp = 0;
    787 		f->wp = 0;
    788 		return f;
    789 	}
    790 
    791 	if(pos == PEnd && next == nil)
    792 		pos = PMiddle;
    793 	m = memalloc(n, pos);
    794 	f->mem = m;
    795 	f->rp = m->rp;
    796 	f->wp = m->wp;
    797 	return f;
    798 }
    799 
    800 Packet*
    801 packetforeign(uchar *buf, int n, void (*free)(void *a), void *a)
    802 {
    803 	Packet *p;
    804 	Frag *f;
    805 
    806 	p = packetalloc();
    807 	p->pc = getcallerpc(&buf);
    808 	f = fragalloc(p, 0, 0, nil);
    809 	f->free = free;
    810 	f->a = a;
    811 	f->next = nil;
    812 	f->rp = buf;
    813 	f->wp = buf+n;
    814 
    815 	p->first = f;
    816 	p->last = f;
    817 	p->size = n;
    818 	NOTFREE(p);
    819 	return p;
    820 }
    821 
    822 static Frag *
    823 fragdup(Packet *p, Frag *f)
    824 {
    825 	Frag *ff;
    826 	Mem *m;
    827 
    828 	m = f->mem;
    829 
    830 	/*
    831 	 * m->rp && m->wp can be out of date when ref == 1
    832 	 * also, potentially reclaims space from previous frags
    833 	 */
    834 	if(m && m->ref == 1) {
    835 		m->rp = f->rp;
    836 		m->wp = f->wp;
    837 	}
    838 
    839 	ff = fragalloc(p, 0, 0, nil);
    840 	ff->mem = f->mem;
    841 	ff->rp = f->rp;
    842 	ff->wp = f->wp;
    843 	ff->next = f->next;
    844 
    845 	/*
    846 	 * We can't duplicate these -- there's no dup function.
    847 	 */
    848 	assert(f->free==nil && f->a==nil);
    849 
    850 	if(m){
    851 		lock(&m->lk);
    852 		m->ref++;
    853 		unlock(&m->lk);
    854 	}
    855 
    856 
    857 	return ff;
    858 }
    859 
    860 
    861 static void
    862 fragfree(Frag *f)
    863 {
    864 	if(f->mem == nil){
    865 		if(f->free)
    866 			(*f->free)(f->a);
    867 	}else{
    868 		memfree(f->mem);
    869 		f->mem = 0;
    870 	}
    871 
    872 	if(f->state == FragLocalAlloc) {
    873 		f->state = FragLocalFree;
    874 		return;
    875 	}
    876 
    877 	lock(&freelist.lk);
    878 	f->next = freelist.frag;
    879 	freelist.frag = f;
    880 	unlock(&freelist.lk);
    881 }
    882 
    883 static Mem *
    884 memalloc(int n, int pos)
    885 {
    886 	Mem *m;
    887 	int nn;
    888 
    889 	if(n < 0 || n > MaxFragSize) {
    890 		werrstr(EPacketSize);
    891 		return nil;
    892 	}
    893 	if(n <= SmallMemSize) {
    894 		lock(&freelist.lk);
    895 		m = freelist.smallmem;
    896 		if(m != nil)
    897 			freelist.smallmem = m->next;
    898 		else
    899 			freelist.nsmallmem++;
    900 		unlock(&freelist.lk);
    901 		nn = SmallMemSize;
    902 	} else {
    903 		lock(&freelist.lk);
    904 		m = freelist.bigmem;
    905 		if(m != nil)
    906 			freelist.bigmem = m->next;
    907 		else
    908 			freelist.nbigmem++;
    909 		unlock(&freelist.lk);
    910 		nn = BigMemSize;
    911 	}
    912 
    913 	if(m == nil) {
    914 		m = vtbrk(sizeof(Mem));
    915 		m->bp = vtbrk(nn);
    916 		m->ep = m->bp + nn;
    917 	}
    918 	assert(m->ref == 0);
    919 	m->ref = 1;
    920 
    921 	switch(pos) {
    922 	default:
    923 		assert(0);
    924 	case PFront:
    925 		m->rp = m->bp;
    926 		break;
    927 	case PMiddle:
    928 		/* leave a little bit at end */
    929 		m->rp = m->ep - n - 32;
    930 		break;
    931 	case PEnd:
    932 		m->rp = m->ep - n;
    933 		break;
    934 	}
    935 	/* check we did not blow it */
    936 	if(m->rp < m->bp)
    937 		m->rp = m->bp;
    938 	m->wp = m->rp + n;
    939 	assert(m->rp >= m->bp && m->wp <= m->ep);
    940 	return m;
    941 }
    942 
    943 static void
    944 memfree(Mem *m)
    945 {
    946 	lock(&m->lk);
    947 	m->ref--;
    948 	if(m->ref > 0) {
    949 		unlock(&m->lk);
    950 		return;
    951 	}
    952 	unlock(&m->lk);
    953 	assert(m->ref == 0);
    954 
    955 /*	memset(m->bp, 0xEF, m->ep-m->bp); */
    956 	switch(m->ep - m->bp) {
    957 	default:
    958 		assert(0);
    959 	case SmallMemSize:
    960 		lock(&freelist.lk);
    961 		m->next = freelist.smallmem;
    962 		freelist.smallmem = m;
    963 		unlock(&freelist.lk);
    964 		break;
    965 	case BigMemSize:
    966 		lock(&freelist.lk);
    967 		m->next = freelist.bigmem;
    968 		freelist.bigmem = m;
    969 		unlock(&freelist.lk);
    970 		break;
    971 	}
    972 }
    973 
    974 static int
    975 memhead(Mem *m, uchar *rp, int n)
    976 {
    977 	fprint(2, "memhead called\n");
    978 	abort();
    979 	lock(&m->lk);
    980 	if(m->rp != rp) {
    981 		unlock(&m->lk);
    982 		return -1;
    983 	}
    984 	m->rp -= n;
    985 	unlock(&m->lk);
    986 	return 0;
    987 }
    988 
    989 static int
    990 memtail(Mem *m, uchar *wp, int n)
    991 {
    992 	fprint(2, "memtail called\n");
    993 	abort();
    994 	lock(&m->lk);
    995 	if(m->wp != wp) {
    996 		unlock(&m->lk);
    997 		return -1;
    998 	}
    999 	m->wp += n;
   1000 	unlock(&m->lk);
   1001 	return 0;
   1002 }
   1003 
   1004 #ifdef NOTDEF
   1005 static void
   1006 checkpacket(Packet *p)
   1007 {
   1008 	int s, as;
   1009 	Frag *f;
   1010 	Frag *ff;
   1011 
   1012 	s = 0;
   1013 	as = 0;
   1014 	ff=p->first;
   1015 	for(f=p->first; f; ff=f,f=f->next){
   1016 		assert(f->p == p);
   1017 		s += FRAGSIZE(f);
   1018 		as += FRAGASIZE(f);
   1019 	}
   1020 	assert(s == p->size);
   1021 	assert(as == p->asize);
   1022 	if(p->first)
   1023 		assert(ff==p->last);
   1024 }
   1025 #endif