Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	"u.h"
2
#include	"../port/lib.h"
3
#include	"mem.h"
4
#include	"dat.h"
5
#include	"fns.h"
6
#include	"error.h"
7
#include	<pool.h>
8
 
9
static void poolprint(Pool*, char*, ...);
10
static void ppanic(Pool*, char*, ...);
11
static void plock(Pool*);
12
static void punlock(Pool*);
13
 
14
typedef struct Private	Private;
15
struct Private {
16
	Lock		lk;
17
	char		msg[256];	/* a rock for messages to be printed at unlock */
18
};
19
 
20
static Private pmainpriv;
21
static Pool pmainmem = {
22
	.name=	"Main",
23
	.maxsize=	4*1024*1024,
24
	.minarena=	128*1024,
25
	.quantum=	32,
26
	.alloc=	xalloc,
27
	.merge=	xmerge,
28
	.flags=	POOL_TOLERANCE,
29
 
30
	.lock=	plock,
31
	.unlock=	punlock,
32
	.print=	poolprint,
33
	.panic=	ppanic,
34
 
35
	.private=	&pmainpriv,
36
};
37
 
38
static Private pimagpriv;
39
static Pool pimagmem = {
40
	.name=	"Image",
41
	.maxsize=	16*1024*1024,
42
	.minarena=	2*1024*1024,
43
	.quantum=	32,
44
	.alloc=	xalloc,
45
	.merge=	xmerge,
46
	.flags=	0,
47
 
48
	.lock=	plock,
49
	.unlock=	punlock,
50
	.print=	poolprint,
51
	.panic=	ppanic,
52
 
53
	.private=	&pimagpriv,
54
};
55
 
56
Pool*	mainmem = &pmainmem;
57
Pool*	imagmem = &pimagmem;
58
 
59
/*
60
 * because we can't print while we're holding the locks, 
61
 * we have the save the message and print it once we let go.
62
 */
63
static void
64
poolprint(Pool *p, char *fmt, ...)
65
{
66
	va_list v;
67
	Private *pv;
68
 
69
	pv = p->private;
70
	va_start(v, fmt);
71
	vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
72
	va_end(v);
73
}
74
 
75
static void
76
ppanic(Pool *p, char *fmt, ...)
77
{
78
	va_list v;
79
	Private *pv;
80
	char msg[sizeof pv->msg];
81
 
82
	pv = p->private;
83
	va_start(v, fmt);
84
	vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
85
	va_end(v);
86
	memmove(msg, pv->msg, sizeof msg);
87
	iunlock(&pv->lk);
88
	panic("%s", msg);
89
}
90
 
91
static void
92
plock(Pool *p)
93
{
94
	Private *pv;
95
 
96
	pv = p->private;
97
	ilock(&pv->lk);
98
	pv->lk.pc = getcallerpc(&p);
99
	pv->msg[0] = 0;
100
}
101
 
102
static void
103
punlock(Pool *p)
104
{
105
	Private *pv;
106
	char msg[sizeof pv->msg];
107
 
108
	pv = p->private;
109
	if(pv->msg[0] == 0){
110
		iunlock(&pv->lk);
111
		return;
112
	}
113
 
114
	memmove(msg, pv->msg, sizeof msg);
115
	iunlock(&pv->lk);
116
	iprint("%.*s", sizeof pv->msg, msg);
117
}
118
 
119
void
120
poolsummary(Pool *p)
121
{
122
	print("%s max %lud cur %lud free %lud alloc %lud\n", p->name,
123
		p->maxsize, p->cursize, p->curfree, p->curalloc);
124
}
125
 
126
void
127
mallocsummary(void)
128
{
129
	poolsummary(mainmem);
130
	poolsummary(imagmem);
131
}
132
 
133
/* everything from here down should be the same in libc, libdebugmalloc, and the kernel */
134
/* - except the code for malloc(), which alternately doesn't clear or does. */
135
/* - except the code for smalloc(), which lives only in the kernel. */
136
 
137
/*
138
 * Npadlong is the number of 32-bit longs to leave at the beginning of 
139
 * each allocated buffer for our own bookkeeping.  We return to the callers
140
 * a pointer that points immediately after our bookkeeping area.  Incoming pointers
141
 * must be decremented by that much, and outgoing pointers incremented.
142
 * The malloc tag is stored at MallocOffset from the beginning of the block,
143
 * and the realloc tag at ReallocOffset.  The offsets are from the true beginning
144
 * of the block, not the beginning the caller sees.
145
 *
146
 * The extra if(Npadlong != 0) in various places is a hint for the compiler to
147
 * compile out function calls that would otherwise be no-ops.
148
 */
