xref: /plan9/sys/src/liboventi/packet.c (revision 368c31ab13393dea083228fdd1c3445076f83a4b)
1*368c31abSDavid du Colombier #include <u.h>
2*368c31abSDavid du Colombier #include <libc.h>
3*368c31abSDavid du Colombier #include <oventi.h>
4*368c31abSDavid du Colombier #include "packet.h"
5*368c31abSDavid du Colombier 
6*368c31abSDavid du Colombier static Frag *fragAlloc(Packet*, int n, int pos, Frag *next);
7*368c31abSDavid du Colombier static Frag *fragDup(Packet*, Frag*);
8*368c31abSDavid du Colombier static void fragFree(Frag*);
9*368c31abSDavid du Colombier 
10*368c31abSDavid du Colombier static Mem *memAlloc(int, int);
11*368c31abSDavid du Colombier static void memFree(Mem*);
12*368c31abSDavid du Colombier static int memHead(Mem *m, uchar *rp, int n);
13*368c31abSDavid du Colombier static int memTail(Mem *m, uchar *wp, int n);
14*368c31abSDavid du Colombier 
15*368c31abSDavid du Colombier static char EPacketSize[] = "bad packet size";
16*368c31abSDavid du Colombier static char EPacketOffset[] = "bad packet offset";
17*368c31abSDavid du Colombier static char EBadSize[] = "bad size";
18*368c31abSDavid du Colombier 
19*368c31abSDavid du Colombier static struct {
20*368c31abSDavid du Colombier 	Lock lk;
21*368c31abSDavid du Colombier 	Packet *packet;
22*368c31abSDavid du Colombier 	int npacket;
23*368c31abSDavid du Colombier 	Frag *frag;
24*368c31abSDavid du Colombier 	int nfrag;
25*368c31abSDavid du Colombier 	Mem *bigMem;
26*368c31abSDavid du Colombier 	int nbigMem;
27*368c31abSDavid du Colombier 	Mem *smallMem;
28*368c31abSDavid du Colombier 	int nsmallMem;
29*368c31abSDavid du Colombier } freeList;
30*368c31abSDavid du Colombier 
31*368c31abSDavid du Colombier #define FRAGSIZE(f) ((f)->wp - (f)->rp)
32*368c31abSDavid du Colombier #define FRAGASIZE(f) ((f)->mem->ep - (f)->mem->bp)
33*368c31abSDavid du Colombier 
34*368c31abSDavid du Colombier #define NOTFREE(p) assert((p)->size>=0)
35*368c31abSDavid du Colombier 
36*368c31abSDavid du Colombier Packet *
packetAlloc(void)37*368c31abSDavid du Colombier packetAlloc(void)
38*368c31abSDavid du Colombier {
39*368c31abSDavid du Colombier 	Packet *p;
40*368c31abSDavid du Colombier 
41*368c31abSDavid du Colombier 	lock(&freeList.lk);
42*368c31abSDavid du Colombier 	p = freeList.packet;
43*368c31abSDavid du Colombier 	if(p != nil)
44*368c31abSDavid du Colombier 		freeList.packet = p->next;
45*368c31abSDavid du Colombier 	else
46*368c31abSDavid du Colombier 		freeList.npacket++;
47*368c31abSDavid du Colombier 	unlock(&freeList.lk);
48*368c31abSDavid du Colombier 
49*368c31abSDavid du Colombier 	if(p == nil)
50*368c31abSDavid du Colombier 		p = vtMemBrk(sizeof(Packet));
51*368c31abSDavid du Colombier 	else
52*368c31abSDavid du Colombier 		assert(p->size == -1);
53*368c31abSDavid du Colombier 	p->size = 0;
54*368c31abSDavid du Colombier 	p->asize = 0;
55*368c31abSDavid du Colombier 	p->first = nil;
56*368c31abSDavid du Colombier 	p->last = nil;
57*368c31abSDavid du Colombier 	p->next = nil;
58*368c31abSDavid du Colombier 
59*368c31abSDavid du Colombier 	return p;
60*368c31abSDavid du Colombier }
61*368c31abSDavid du Colombier 
62*368c31abSDavid du Colombier void
packetFree(Packet * p)63*368c31abSDavid du Colombier packetFree(Packet *p)
64*368c31abSDavid du Colombier {
65*368c31abSDavid du Colombier 	Frag *f, *ff;
66*368c31abSDavid du Colombier 
67*368c31abSDavid du Colombier if(0)fprint(2, "packetFree %p\n", p);
68*368c31abSDavid du Colombier 
69*368c31abSDavid du Colombier 	NOTFREE(p);
70*368c31abSDavid du Colombier 	p->size = -1;
71*368c31abSDavid du Colombier 
72*368c31abSDavid du Colombier 	for(f=p->first; f!=nil; f=ff) {
73*368c31abSDavid du Colombier 		ff = f->next;
74*368c31abSDavid du Colombier 		fragFree(f);
75*368c31abSDavid du Colombier 	}
76*368c31abSDavid du Colombier 	p->first = nil;
77*368c31abSDavid du Colombier 	p->last = nil;
78*368c31abSDavid du Colombier 
79*368c31abSDavid du Colombier 	lock(&freeList.lk);
80*368c31abSDavid du Colombier 	p->next = freeList.packet;
81*368c31abSDavid du Colombier 	freeList.packet = p;
82*368c31abSDavid du Colombier 	unlock(&freeList.lk);
83*368c31abSDavid du Colombier }
84*368c31abSDavid du Colombier 
85*368c31abSDavid du Colombier Packet *
packetDup(Packet * p,int offset,int n)86*368c31abSDavid du Colombier packetDup(Packet *p, int offset, int n)
87*368c31abSDavid du Colombier {
88*368c31abSDavid du Colombier 	Frag *f, *ff;
89*368c31abSDavid du Colombier 	Packet *pp;
90*368c31abSDavid du Colombier 
91*368c31abSDavid du Colombier 	NOTFREE(p);
92*368c31abSDavid du Colombier 	if(offset < 0 || n < 0 || offset+n > p->size) {
93*368c31abSDavid du Colombier 		vtSetError(EBadSize);
94*368c31abSDavid du Colombier 		return nil;
95*368c31abSDavid du Colombier 	}
96*368c31abSDavid du Colombier 
97*368c31abSDavid du Colombier 	pp = packetAlloc();
98*368c31abSDavid du Colombier 	if(n == 0)
99*368c31abSDavid du Colombier 		return pp;
100*368c31abSDavid du Colombier 
101*368c31abSDavid du Colombier 	pp->size = n;
102*368c31abSDavid du Colombier 
103*368c31abSDavid du Colombier 	/* skip offset */
104*368c31abSDavid du Colombier 	for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
105*368c31abSDavid du Colombier 		offset -= FRAGSIZE(f);
106*368c31abSDavid du Colombier 
107*368c31abSDavid du Colombier 	/* first frag */
108*368c31abSDavid du Colombier 	ff = fragDup(pp, f);
109*368c31abSDavid du Colombier 	ff->rp += offset;
110*368c31abSDavid du Colombier 	pp->first = ff;
111*368c31abSDavid du Colombier 	n -= FRAGSIZE(ff);
112*368c31abSDavid du Colombier 	pp->asize += FRAGASIZE(ff);
113*368c31abSDavid du Colombier 
114*368c31abSDavid du Colombier 	/* the remaining */
115*368c31abSDavid du Colombier 	while(n > 0) {
116*368c31abSDavid du Colombier 		f = f->next;
117*368c31abSDavid du Colombier 		ff->next = fragDup(pp, f);
118*368c31abSDavid du Colombier 		ff = ff->next;
119*368c31abSDavid du Colombier 		n -= FRAGSIZE(ff);
120*368c31abSDavid du Colombier 		pp->asize += FRAGASIZE(ff);
121*368c31abSDavid du Colombier 	}
122*368c31abSDavid du Colombier 
123*368c31abSDavid du Colombier 	/* fix up last frag: note n <= 0 */
124*368c31abSDavid du Colombier 	ff->wp += n;
125*368c31abSDavid du Colombier 	ff->next = nil;
126*368c31abSDavid du Colombier 	pp->last = ff;
127*368c31abSDavid du Colombier 
128*368c31abSDavid du Colombier 	return pp;
129*368c31abSDavid du Colombier }
130*368c31abSDavid du Colombier 
131*368c31abSDavid du Colombier Packet *
packetSplit(Packet * p,int n)132*368c31abSDavid du Colombier packetSplit(Packet *p, int n)
133*368c31abSDavid du Colombier {
134*368c31abSDavid du Colombier 	Packet *pp;
135*368c31abSDavid du Colombier 	Frag *f, *ff;
136*368c31abSDavid du Colombier 
137*368c31abSDavid du Colombier 	NOTFREE(p);
138*368c31abSDavid du Colombier 	if(n < 0 || n > p->size) {
139*368c31abSDavid du Colombier 		vtSetError(EPacketSize);
140*368c31abSDavid du Colombier 		return nil;
141*368c31abSDavid du Colombier 	}
142*368c31abSDavid du Colombier 
143*368c31abSDavid du Colombier 	pp = packetAlloc();
144*368c31abSDavid du Colombier 	if(n == 0)
145*368c31abSDavid du Colombier 		return pp;
146*368c31abSDavid du Colombier 
147*368c31abSDavid du Colombier 	pp->size = n;
148*368c31abSDavid du Colombier 	p->size -= n;
149*368c31abSDavid du Colombier 	ff = nil;
150*368c31abSDavid du Colombier 	for(f=p->first; n > 0 && n >= FRAGSIZE(f); f=f->next) {
151*368c31abSDavid du Colombier 		n -= FRAGSIZE(f);
152*368c31abSDavid du Colombier 		p->asize -= FRAGASIZE(f);
153*368c31abSDavid du Colombier 		pp->asize += FRAGASIZE(f);
154*368c31abSDavid du Colombier 		ff = f;
155*368c31abSDavid du Colombier 	}
156*368c31abSDavid du Colombier 
157*368c31abSDavid du Colombier 	/* split shared frag */
158*368c31abSDavid du Colombier 	if(n > 0) {
159*368c31abSDavid du Colombier 		ff = f;
160*368c31abSDavid du Colombier 		f = fragDup(pp, ff);
161*368c31abSDavid du Colombier 		pp->asize += FRAGASIZE(ff);
162*368c31abSDavid du Colombier 		ff->next = nil;
163*368c31abSDavid du Colombier 		ff->wp = ff->rp + n;
164*368c31abSDavid du Colombier 		f->rp += n;
165*368c31abSDavid du Colombier 	}
166*368c31abSDavid du Colombier 
167*368c31abSDavid du Colombier 	pp->first = p->first;
168*368c31abSDavid du Colombier 	pp->last = ff;
169*368c31abSDavid du Colombier 	p->first = f;
170*368c31abSDavid du Colombier 	return pp;
171*368c31abSDavid du Colombier }
172*368c31abSDavid du Colombier 
173*368c31abSDavid du Colombier int
packetConsume(Packet * p,uchar * buf,int n)174*368c31abSDavid du Colombier packetConsume(Packet *p, uchar *buf, int n)
175*368c31abSDavid du Colombier {
176*368c31abSDavid du Colombier 	NOTFREE(p);
177*368c31abSDavid du Colombier 	if(buf && !packetCopy(p, buf, 0, n))
178*368c31abSDavid du Colombier 		return 0;
179*368c31abSDavid du Colombier 	return packetTrim(p, n, p->size-n);
180*368c31abSDavid du Colombier }
181*368c31abSDavid du Colombier 
182*368c31abSDavid du Colombier int
packetTrim(Packet * p,int offset,int n)183*368c31abSDavid du Colombier packetTrim(Packet *p, int offset, int n)
184*368c31abSDavid du Colombier {
185*368c31abSDavid du Colombier 	Frag *f, *ff;
186*368c31abSDavid du Colombier 
187*368c31abSDavid du Colombier 	NOTFREE(p);
188*368c31abSDavid du Colombier 	if(offset < 0 || offset > p->size) {
189*368c31abSDavid du Colombier 		vtSetError(EPacketOffset);
190*368c31abSDavid du Colombier 		return 0;
191*368c31abSDavid du Colombier 	}
192*368c31abSDavid du Colombier 
193*368c31abSDavid du Colombier 	if(n < 0 || offset + n > p->size) {
194*368c31abSDavid du Colombier 		vtSetError(EPacketOffset);
195*368c31abSDavid du Colombier 		return 0;
196*368c31abSDavid du Colombier 	}
197*368c31abSDavid du Colombier 
198*368c31abSDavid du Colombier 	p->size = n;
199*368c31abSDavid du Colombier 
200*368c31abSDavid du Colombier 	/* easy case */
201*368c31abSDavid du Colombier 	if(n == 0) {
202*368c31abSDavid du Colombier 		for(f=p->first; f != nil; f=ff) {
203*368c31abSDavid du Colombier 			ff = f->next;
204*368c31abSDavid du Colombier 			fragFree(f);
205*368c31abSDavid du Colombier 		}
206*368c31abSDavid du Colombier 		p->first = p->last = nil;
207*368c31abSDavid du Colombier 		p->asize = 0;
208*368c31abSDavid du Colombier 		return 1;
209*368c31abSDavid du Colombier 	}
210*368c31abSDavid du Colombier 
211*368c31abSDavid du Colombier 	/* free before offset */
212*368c31abSDavid du Colombier 	for(f=p->first; offset >= FRAGSIZE(f); f=ff) {
213*368c31abSDavid du Colombier 		p->asize -= FRAGASIZE(f);
214*368c31abSDavid du Colombier 		offset -= FRAGSIZE(f);
215*368c31abSDavid du Colombier 		ff = f->next;
216*368c31abSDavid du Colombier 		fragFree(f);
217*368c31abSDavid du Colombier 	}
218*368c31abSDavid du Colombier 
219*368c31abSDavid du Colombier 	/* adjust frag */
220*368c31abSDavid du Colombier 	f->rp += offset;
221*368c31abSDavid du Colombier 	p->first = f;
222*368c31abSDavid du Colombier 
223*368c31abSDavid du Colombier 	/* skip middle */
224*368c31abSDavid du Colombier 	for(; n > 0 && n > FRAGSIZE(f); f=f->next)
225*368c31abSDavid du Colombier 		n -= FRAGSIZE(f);
226*368c31abSDavid du Colombier 
227*368c31abSDavid du Colombier 	/* adjust end */
228*368c31abSDavid du Colombier 	f->wp = f->rp + n;
229*368c31abSDavid du Colombier 	p->last = f;
230*368c31abSDavid du Colombier 	ff = f->next;
231*368c31abSDavid du Colombier 	f->next = nil;
232*368c31abSDavid du Colombier 
233*368c31abSDavid du Colombier 	/* free after */
234*368c31abSDavid du Colombier 	for(f=ff; f != nil; f=ff) {
235*368c31abSDavid du Colombier 		p->asize -= FRAGASIZE(f);
236*368c31abSDavid du Colombier 		ff = f->next;
237*368c31abSDavid du Colombier 		fragFree(f);
238*368c31abSDavid du Colombier 	}
239*368c31abSDavid du Colombier 	return 1;
240*368c31abSDavid du Colombier }
241*368c31abSDavid du Colombier 
242*368c31abSDavid du Colombier uchar *
packetHeader(Packet * p,int n)243*368c31abSDavid du Colombier packetHeader(Packet *p, int n)
244*368c31abSDavid du Colombier {
245*368c31abSDavid du Colombier 	Frag *f;
246*368c31abSDavid du Colombier 	Mem *m;
247*368c31abSDavid du Colombier 
248*368c31abSDavid du Colombier 	NOTFREE(p);
249*368c31abSDavid du Colombier 	if(n <= 0 || n > MaxFragSize) {
250*368c31abSDavid du Colombier 		vtSetError(EPacketSize);
251*368c31abSDavid du Colombier 		return 0;
252*368c31abSDavid du Colombier 	}
253*368c31abSDavid du Colombier 
254*368c31abSDavid du Colombier 	p->size += n;
255*368c31abSDavid du Colombier 
256*368c31abSDavid du Colombier 	/* try and fix in current frag */
257*368c31abSDavid du Colombier 	f = p->first;
258*368c31abSDavid du Colombier 	if(f != nil) {
259*368c31abSDavid du Colombier 		m = f->mem;
260*368c31abSDavid du Colombier 		if(n <= f->rp - m->bp)
261*368c31abSDavid du Colombier 		if(m->ref == 1 || memHead(m, f->rp, n)) {
262*368c31abSDavid du Colombier 			f->rp -= n;
263*368c31abSDavid du Colombier 			return f->rp;
264*368c31abSDavid du Colombier 		}
265*368c31abSDavid du Colombier 	}
266*368c31abSDavid du Colombier 
267*368c31abSDavid du Colombier 	/* add frag to front */
268*368c31abSDavid du Colombier 	f = fragAlloc(p, n, PEnd, p->first);
269*368c31abSDavid du Colombier 	p->asize += FRAGASIZE(f);
270*368c31abSDavid du Colombier 	if(p->first == nil)
271*368c31abSDavid du Colombier 		p->last = f;
272*368c31abSDavid du Colombier 	p->first = f;
273*368c31abSDavid du Colombier 	return f->rp;
274*368c31abSDavid du Colombier }
275*368c31abSDavid du Colombier 
276*368c31abSDavid du Colombier uchar *
packetTrailer(Packet * p,int n)277*368c31abSDavid du Colombier packetTrailer(Packet *p, int n)
278*368c31abSDavid du Colombier {
279*368c31abSDavid du Colombier 	Mem *m;
280*368c31abSDavid du Colombier 	Frag *f;
281*368c31abSDavid du Colombier 
282*368c31abSDavid du Colombier 	NOTFREE(p);
283*368c31abSDavid du Colombier 	if(n <= 0 || n > MaxFragSize) {
284*368c31abSDavid du Colombier 		vtSetError(EPacketSize);
285*368c31abSDavid du Colombier 		return 0;
286*368c31abSDavid du Colombier 	}
287*368c31abSDavid du Colombier 
288*368c31abSDavid du Colombier 	p->size += n;
289*368c31abSDavid du Colombier 
290*368c31abSDavid du Colombier 	/* try and fix in current frag */
291*368c31abSDavid du Colombier 	if(p->first != nil) {
292*368c31abSDavid du Colombier 		f = p->last;
293*368c31abSDavid du Colombier 		m = f->mem;
294*368c31abSDavid du Colombier 		if(n <= m->ep - f->wp)
295*368c31abSDavid du Colombier 		if(m->ref == 1 || memTail(m, f->wp, n)) {
296*368c31abSDavid du Colombier 			f->wp += n;
297*368c31abSDavid du Colombier 			return f->wp - n;
298*368c31abSDavid du Colombier 		}
299*368c31abSDavid du Colombier 	}
300*368c31abSDavid du Colombier 
301*368c31abSDavid du Colombier 	/* add frag to end */
302*368c31abSDavid du Colombier 	f = fragAlloc(p, n, (p->first == nil)?PMiddle:PFront, nil);
303*368c31abSDavid du Colombier 	p->asize += FRAGASIZE(f);
304*368c31abSDavid du Colombier 	if(p->first == nil)
305*368c31abSDavid du Colombier 		p->first = f;
306*368c31abSDavid du Colombier 	else
307*368c31abSDavid du Colombier 		p->last->next = f;
308*368c31abSDavid du Colombier 	p->last = f;
309*368c31abSDavid du Colombier 	return f->rp;
310*368c31abSDavid du Colombier }
311*368c31abSDavid du Colombier 
312*368c31abSDavid du Colombier int
packetPrefix(Packet * p,uchar * buf,int n)313*368c31abSDavid du Colombier packetPrefix(Packet *p, uchar *buf, int n)
314*368c31abSDavid du Colombier {
315*368c31abSDavid du Colombier 	Frag *f;
316*368c31abSDavid du Colombier 	int nn;
317*368c31abSDavid du Colombier 	Mem *m;
318*368c31abSDavid du Colombier 
319*368c31abSDavid du Colombier 	NOTFREE(p);
320*368c31abSDavid du Colombier 	if(n <= 0)
321*368c31abSDavid du Colombier 		return 1;
322*368c31abSDavid du Colombier 
323*368c31abSDavid du Colombier 	p->size += n;
324*368c31abSDavid du Colombier 
325*368c31abSDavid du Colombier 	/* try and fix in current frag */
326*368c31abSDavid du Colombier 	f = p->first;
327*368c31abSDavid du Colombier 	if(f != nil) {
328*368c31abSDavid du Colombier 		m = f->mem;
329*368c31abSDavid du Colombier 		nn = f->rp - m->bp;
330*368c31abSDavid du Colombier 		if(nn > n)
331*368c31abSDavid du Colombier 			nn = n;
332*368c31abSDavid du Colombier 		if(m->ref == 1 || memHead(m, f->rp, nn)) {
333*368c31abSDavid du Colombier 			f->rp -= nn;
334*368c31abSDavid du Colombier 			n -= nn;
335*368c31abSDavid du Colombier 			memmove(f->rp, buf+n, nn);
336*368c31abSDavid du Colombier 		}
337*368c31abSDavid du Colombier 	}
338*368c31abSDavid du Colombier 
339*368c31abSDavid du Colombier 	while(n > 0) {
340*368c31abSDavid du Colombier 		nn = n;
341*368c31abSDavid du Colombier 		if(nn > MaxFragSize)
342*368c31abSDavid du Colombier 			nn = MaxFragSize;
343*368c31abSDavid du Colombier 		f = fragAlloc(p, nn, PEnd, p->first);
344*368c31abSDavid du Colombier 		p->asize += FRAGASIZE(f);
345*368c31abSDavid du Colombier 		if(p->first == nil)
346*368c31abSDavid du Colombier 			p->last = f;
347*368c31abSDavid du Colombier 		p->first = f;
348*368c31abSDavid du Colombier 		n -= nn;
349*368c31abSDavid du Colombier 		memmove(f->rp, buf+n, nn);
350*368c31abSDavid du Colombier 	}
351*368c31abSDavid du Colombier 	return 1;
352*368c31abSDavid du Colombier }
353*368c31abSDavid du Colombier 
354*368c31abSDavid du Colombier int
packetAppend(Packet * p,uchar * buf,int n)355*368c31abSDavid du Colombier packetAppend(Packet *p, uchar *buf, int n)
356*368c31abSDavid du Colombier {
357*368c31abSDavid du Colombier 	Frag *f;
358*368c31abSDavid du Colombier 	int nn;
359*368c31abSDavid du Colombier 	Mem *m;
360*368c31abSDavid du Colombier 
361*368c31abSDavid du Colombier 	NOTFREE(p);
362*368c31abSDavid du Colombier 	if(n <= 0)
363*368c31abSDavid du Colombier 		return 1;
364*368c31abSDavid du Colombier 
365*368c31abSDavid du Colombier 	p->size += n;
366*368c31abSDavid du Colombier 	/* try and fix in current frag */
367*368c31abSDavid du Colombier 	if(p->first != nil) {
368*368c31abSDavid du Colombier 		f = p->last;
369*368c31abSDavid du Colombier 		m = f->mem;
370*368c31abSDavid du Colombier 		nn = m->ep - f->wp;
371*368c31abSDavid du Colombier 		if(nn > n)
372*368c31abSDavid du Colombier 			nn = n;
373*368c31abSDavid du Colombier 		if(m->ref == 1 || memTail(m, f->wp, nn)) {
374*368c31abSDavid du Colombier 			memmove(f->wp, buf, nn);
375*368c31abSDavid du Colombier 			f->wp += nn;
376*368c31abSDavid du Colombier 			buf += nn;
377*368c31abSDavid du Colombier 			n -= nn;
378*368c31abSDavid du Colombier 		}
379*368c31abSDavid du Colombier 	}
380*368c31abSDavid du Colombier 
381*368c31abSDavid du Colombier 	while(n > 0) {
382*368c31abSDavid du Colombier 		nn = n;
383*368c31abSDavid du Colombier 		if(nn > MaxFragSize)
384*368c31abSDavid du Colombier 			nn = MaxFragSize;
385*368c31abSDavid du Colombier 		f = fragAlloc(p, nn, (p->first == nil)?PMiddle:PFront, nil);
386*368c31abSDavid du Colombier 		p->asize += FRAGASIZE(f);
387*368c31abSDavid du Colombier 		if(p->first == nil)
388*368c31abSDavid du Colombier 			p->first = f;
389*368c31abSDavid du Colombier 		else
390*368c31abSDavid du Colombier 			p->last->next = f;
391*368c31abSDavid du Colombier 		p->last = f;
392*368c31abSDavid du Colombier 		memmove(f->rp, buf, nn);
393*368c31abSDavid du Colombier 		buf += nn;
394*368c31abSDavid du Colombier 		n -= nn;
395*368c31abSDavid du Colombier 	}
396*368c31abSDavid du Colombier 	return 1;
397*368c31abSDavid du Colombier }
398*368c31abSDavid du Colombier 
399*368c31abSDavid du Colombier int
packetConcat(Packet * p,Packet * pp)400*368c31abSDavid du Colombier packetConcat(Packet *p, Packet *pp)
401*368c31abSDavid du Colombier {
402*368c31abSDavid du Colombier 	NOTFREE(p);
403*368c31abSDavid du Colombier 	NOTFREE(pp);
404*368c31abSDavid du Colombier 	if(pp->size == 0)
405*368c31abSDavid du Colombier 		return 1;
406*368c31abSDavid du Colombier 	p->size += pp->size;
407*368c31abSDavid du Colombier 	p->asize += pp->asize;
408*368c31abSDavid du Colombier 
409*368c31abSDavid du Colombier 	if(p->first != nil)
410*368c31abSDavid du Colombier 		p->last->next = pp->first;
411*368c31abSDavid du Colombier 	else
412*368c31abSDavid du Colombier 		p->first = pp->first;
413*368c31abSDavid du Colombier 	p->last = pp->last;
414*368c31abSDavid du Colombier 	pp->size = 0;
415*368c31abSDavid du Colombier 	pp->asize = 0;
416*368c31abSDavid du Colombier 	pp->first = nil;
417*368c31abSDavid du Colombier 	pp->last = nil;
418*368c31abSDavid du Colombier 	return 1;
419*368c31abSDavid du Colombier }
420*368c31abSDavid du Colombier 
421*368c31abSDavid du Colombier uchar *
packetPeek(Packet * p,uchar * buf,int offset,int n)422*368c31abSDavid du Colombier packetPeek(Packet *p, uchar *buf, int offset, int n)
423*368c31abSDavid du Colombier {
424*368c31abSDavid du Colombier 	Frag *f;
425*368c31abSDavid du Colombier 	int nn;
426*368c31abSDavid du Colombier 	uchar *b;
427*368c31abSDavid du Colombier 
428*368c31abSDavid du Colombier 	NOTFREE(p);
429*368c31abSDavid du Colombier 	if(n == 0)
430*368c31abSDavid du Colombier 		return buf;
431*368c31abSDavid du Colombier 
432*368c31abSDavid du Colombier 	if(offset < 0 || offset >= p->size) {
433*368c31abSDavid du Colombier 		vtSetError(EPacketOffset);
434*368c31abSDavid du Colombier 		return 0;
435*368c31abSDavid du Colombier 	}
436*368c31abSDavid du Colombier 
437*368c31abSDavid du Colombier 	if(n < 0 || offset + n > p->size) {
438*368c31abSDavid du Colombier 		vtSetError(EPacketSize);
439*368c31abSDavid du Colombier 		return 0;
440*368c31abSDavid du Colombier 	}
441*368c31abSDavid du Colombier 
442*368c31abSDavid du Colombier 	/* skip up to offset */
443*368c31abSDavid du Colombier 	for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
444*368c31abSDavid du Colombier 		offset -= FRAGSIZE(f);
445*368c31abSDavid du Colombier 
446*368c31abSDavid du Colombier 	/* easy case */
447*368c31abSDavid du Colombier 	if(offset + n <= FRAGSIZE(f))
448*368c31abSDavid du Colombier 		return f->rp + offset;
449*368c31abSDavid du Colombier 
450*368c31abSDavid du Colombier 	for(b=buf; n>0; n -= nn) {
451*368c31abSDavid du Colombier 		nn = FRAGSIZE(f) - offset;
452*368c31abSDavid du Colombier 		if(nn > n)
453*368c31abSDavid du Colombier 			nn = n;
454*368c31abSDavid du Colombier 		memmove(b, f->rp+offset, nn);
455*368c31abSDavid du Colombier 		offset = 0;
456*368c31abSDavid du Colombier 		f = f->next;
457*368c31abSDavid du Colombier 		b += nn;
458*368c31abSDavid du Colombier 	}
459*368c31abSDavid du Colombier 
460*368c31abSDavid du Colombier 	return buf;
461*368c31abSDavid du Colombier }
462*368c31abSDavid du Colombier 
463*368c31abSDavid du Colombier int
packetCopy(Packet * p,uchar * buf,int offset,int n)464*368c31abSDavid du Colombier packetCopy(Packet *p, uchar *buf, int offset, int n)
465*368c31abSDavid du Colombier {
466*368c31abSDavid du Colombier 	uchar *b;
467*368c31abSDavid du Colombier 
468*368c31abSDavid du Colombier 	NOTFREE(p);
469*368c31abSDavid du Colombier 	b = packetPeek(p, buf, offset, n);
470*368c31abSDavid du Colombier 	if(b == nil)
471*368c31abSDavid du Colombier 		return 0;
472*368c31abSDavid du Colombier 	if(b != buf)
473*368c31abSDavid du Colombier 		memmove(buf, b, n);
474*368c31abSDavid du Colombier 	return 1;
475*368c31abSDavid du Colombier }
476*368c31abSDavid du Colombier 
477*368c31abSDavid du Colombier int
packetFragments(Packet * p,IOchunk * io,int nio,int offset)478*368c31abSDavid du Colombier packetFragments(Packet *p, IOchunk *io, int nio, int offset)
479*368c31abSDavid du Colombier {
480*368c31abSDavid du Colombier 	Frag *f;
481*368c31abSDavid du Colombier 	int size;
482*368c31abSDavid du Colombier 	IOchunk *eio;
483*368c31abSDavid du Colombier 
484*368c31abSDavid du Colombier 	NOTFREE(p);
485*368c31abSDavid du Colombier 	if(p->size == 0 || nio <= 0)
486*368c31abSDavid du Colombier 		return 0;
487*368c31abSDavid du Colombier 
488*368c31abSDavid du Colombier 	if(offset < 0 || offset > p->size) {
489*368c31abSDavid du Colombier 		vtSetError(EPacketOffset);
490*368c31abSDavid du Colombier 		return -1;
491*368c31abSDavid du Colombier 	}
492*368c31abSDavid du Colombier 
493*368c31abSDavid du Colombier 	for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
494*368c31abSDavid du Colombier 		offset -= FRAGSIZE(f);
495*368c31abSDavid du Colombier 
496*368c31abSDavid du Colombier 	size = 0;
497*368c31abSDavid du Colombier 	eio = io + nio;
498*368c31abSDavid du Colombier 	for(; f != nil && io < eio; f=f->next) {
499*368c31abSDavid du Colombier 		io->addr = f->rp + offset;
500*368c31abSDavid du Colombier 		io->len = f->wp - (f->rp + offset);
501*368c31abSDavid du Colombier 		offset = 0;
502*368c31abSDavid du Colombier 		size += io->len;
503*368c31abSDavid du Colombier 		io++;
504*368c31abSDavid du Colombier 	}
505*368c31abSDavid du Colombier 
506*368c31abSDavid du Colombier 	return size;
507*368c31abSDavid du Colombier }
508*368c31abSDavid du Colombier 
509*368c31abSDavid du Colombier void
packetStats(void)510*368c31abSDavid du Colombier packetStats(void)
511*368c31abSDavid du Colombier {
512*368c31abSDavid du Colombier 	Packet *p;
513*368c31abSDavid du Colombier 	Frag *f;
514*368c31abSDavid du Colombier 	Mem *m;
515*368c31abSDavid du Colombier 
516*368c31abSDavid du Colombier 	int np, nf, nsm, nbm;
517*368c31abSDavid du Colombier 
518*368c31abSDavid du Colombier 	lock(&freeList.lk);
519*368c31abSDavid du Colombier 	np = 0;
520*368c31abSDavid du Colombier 	for(p=freeList.packet; p; p=p->next)
521*368c31abSDavid du Colombier 		np++;
522*368c31abSDavid du Colombier 	nf = 0;
523*368c31abSDavid du Colombier 	for(f=freeList.frag; f; f=f->next)
524*368c31abSDavid du Colombier 		nf++;
525*368c31abSDavid du Colombier 	nsm = 0;
526*368c31abSDavid du Colombier 	for(m=freeList.smallMem; m; m=m->next)
527*368c31abSDavid du Colombier 		nsm++;
528*368c31abSDavid du Colombier 	nbm = 0;
529*368c31abSDavid du Colombier 	for(m=freeList.bigMem; m; m=m->next)
530*368c31abSDavid du Colombier 		nbm++;
531*368c31abSDavid du Colombier 
532*368c31abSDavid du Colombier 	fprint(2, "packet: %d/%d frag: %d/%d small mem: %d/%d big mem: %d/%d\n",
533*368c31abSDavid du Colombier 		np, freeList.npacket,
534*368c31abSDavid du Colombier 		nf, freeList.nfrag,
535*368c31abSDavid du Colombier 		nsm, freeList.nsmallMem,
536*368c31abSDavid du Colombier 		nbm, freeList.nbigMem);
537*368c31abSDavid du Colombier 
538*368c31abSDavid du Colombier 	unlock(&freeList.lk);
539*368c31abSDavid du Colombier }
540*368c31abSDavid du Colombier 
541*368c31abSDavid du Colombier 
542*368c31abSDavid du Colombier int
packetSize(Packet * p)543*368c31abSDavid du Colombier packetSize(Packet *p)
544*368c31abSDavid du Colombier {
545*368c31abSDavid du Colombier 	NOTFREE(p);
546*368c31abSDavid du Colombier 	if(0) {
547*368c31abSDavid du Colombier 		Frag *f;
548*368c31abSDavid du Colombier 		int size = 0;
549*368c31abSDavid du Colombier 
550*368c31abSDavid du Colombier 		for(f=p->first; f; f=f->next)
551*368c31abSDavid du Colombier 			size += FRAGSIZE(f);
552*368c31abSDavid du Colombier 		if(size != p->size)
553*368c31abSDavid du Colombier 			fprint(2, "packetSize %d %d\n", size, p->size);
554*368c31abSDavid du Colombier 		assert(size == p->size);
555*368c31abSDavid du Colombier 	}
556*368c31abSDavid du Colombier 	return p->size;
557*368c31abSDavid du Colombier }
558*368c31abSDavid du Colombier 
559*368c31abSDavid du Colombier int
packetAllocatedSize(Packet * p)560*368c31abSDavid du Colombier packetAllocatedSize(Packet *p)
561*368c31abSDavid du Colombier {
562*368c31abSDavid du Colombier 	NOTFREE(p);
563*368c31abSDavid du Colombier 	if(0) {
564*368c31abSDavid du Colombier 		Frag *f;
565*368c31abSDavid du Colombier 		int asize = 0;
566*368c31abSDavid du Colombier 
567*368c31abSDavid du Colombier 		for(f=p->first; f; f=f->next)
568*368c31abSDavid du Colombier 			asize += FRAGASIZE(f);
569*368c31abSDavid du Colombier 		if(asize != p->asize)
570*368c31abSDavid du Colombier 			fprint(2, "packetAllocatedSize %d %d\n", asize, p->asize);
571*368c31abSDavid du Colombier 		assert(asize == p->asize);
572*368c31abSDavid du Colombier 	}
573*368c31abSDavid du Colombier 	return p->asize;
574*368c31abSDavid du Colombier }
575*368c31abSDavid du Colombier 
576*368c31abSDavid du Colombier void
packetSha1(Packet * p,uchar sha1[VtScoreSize])577*368c31abSDavid du Colombier packetSha1(Packet *p, uchar sha1[VtScoreSize])
578*368c31abSDavid du Colombier {
579*368c31abSDavid du Colombier 	Frag *f;
580*368c31abSDavid du Colombier 	VtSha1 *s;
581*368c31abSDavid du Colombier 	int size;
582*368c31abSDavid du Colombier 
583*368c31abSDavid du Colombier 	NOTFREE(p);
584*368c31abSDavid du Colombier 	s = vtSha1Alloc();
585*368c31abSDavid du Colombier 	size = p->size;
586*368c31abSDavid du Colombier 	for(f=p->first; f; f=f->next) {
587*368c31abSDavid du Colombier 		vtSha1Update(s, f->rp, FRAGSIZE(f));
588*368c31abSDavid du Colombier 		size -= FRAGSIZE(f);
589*368c31abSDavid du Colombier 	}
590*368c31abSDavid du Colombier 	assert(size == 0);
591*368c31abSDavid du Colombier 	vtSha1Final(s, sha1);
592*368c31abSDavid du Colombier 	vtSha1Free(s);
593*368c31abSDavid du Colombier }
594*368c31abSDavid du Colombier 
595*368c31abSDavid du Colombier int
packetCmp(Packet * pkt0,Packet * pkt1)596*368c31abSDavid du Colombier packetCmp(Packet *pkt0, Packet *pkt1)
597*368c31abSDavid du Colombier {
598*368c31abSDavid du Colombier 	Frag *f0, *f1;
599*368c31abSDavid du Colombier 	int n0, n1, x;
600*368c31abSDavid du Colombier 
601*368c31abSDavid du Colombier 	NOTFREE(pkt0);
602*368c31abSDavid du Colombier 	NOTFREE(pkt1);
603*368c31abSDavid du Colombier 	f0 = pkt0->first;
604*368c31abSDavid du Colombier 	f1 = pkt1->first;
605*368c31abSDavid du Colombier 
606*368c31abSDavid du Colombier 	if(f0 == nil)
607*368c31abSDavid du Colombier 		return (f1 == nil)?0:-1;
608*368c31abSDavid du Colombier 	if(f1 == nil)
609*368c31abSDavid du Colombier 		return 1;
610*368c31abSDavid du Colombier 	n0 = FRAGSIZE(f0);
611*368c31abSDavid du Colombier 	n1 = FRAGSIZE(f1);
612*368c31abSDavid du Colombier 
613*368c31abSDavid du Colombier 	for(;;) {
614*368c31abSDavid du Colombier 		if(n0 < n1) {
615*368c31abSDavid du Colombier 			x = memcmp(f0->wp - n0, f1->wp - n1, n0);
616*368c31abSDavid du Colombier 			if(x != 0)
617*368c31abSDavid du Colombier 				return x;
618*368c31abSDavid du Colombier 			n1 -= n0;
619*368c31abSDavid du Colombier 			f0 = f0->next;
620*368c31abSDavid du Colombier 			if(f0 == nil)
621*368c31abSDavid du Colombier 				return -1;
622*368c31abSDavid du Colombier 			n0 = FRAGSIZE(f0);
623*368c31abSDavid du Colombier 		} else if (n0 > n1) {
624*368c31abSDavid du Colombier 			x = memcmp(f0->wp - n0, f1->wp - n1, n1);
625*368c31abSDavid du Colombier 			if(x != 0)
626*368c31abSDavid du Colombier 				return x;
627*368c31abSDavid du Colombier 			n0 -= n1;
628*368c31abSDavid du Colombier 			f1 = f1->next;
629*368c31abSDavid du Colombier 			if(f1 == nil)
630*368c31abSDavid du Colombier 				return 1;
631*368c31abSDavid du Colombier 			n1 = FRAGSIZE(f1);
632*368c31abSDavid du Colombier 		} else { /* n0 == n1 */
633*368c31abSDavid du Colombier 			x = memcmp(f0->wp - n0, f1->wp - n1, n0);
634*368c31abSDavid du Colombier 			if(x != 0)
635*368c31abSDavid du Colombier 				return x;
636*368c31abSDavid du Colombier 			f0 = f0->next;
637*368c31abSDavid du Colombier 			f1 = f1->next;
638*368c31abSDavid du Colombier 			if(f0 == nil)
639*368c31abSDavid du Colombier 				return (f1 == nil)?0:-1;
640*368c31abSDavid du Colombier 			if(f1 == nil)
641*368c31abSDavid du Colombier 				return 1;
642*368c31abSDavid du Colombier 			n0 = FRAGSIZE(f0);
643*368c31abSDavid du Colombier 			n1 = FRAGSIZE(f1);
644*368c31abSDavid du Colombier 		}
645*368c31abSDavid du Colombier 	}
646*368c31abSDavid du Colombier }
647*368c31abSDavid du Colombier 
648*368c31abSDavid du Colombier 
649*368c31abSDavid du Colombier static Frag *
fragAlloc(Packet * p,int n,int pos,Frag * next)650*368c31abSDavid du Colombier fragAlloc(Packet *p, int n, int pos, Frag *next)
651*368c31abSDavid du Colombier {
652*368c31abSDavid du Colombier 	Frag *f, *ef;
653*368c31abSDavid du Colombier 	Mem *m;
654*368c31abSDavid du Colombier 
655*368c31abSDavid du Colombier 	/* look for local frag */
656*368c31abSDavid du Colombier 	f = &p->local[0];
657*368c31abSDavid du Colombier 	ef = &p->local[NLocalFrag];
658*368c31abSDavid du Colombier 	for(;f<ef; f++) {
659*368c31abSDavid du Colombier 		if(f->state == FragLocalFree) {
660*368c31abSDavid du Colombier 			f->state = FragLocalAlloc;
661*368c31abSDavid du Colombier 			goto Found;
662*368c31abSDavid du Colombier 		}
663*368c31abSDavid du Colombier 	}
664*368c31abSDavid du Colombier 	lock(&freeList.lk);
665*368c31abSDavid du Colombier 	f = freeList.frag;
666*368c31abSDavid du Colombier 	if(f != nil)
667*368c31abSDavid du Colombier 		freeList.frag = f->next;
668*368c31abSDavid du Colombier 	else
669*368c31abSDavid du Colombier 		freeList.nfrag++;
670*368c31abSDavid du Colombier 	unlock(&freeList.lk);
671*368c31abSDavid du Colombier 
672*368c31abSDavid du Colombier 	if(f == nil) {
673*368c31abSDavid du Colombier 		f = vtMemBrk(sizeof(Frag));
674*368c31abSDavid du Colombier 		f->state = FragGlobal;
675*368c31abSDavid du Colombier 	}
676*368c31abSDavid du Colombier 
677*368c31abSDavid du Colombier Found:
678*368c31abSDavid du Colombier 	if(n == 0)
679*368c31abSDavid du Colombier 		return f;
680*368c31abSDavid du Colombier 
681*368c31abSDavid du Colombier 	if(pos == PEnd && next == nil)
682*368c31abSDavid du Colombier 		pos = PMiddle;
683*368c31abSDavid du Colombier 	m = memAlloc(n, pos);
684*368c31abSDavid du Colombier 	f->mem = m;
685*368c31abSDavid du Colombier 	f->rp = m->rp;
686*368c31abSDavid du Colombier 	f->wp = m->wp;
687*368c31abSDavid du Colombier 	f->next = next;
688*368c31abSDavid du Colombier 
689*368c31abSDavid du Colombier 	return f;
690*368c31abSDavid du Colombier }
691*368c31abSDavid du Colombier 
692*368c31abSDavid du Colombier static Frag *
fragDup(Packet * p,Frag * f)693*368c31abSDavid du Colombier fragDup(Packet *p, Frag *f)
694*368c31abSDavid du Colombier {
695*368c31abSDavid du Colombier 	Frag *ff;
696*368c31abSDavid du Colombier 	Mem *m;
697*368c31abSDavid du Colombier 
698*368c31abSDavid du Colombier 	m = f->mem;
699*368c31abSDavid du Colombier 
700*368c31abSDavid du Colombier 	/*
701*368c31abSDavid du Colombier 	 * m->rp && m->wp can be out of date when ref == 1
702*368c31abSDavid du Colombier 	 * also, potentially reclaims space from previous frags
703*368c31abSDavid du Colombier 	 */
704*368c31abSDavid du Colombier 	if(m->ref == 1) {
705*368c31abSDavid du Colombier 		m->rp = f->rp;
706*368c31abSDavid du Colombier 		m->wp = f->wp;
707*368c31abSDavid du Colombier 	}
708*368c31abSDavid du Colombier 
709*368c31abSDavid du Colombier 	ff = fragAlloc(p, 0, 0, nil);
710*368c31abSDavid du Colombier 	*ff = *f;
711*368c31abSDavid du Colombier 	lock(&m->lk);
712*368c31abSDavid du Colombier 	m->ref++;
713*368c31abSDavid du Colombier 	unlock(&m->lk);
714*368c31abSDavid du Colombier 	return ff;
715*368c31abSDavid du Colombier }
716*368c31abSDavid du Colombier 
717*368c31abSDavid du Colombier 
718*368c31abSDavid du Colombier static void
fragFree(Frag * f)719*368c31abSDavid du Colombier fragFree(Frag *f)
720*368c31abSDavid du Colombier {
721*368c31abSDavid du Colombier 	memFree(f->mem);
722*368c31abSDavid du Colombier 
723*368c31abSDavid du Colombier 	if(f->state == FragLocalAlloc) {
724*368c31abSDavid du Colombier 		f->state = FragLocalFree;
725*368c31abSDavid du Colombier 		return;
726*368c31abSDavid du Colombier 	}
727*368c31abSDavid du Colombier 
728*368c31abSDavid du Colombier 	lock(&freeList.lk);
729*368c31abSDavid du Colombier 	f->next = freeList.frag;
730*368c31abSDavid du Colombier 	freeList.frag = f;
731*368c31abSDavid du Colombier 	unlock(&freeList.lk);
732*368c31abSDavid du Colombier }
733*368c31abSDavid du Colombier 
734*368c31abSDavid du Colombier static Mem *
memAlloc(int n,int pos)735*368c31abSDavid du Colombier memAlloc(int n, int pos)
736*368c31abSDavid du Colombier {
737*368c31abSDavid du Colombier 	Mem *m;
738*368c31abSDavid du Colombier 	int nn;
739*368c31abSDavid du Colombier 
740*368c31abSDavid du Colombier 	if(n < 0 || n > MaxFragSize) {
741*368c31abSDavid du Colombier 		vtSetError(EPacketSize);
742*368c31abSDavid du Colombier 		return 0;
743*368c31abSDavid du Colombier 	}
744*368c31abSDavid du Colombier 	if(n <= SmallMemSize) {
745*368c31abSDavid du Colombier 		lock(&freeList.lk);
746*368c31abSDavid du Colombier 		m = freeList.smallMem;
747*368c31abSDavid du Colombier 		if(m != nil)
748*368c31abSDavid du Colombier 			freeList.smallMem = m->next;
749*368c31abSDavid du Colombier 		else
750*368c31abSDavid du Colombier 			freeList.nsmallMem++;
751*368c31abSDavid du Colombier 		unlock(&freeList.lk);
752*368c31abSDavid du Colombier 		nn = SmallMemSize;
753*368c31abSDavid du Colombier 	} else {
754*368c31abSDavid du Colombier 		lock(&freeList.lk);
755*368c31abSDavid du Colombier 		m = freeList.bigMem;
756*368c31abSDavid du Colombier 		if(m != nil)
757*368c31abSDavid du Colombier 			freeList.bigMem = m->next;
758*368c31abSDavid du Colombier 		else
759*368c31abSDavid du Colombier 			freeList.nbigMem++;
760*368c31abSDavid du Colombier 		unlock(&freeList.lk);
761*368c31abSDavid du Colombier 		nn = BigMemSize;
762*368c31abSDavid du Colombier 	}
763*368c31abSDavid du Colombier 
764*368c31abSDavid du Colombier 	if(m == nil) {
765*368c31abSDavid du Colombier 		m = vtMemBrk(sizeof(Mem));
766*368c31abSDavid du Colombier 		m->bp = vtMemBrk(nn);
767*368c31abSDavid du Colombier 		m->ep = m->bp + nn;
768*368c31abSDavid du Colombier 	}
769*368c31abSDavid du Colombier 	assert(m->ref == 0);
770*368c31abSDavid du Colombier 	m->ref = 1;
771*368c31abSDavid du Colombier 
772*368c31abSDavid du Colombier 	switch(pos) {
773*368c31abSDavid du Colombier 	default:
774*368c31abSDavid du Colombier 		assert(0);
775*368c31abSDavid du Colombier 	case PFront:
776*368c31abSDavid du Colombier 		m->rp = m->bp;
777*368c31abSDavid du Colombier 		break;
778*368c31abSDavid du Colombier 	case PMiddle:
779*368c31abSDavid du Colombier 		/* leave a little bit at end */
780*368c31abSDavid du Colombier 		m->rp = m->ep - n - 32;
781*368c31abSDavid du Colombier 		break;
782*368c31abSDavid du Colombier 	case PEnd:
783*368c31abSDavid du Colombier 		m->rp = m->ep - n;
784*368c31abSDavid du Colombier 		break;
785*368c31abSDavid du Colombier 	}
786*368c31abSDavid du Colombier 	/* check we did not blow it */
787*368c31abSDavid du Colombier 	if(m->rp < m->bp)
788*368c31abSDavid du Colombier 		m->rp = m->bp;
789*368c31abSDavid du Colombier 	m->wp = m->rp + n;
790*368c31abSDavid du Colombier 	assert(m->rp >= m->bp && m->wp <= m->ep);
791*368c31abSDavid du Colombier 	return m;
792*368c31abSDavid du Colombier }
793*368c31abSDavid du Colombier 
794*368c31abSDavid du Colombier static void
memFree(Mem * m)795*368c31abSDavid du Colombier memFree(Mem *m)
796*368c31abSDavid du Colombier {
797*368c31abSDavid du Colombier 	lock(&m->lk);
798*368c31abSDavid du Colombier 	m->ref--;
799*368c31abSDavid du Colombier 	if(m->ref > 0) {
800*368c31abSDavid du Colombier 		unlock(&m->lk);
801*368c31abSDavid du Colombier 		return;
802*368c31abSDavid du Colombier 	}
803*368c31abSDavid du Colombier 	unlock(&m->lk);
804*368c31abSDavid du Colombier 	assert(m->ref == 0);
805*368c31abSDavid du Colombier 
806*368c31abSDavid du Colombier 	switch(m->ep - m->bp) {
807*368c31abSDavid du Colombier 	default:
808*368c31abSDavid du Colombier 		assert(0);
809*368c31abSDavid du Colombier 	case SmallMemSize:
810*368c31abSDavid du Colombier 		lock(&freeList.lk);
811*368c31abSDavid du Colombier 		m->next = freeList.smallMem;
812*368c31abSDavid du Colombier 		freeList.smallMem = m;
813*368c31abSDavid du Colombier 		unlock(&freeList.lk);
814*368c31abSDavid du Colombier 		break;
815*368c31abSDavid du Colombier 	case BigMemSize:
816*368c31abSDavid du Colombier 		lock(&freeList.lk);
817*368c31abSDavid du Colombier 		m->next = freeList.bigMem;
818*368c31abSDavid du Colombier 		freeList.bigMem = m;
819*368c31abSDavid du Colombier 		unlock(&freeList.lk);
820*368c31abSDavid du Colombier 		break;
821*368c31abSDavid du Colombier 	}
822*368c31abSDavid du Colombier }
823*368c31abSDavid du Colombier 
824*368c31abSDavid du Colombier static int
memHead(Mem * m,uchar * rp,int n)825*368c31abSDavid du Colombier memHead(Mem *m, uchar *rp, int n)
826*368c31abSDavid du Colombier {
827*368c31abSDavid du Colombier 	lock(&m->lk);
828*368c31abSDavid du Colombier 	if(m->rp != rp) {
829*368c31abSDavid du Colombier 		unlock(&m->lk);
830*368c31abSDavid du Colombier 		return 0;
831*368c31abSDavid du Colombier 	}
832*368c31abSDavid du Colombier 	m->rp -= n;
833*368c31abSDavid du Colombier 	unlock(&m->lk);
834*368c31abSDavid du Colombier 	return 1;
835*368c31abSDavid du Colombier }
836*368c31abSDavid du Colombier 
837*368c31abSDavid du Colombier static int
memTail(Mem * m,uchar * wp,int n)838*368c31abSDavid du Colombier memTail(Mem *m, uchar *wp, int n)
839*368c31abSDavid du Colombier {
840*368c31abSDavid du Colombier 	lock(&m->lk);
841*368c31abSDavid du Colombier 	if(m->wp != wp) {
842*368c31abSDavid du Colombier 		unlock(&m->lk);
843*368c31abSDavid du Colombier 		return 0;
844*368c31abSDavid du Colombier 	}
845*368c31abSDavid du Colombier 	m->wp += n;
846*368c31abSDavid du Colombier 	unlock(&m->lk);
847*368c31abSDavid du Colombier 	return 1;
848*368c31abSDavid du Colombier }
849