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));
177 tsleep(&up->sleep, return0, 0, 100);
180 v = (ulong*)v+Npadlong;
181 setmalloctag(v, getcallerpc(&size));
192 v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
196 v = (ulong*)v+Npadlong;
197 setmalloctag(v, getcallerpc(&size));
205 mallocz(ulong size, int clr)
209 v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
210 if(Npadlong && v != nil){
211 v = (ulong*)v+Npadlong;
212 setmalloctag(v, getcallerpc(&size));
221 mallocalign(ulong size, ulong align, long offset, ulong span)
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));
240 poolfree(mainmem, (ulong*)v-Npadlong);
244 realloc(void *v, ulong size)
249 v = (ulong*)v-Npadlong;
250 if(Npadlong !=0 && size != 0)
251 size += Npadlong*sizeof(ulong);
253 if(nv = poolrealloc(mainmem, v, size)){
254 nv = (ulong*)nv+Npadlong;
255 setrealloctag(nv, getcallerpc(&v));
257 setmalloctag(nv, getcallerpc(&v));
265 return poolmsize(mainmem, (ulong*)v-Npadlong)-Npadlong*sizeof(ulong);
269 calloc(ulong n, ulong szelem)
272 if(v = mallocz(n*szelem, 1))
273 setmalloctag(v, getcallerpc(&n));
278 setmalloctag(void *v, ulong pc)
282 if(Npadlong <= MallocOffset || v == nil)
285 u[-Npadlong+MallocOffset] = pc;
289 setrealloctag(void *v, ulong pc)
293 if(Npadlong <= ReallocOffset || v == nil)
296 u[-Npadlong+ReallocOffset] = pc;
300 getmalloctag(void *v)
303 if(Npadlong <= MallocOffset)
305 return ((ulong*)v)[-Npadlong+MallocOffset];
309 getrealloctag(void *v)
312 if(Npadlong <= ReallocOffset)
313 return ((ulong*)v)[-Npadlong+ReallocOffset];