2 #include "../port/lib.h"
9 static void poolprint(Pool*, char*, ...);
10 static void ppanic(Pool*, char*, ...);
11 static void plock(Pool*);
12 static void punlock(Pool*);
14 typedef struct Private Private;
17 char msg[256]; /* a rock for messages to be printed at unlock */
20 static Private pmainpriv;
21 static Pool pmainmem = {
23 .maxsize= 4*1024*1024,
28 .flags= POOL_TOLERANCE,
38 static Private pimagpriv;
39 static Pool pimagmem = {
41 .maxsize= 16*1024*1024,
42 .minarena= 2*1024*1024,
56 Pool* mainmem = &pmainmem;
57 Pool* imagmem = &pimagmem;
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.
64 poolprint(Pool *p, char *fmt, ...)
71 vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
76 ppanic(Pool *p, char *fmt, ...)
80 char msg[sizeof pv->msg];
84 vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
86 memmove(msg, pv->msg, sizeof msg);
98 pv->lk.pc = getcallerpc(&p);
106 char msg[sizeof pv->msg];
114 memmove(msg, pv->msg, sizeof msg);
116 iprint("%.*s", sizeof pv->msg, msg);
122 print("%s max %lud cur %lud free %lud alloc %lud\n", p->name,
123 p->maxsize, p->cursize, p->curfree, p->curalloc);
129 poolsummary(mainmem);
130 poolsummary(imagmem);
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. */
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.
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.
174 v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
183 v = (ulong*)v+Npadlong;
184 setmalloctag(v, getcallerpc(&size));
195 v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
199 v = (ulong*)v+Npadlong;
200 setmalloctag(v, getcallerpc(&size));
208 mallocz(ulong size, int clr)
212 v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
213 if(Npadlong && v != nil){
214 v = (ulong*)v+Npadlong;
215 setmalloctag(v, getcallerpc(&size));
224 mallocalign(ulong size, ulong align, long offset, ulong span)
228 v = poolallocalign(mainmem, size+Npadlong*sizeof(ulong), align, offset-Npadlong*sizeof(ulong), span);
229 if(Npadlong && v != nil){
230 v = (ulong*)v+Npadlong;
231 setmalloctag(v, getcallerpc(&size));
243 poolfree(mainmem, (ulong*)v-Npadlong);
247 realloc(void *v, ulong size)
252 v = (ulong*)v-Npadlong;
253 if(Npadlong !=0 && size != 0)
254 size += Npadlong*sizeof(ulong);
256 if(nv = poolrealloc(mainmem, v, size)){
257 nv = (ulong*)nv+Npadlong;
258 setrealloctag(nv, getcallerpc(&v));
260 setmalloctag(nv, getcallerpc(&v));
268 return poolmsize(mainmem, (ulong*)v-Npadlong)-Npadlong*sizeof(ulong);
272 calloc(ulong n, ulong szelem)
275 if(v = mallocz(n*szelem, 1))
276 setmalloctag(v, getcallerpc(&n));
281 setmalloctag(void *v, ulong pc)
285 if(Npadlong <= MallocOffset || v == nil)
288 u[-Npadlong+MallocOffset] = pc;
292 setrealloctag(void *v, ulong pc)
296 if(Npadlong <= ReallocOffset || v == nil)
299 u[-Npadlong+ReallocOffset] = pc;
303 getmalloctag(void *v)
306 if(Npadlong <= MallocOffset)
308 return ((ulong*)v)[-Npadlong+MallocOffset];
312 getrealloctag(void *v)
315 if(Npadlong <= ReallocOffset)
316 return ((ulong*)v)[-Npadlong+ReallocOffset];