xref: /plan9/sys/src/libventi/packet.c (revision 9ba92a1a1d8a653f6050241dbdbd039f2ecb1dc2)
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 *
packetalloc(void)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
packetfree(Packet * p)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 *
packetdup(Packet * p,int offset,int n)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 *
packetsplit(Packet * p,int n)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
packetconsume(Packet * p,uchar * buf,int n)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
packettrim(Packet * p,int offset,int n)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 *
packetheader(Packet * p,int n)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 *
packettrailer(Packet * p,int n)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
packetprefix(Packet * p,uchar * buf,int n)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
packetappend(Packet * p,uchar * buf,int n)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
packetconcat(Packet * p,Packet * pp)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 *
packetpeek(Packet * p,uchar * buf,int offset,int n)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
packetcopy(Packet * p,uchar * buf,int offset,int n)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
packetfragments(Packet * p,IOchunk * io,int nio,int offset)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
packetstats(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
packetsize(Packet * p)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
packetasize(Packet * p)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
packetsha1(Packet * p,uchar digest[VtScoreSize])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
packetcmp(Packet * pkt0,Packet * pkt1)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 *
fragalloc(Packet * p,int n,int pos,Frag * next)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*
packetforeign(uchar * buf,int n,void (* free)(void * a),void * a)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 *
fragdup(Packet * p,Frag * f)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
fragfree(Frag * f)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 *
memalloc(int n,int pos)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
memfree(Mem * m)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
memhead(Mem * m,uchar * rp,int n)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
memtail(Mem * m,uchar * wp,int n)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
checkpacket(Packet * p)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
1026