149
 
150
/*	non tracing
151
 *
152
enum {
153
	Npadlong	= 0,
154
	MallocOffset = 0,
155
	ReallocOffset = 0,
156
};
157
 *
158
 */
159
 
160
/* tracing */
161
enum {
162
	Npadlong	= 2,
163
	MallocOffset = 0,
164
	ReallocOffset = 1
165
};
166
 
167
 
168
void*
169
smalloc(ulong size)
170
{
171
	void *v;
172
 
173
	for(;;) {
174
		v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
175
		if(v != nil)
176
			break;
177
		tsleep(&up->sleep, return0, 0, 100);
178
	}
179
	if(Npadlong){
180
		v = (ulong*)v+Npadlong;
181
		setmalloctag(v, getcallerpc(&size));
182
	}
183
	memset(v, 0, size);
184
	return v;
185
}
186
 
187
void*
188
malloc(ulong size)
189
{
190
	void *v;
191
 
192
	v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
193
	if(v == nil)
194
		return nil;
195
	if(Npadlong){
196
		v = (ulong*)v+Npadlong;
197
		setmalloctag(v, getcallerpc(&size));
198
		setrealloctag(v, 0);
199
	}
200
	memset(v, 0, size);
201
	return v;
202
}
203
 
204
void*
205
mallocz(ulong size, int clr)
206
{
207
	void *v;
208
 
209
	v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
210
	if(Npadlong && v != nil){
211
		v = (ulong*)v+Npadlong;
212
		setmalloctag(v, getcallerpc(&size));
213
		setrealloctag(v, 0);
214
	}
215
	if(clr && v != nil)
216
		memset(v, 0, size);
217
	return v;
218
}
219
 
220
void*
221
mallocalign(ulong size, ulong align, long offset, ulong span)
222
{
223
	void *v;
224
 
225
	v = poolallocalign(mainmem, size+Npadlong*sizeof(ulong), align, offset-Npadlong*sizeof(ulong), span);
226
	if(Npadlong && v != nil){
227
		v = (ulong*)v+Npadlong;
228
		setmalloctag(v, getcallerpc(&size));
229
		setrealloctag(v, 0);
230
	}
231
	if(v)
232
		memset(v, 0, size);
233
	return v;
234
}
235
 
236
void
237
free(void *v)
238
{
239
	if(v != nil)
240
		poolfree(mainmem, (ulong*)v-Npadlong);
241
}
242
 
243
void*
244
realloc(void *v, ulong size)
245
{
246
	void *nv;
247
 
248
	if(v != nil)
249
		v = (ulong*)v-Npadlong;
250
	if(Npadlong !=0 && size != 0)
251
		size += Npadlong*sizeof(ulong);
252
 
253
	if(nv = poolrealloc(mainmem, v, size)){
254
		nv = (ulong*)nv+Npadlong;
255
		setrealloctag(nv, getcallerpc(&v));
256
		if(v == nil)
257
			setmalloctag(nv, getcallerpc(&v));
258
	}		
259
	return nv;
260
}
261
 
262
ulong
263
msize(void *v)
264
{
265
	return poolmsize(mainmem, (ulong*)v-Npadlong)-Npadlong*sizeof(ulong);
266
}
267
 
268
void*
269
calloc(ulong n, ulong szelem)
270
{
271
	void *v;
272
	if(v = mallocz(n*szelem, 1))
273
		setmalloctag(v, getcallerpc(&n));
274
	return v;
275
}
276
 
277
void
278
setmalloctag(void *v, ulong pc)
279
{
280
	ulong *u;
281
	USED(v, pc);
282
	if(Npadlong <= MallocOffset || v == nil)
283
		return;
284
	u = v;
285
	u[-Npadlong+MallocOffset] = pc;
286
}
287
 
288
void
289
setrealloctag(void *v, ulong pc)
290
{
291
	ulong *u;
292
	USED(v, pc);
293
	if(Npadlong <= ReallocOffset || v == nil)
294
		return;
295
	u = v;
296
	u[-Npadlong+ReallocOffset] = pc;
297
}
298
 
299
ulong
300
getmalloctag(void *v)
301
{
302
	USED(v);
303
	if(Npadlong <= MallocOffset)
304
		return ~0;
305
	return ((ulong*)v)[-Npadlong+MallocOffset];
306
}
307
 
308
ulong
309
getrealloctag(void *v)
310
{
311
	USED(v);
312
	if(Npadlong <= ReallocOffset)
313
		return ((ulong*)v)[-Npadlong+ReallocOffset];
314
	return ~0;
315
}