Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature-vt/sys/src/cmd/ip/ppp/block.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <ip.h>
4
#include <auth.h>
5
#include "ppp.h"
6
 
7
enum
8
{
9
	PAD	= 128,
10
	NLIST	= (1<<5),
11
	BPOW	= 10,
12
};
13
 
14
typedef struct Barena Barena;
15
struct Barena
16
{
17
	QLock;
18
	Block*	list[NLIST];
19
};
20
static Barena area;
21
 
22
#define ADEBUG if(0)
23
 
24
 
25
/*
26
 *  allocation tracing
27
 */
28
enum
29
{
30
	Npc=	64,
31
};
32
typedef struct Arefent Arefent;
33
struct Arefent
34
{
35
	uint	pc;
36
	uint	n;
37
};
38
typedef struct Aref Aref;
39
struct  Aref
40
{
41
	Arefent	tab[Npc];
42
	QLock;
43
};
44
Aref arefblock;
45
 
46
static ulong	callerpc(void*);
47
static void	aref(Aref*, ulong);
48
static void	aunref(Aref*, ulong);
49
 
50
Block*
51
allocb(int len)
52
{
53
	int sz;
54
	Block *bp, **l;
55
 
56
	len += PAD;
57
	sz = (len>>BPOW)&(NLIST-1);
58
 
59
	qlock(&area);
60
	l = &area.list[sz];
61
	for(bp = *l; bp; bp = bp->flist) {
62
		if(bp->bsz >= len) {
63
			*l = bp->flist;
64
			qunlock(&area);
65
 
66
			bp->next = nil;
67
			bp->list = nil;
68
			bp->flist = nil;
69
			bp->base = (uchar*)bp+sizeof(Block);
70
			bp->rptr = bp->base+PAD;
71
			bp->wptr = bp->rptr;
72
			bp->lim  = bp->base+bp->bsz;
73
			bp->flow = nil;
74
			bp->flags= 0;
75
			ADEBUG {
76
				bp->pc = callerpc(&len);
77
				aref(&arefblock, bp->pc);
78
			}
79
			return bp;
80
		}
81
		l = &bp->flist;
82
	}
83
 
84
	qunlock(&area);
85
 
86
	bp = mallocz(sizeof(Block)+len, 1);
87
 
88
	bp->bsz  = len;
89
	bp->base = (uchar*)bp+sizeof(Block);
90
	bp->rptr = bp->base+PAD;
91
	bp->wptr = bp->rptr;
92
	bp->lim  = bp->base+len;
93
	ADEBUG {
94
		bp->pc = callerpc(&len);
95
		aref(&arefblock, bp->pc);
96
	}
97
	return bp;
98
}
99
 
100
void
101
freeb(Block *bp)
102
{
103
	int sz;
104
	Block **l, *next;
105
 
106
	qlock(&area);
107
	while(bp) {
108
		sz = (bp->bsz>>BPOW)&(NLIST-1);
109
 
110
		l = &area.list[sz];
111
		bp->flist = *l;
112
		*l = bp;
113
 
114
		next = bp->next;
115
 
116
		/* to catch use after free */
117
		bp->rptr = (uchar*)0xdeadbabe;
118
		bp->wptr = (uchar*)0xdeadbabe;
119
		bp->next = (Block*)0xdeadbabe;
120
		bp->list = (Block*)0xdeadbabe;
121
 
122
		ADEBUG aunref(&arefblock, bp->pc);
123
 
124
		bp = next;
125
	}
126
	qunlock(&area);
127
}
128
 
129
/*
130
 *  concatenate a list of blocks into a single one and make sure
131
 *  the result is at least min uchars
132
 */
133
Block*
134
concat(Block *bp)
135
{
136
	int len;
137
	Block *nb, *f;
138
 
139
	nb = allocb(blen(bp));
140
	for(f = bp; f; f = f->next) {
141
		len = BLEN(f);
142
		memmove(nb->wptr, f->rptr, len);
143
		nb->wptr += len;
144
	}
145
	freeb(bp);
146
	return nb;
147
}
148
 
149
int
150
blen(Block *bp)
151
{
152
	int len;
153
 
154
	len = 0;
155
	while(bp) {
156
		len += BLEN(bp);
157
		bp = bp->next;
158
	}
159
	return len;
160
}
161
 
162
Block *
163
pullup(Block *bp, int n)
164
{
165
	int i;
166
	Block *nbp;
167
 
168
	/*
169
	 *  this should almost always be true, the rest it
170
	 *  just for to avoid every caller checking.
171
	 */
172
	if(BLEN(bp) >= n)
173
		return bp;
174
 
175
	/*
176
	 *  if not enough room in the first block,
177
	 *  add another to the front of the list.
178
	 */
179
	if(bp->lim - bp->rptr < n){
180
		nbp = allocb(n);
181
		nbp->next = bp;
182
		bp = nbp;
183
	}
184
 
185
	/*
186
	 *  copy uchars from the trailing blocks into the first
187
	 */
188
	n -= BLEN(bp);
189
	while(nbp = bp->next){
190
		i = BLEN(nbp);
191
		if(i >= n) {
192
			memmove(bp->wptr, nbp->rptr, n);
193
			bp->wptr += n;
194
			nbp->rptr += n;
195
			return bp;
196
		}
197
		else {
198
			memmove(bp->wptr, nbp->rptr, i);
199
			bp->wptr += i;
200
			bp->next = nbp->next;
201
			nbp->next = nil;
202
			freeb(nbp);
203
			n -= i;
204
		}
205
	}
206
	freeb(bp);
207
	return nil;
208
}
209
 
210
/*
211
 *  Pad a block to the front with n uchars.  This is used to add protocol
212
 *  headers to the front of blocks.
213
 */
214
Block*
215
padb(Block *bp, int n)
216
{
217
	Block *nbp;
218
 
219
	if(bp->rptr-bp->base >= n) {
220
		bp->rptr -= n;
221
		return bp;
222
	}
223
	else {
224
		/* fprint(2, "padb: required %d PAD %d\n", n, PAD) = malloc(sizeof(*required %d PAD %d\n", n, PAD))); */
225
		nbp = allocb(n);
226
		nbp->wptr = nbp->lim;
227
		nbp->rptr = nbp->wptr - n;
228
		nbp->next = bp;
229
		return nbp;
230
	}
231
} 
232
 
233
Block *
234
btrim(Block *bp, int offset, int len)
235
{
236
	ulong l;
237
	Block *nb, *startb;
238
 
239
	if(blen(bp) < offset+len) {
240
		freeb(bp);
241
		return nil;
242
	}
243
 
244
	while((l = BLEN(bp)) < offset) {
245
		offset -= l;
246
		nb = bp->next;
247
		bp->next = nil;
248
		freeb(bp);
249
		bp = nb;
250
	}
251
 
252
	startb = bp;
253
	bp->rptr += offset;
254
 
255
	while((l = BLEN(bp)) < len) {
256
		len -= l;
257
		bp = bp->next;
258
	}
259
 
260
	bp->wptr -= (BLEN(bp) - len);
261
	bp->flags |= S_DELIM;
262
 
263
	if(bp->next) {
264
		freeb(bp->next);
265
		bp->next = nil;
266
	}
267
 
268
	return startb;
269
}
270
 
271
Block*
272
copyb(Block *bp, int count)
273
{
274
	int l;
275
	Block *nb, *head, **p;
276
 
277
	p = &head;
278
	head = nil;
279
	while(bp != nil && count != 0) {
280
		l = BLEN(bp);
281
		if(count < l)
282
			l = count;
283
		nb = allocb(l);
284
		memmove(nb->wptr, bp->rptr, l);
285
		nb->wptr += l;
286
		count -= l;
287
		nb->flags = bp->flags;
288
		*p = nb;
289
		p = &nb->next;
290
		bp = bp->next;
291
	}
292
	if(count) {
293
		nb = allocb(count);
294
		memset(nb->wptr, 0, count);
295
		nb->wptr += count;
296
		nb->flags |= S_DELIM;
297
		*p = nb;
298
	}
299
	if(blen(head) == 0)
300
		fprint(2, "copyb: zero length\n");
301
 
302
	return head;
303
}
304
 
305
int
306
pullb(Block **bph, int count)
307
{
308
	Block *bp;
309
	int n, uchars;
310
 
311
	uchars = 0;
312
	if(bph == nil)
313
		return 0;
314
 
315
	while(*bph != nil && count != 0) {
316
		bp = *bph;
317
		n = BLEN(bp);
318
		if(count < n)
319
			n = count;
320
		uchars += n;
321
		count -= n;
322
		bp->rptr += n;
323
		if(BLEN(bp) == 0) {
324
			*bph = bp->next;
325
			bp->next = nil;
326
			freeb(bp);
327
		}
328
	}
329
	return uchars;
330
}
331
 
332
/*
333
 *  handy routines for keeping track of allocations
334
 */
335
static ulong
336
callerpc(void *a)
337
{
338
	return ((ulong*)a)[-1];
339
}
340
static void
341
aref(Aref *ap, ulong pc)
342
{
343
	Arefent *a, *e;
344
 
345
	e = &ap->tab[Npc-1];
346
	qlock(ap);
347
	for(a = ap->tab; a < e; a++)
348
		if(a->pc == pc || a->pc == 0)
349
			break;
350
	a->pc = pc;
351
	a->n++;
352
	qunlock(ap);
353
}
354
static void
355
aunref(Aref *ap, ulong pc)
356
{
357
	Arefent *a, *e;
358
 
359
	e = &ap->tab[Npc-1];
360
	qlock(ap);
361
	for(a = ap->tab; a < e; a++)
362
		if(a->pc == pc || a->pc == 0)
363
			break;
364
	a->n--;
365
	qunlock(ap);
366
}