diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/9/port/alloc.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/9/port/alloc.c')
-rwxr-xr-x | sys/src/9/port/alloc.c | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/sys/src/9/port/alloc.c b/sys/src/9/port/alloc.c new file mode 100755 index 000000000..ed9797967 --- /dev/null +++ b/sys/src/9/port/alloc.c @@ -0,0 +1,315 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "error.h" +#include <pool.h> + +static void poolprint(Pool*, char*, ...); +static void ppanic(Pool*, char*, ...); +static void plock(Pool*); +static void punlock(Pool*); + +typedef struct Private Private; +struct Private { + Lock lk; + char msg[256]; /* a rock for messages to be printed at unlock */ +}; + +static Private pmainpriv; +static Pool pmainmem = { + .name= "Main", + .maxsize= 4*1024*1024, + .minarena= 128*1024, + .quantum= 32, + .alloc= xalloc, + .merge= xmerge, + .flags= POOL_TOLERANCE, + + .lock= plock, + .unlock= punlock, + .print= poolprint, + .panic= ppanic, + + .private= &pmainpriv, +}; + +static Private pimagpriv; +static Pool pimagmem = { + .name= "Image", + .maxsize= 16*1024*1024, + .minarena= 2*1024*1024, + .quantum= 32, + .alloc= xalloc, + .merge= xmerge, + .flags= 0, + + .lock= plock, + .unlock= punlock, + .print= poolprint, + .panic= ppanic, + + .private= &pimagpriv, +}; + +Pool* mainmem = &pmainmem; +Pool* imagmem = &pimagmem; + +/* + * because we can't print while we're holding the locks, + * we have the save the message and print it once we let go. + */ +static void +poolprint(Pool *p, char *fmt, ...) +{ + va_list v; + Private *pv; + + pv = p->private; + va_start(v, fmt); + vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v); + va_end(v); +} + +static void +ppanic(Pool *p, char *fmt, ...) +{ + va_list v; + Private *pv; + char msg[sizeof pv->msg]; + + pv = p->private; + va_start(v, fmt); + vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v); + va_end(v); + memmove(msg, pv->msg, sizeof msg); + iunlock(&pv->lk); + panic("%s", msg); +} + +static void +plock(Pool *p) +{ + Private *pv; + + pv = p->private; + ilock(&pv->lk); + pv->lk.pc = getcallerpc(&p); + pv->msg[0] = 0; +} + +static void +punlock(Pool *p) +{ + Private *pv; + char msg[sizeof pv->msg]; + + pv = p->private; + if(pv->msg[0] == 0){ + iunlock(&pv->lk); + return; + } + + memmove(msg, pv->msg, sizeof msg); + iunlock(&pv->lk); + iprint("%.*s", sizeof pv->msg, msg); +} + +void +poolsummary(Pool *p) +{ + print("%s max %lud cur %lud free %lud alloc %lud\n", p->name, + p->maxsize, p->cursize, p->curfree, p->curalloc); +} + +void +mallocsummary(void) +{ + poolsummary(mainmem); + poolsummary(imagmem); +} + +/* everything from here down should be the same in libc, libdebugmalloc, and the kernel */ +/* - except the code for malloc(), which alternately doesn't clear or does. */ +/* - except the code for smalloc(), which lives only in the kernel. */ + +/* + * Npadlong is the number of 32-bit longs to leave at the beginning of + * each allocated buffer for our own bookkeeping. We return to the callers + * a pointer that points immediately after our bookkeeping area. Incoming pointers + * must be decremented by that much, and outgoing pointers incremented. + * The malloc tag is stored at MallocOffset from the beginning of the block, + * and the realloc tag at ReallocOffset. The offsets are from the true beginning + * of the block, not the beginning the caller sees. + * + * The extra if(Npadlong != 0) in various places is a hint for the compiler to + * compile out function calls that would otherwise be no-ops. + */ + +/* non tracing + * +enum { + Npadlong = 0, + MallocOffset = 0, + ReallocOffset = 0, +}; + * + */ + +/* tracing */ +enum { + Npadlong = 2, + MallocOffset = 0, + ReallocOffset = 1 +}; + + +void* +smalloc(ulong size) +{ + void *v; + + for(;;) { + v = poolalloc(mainmem, size+Npadlong*sizeof(ulong)); + if(v != nil) + break; + tsleep(&up->sleep, return0, 0, 100); + } + if(Npadlong){ + v = (ulong*)v+Npadlong; + setmalloctag(v, getcallerpc(&size)); + } + memset(v, 0, size); + return v; +} + +void* +malloc(ulong size) +{ + void *v; + + v = poolalloc(mainmem, size+Npadlong*sizeof(ulong)); + if(v == nil) + return nil; + if(Npadlong){ + v = (ulong*)v+Npadlong; + setmalloctag(v, getcallerpc(&size)); + setrealloctag(v, 0); + } + memset(v, 0, size); + return v; +} + +void* +mallocz(ulong size, int clr) +{ + void *v; + + v = poolalloc(mainmem, size+Npadlong*sizeof(ulong)); + if(Npadlong && v != nil){ + v = (ulong*)v+Npadlong; + setmalloctag(v, getcallerpc(&size)); + setrealloctag(v, 0); + } + if(clr && v != nil) + memset(v, 0, size); + return v; +} + +void* +mallocalign(ulong size, ulong align, long offset, ulong span) +{ + void *v; + + v = poolallocalign(mainmem, size+Npadlong*sizeof(ulong), align, offset-Npadlong*sizeof(ulong), span); + if(Npadlong && v != nil){ + v = (ulong*)v+Npadlong; + setmalloctag(v, getcallerpc(&size)); + setrealloctag(v, 0); + } + if(v) + memset(v, 0, size); + return v; +} + +void +free(void *v) +{ + if(v != nil) + poolfree(mainmem, (ulong*)v-Npadlong); +} + +void* +realloc(void *v, ulong size) +{ + void *nv; + + if(v != nil) + v = (ulong*)v-Npadlong; + if(Npadlong !=0 && size != 0) + size += Npadlong*sizeof(ulong); + + if(nv = poolrealloc(mainmem, v, size)){ + nv = (ulong*)nv+Npadlong; + setrealloctag(nv, getcallerpc(&v)); + if(v == nil) + setmalloctag(nv, getcallerpc(&v)); + } + return nv; +} + +ulong +msize(void *v) +{ + return poolmsize(mainmem, (ulong*)v-Npadlong)-Npadlong*sizeof(ulong); +} + +void* +calloc(ulong n, ulong szelem) +{ + void *v; + if(v = mallocz(n*szelem, 1)) + setmalloctag(v, getcallerpc(&n)); + return v; +} + +void +setmalloctag(void *v, ulong pc) +{ + ulong *u; + USED(v, pc); + if(Npadlong <= MallocOffset || v == nil) + return; + u = v; + u[-Npadlong+MallocOffset] = pc; +} + +void +setrealloctag(void *v, ulong pc) +{ + ulong *u; + USED(v, pc); + if(Npadlong <= ReallocOffset || v == nil) + return; + u = v; + u[-Npadlong+ReallocOffset] = pc; +} + +ulong +getmalloctag(void *v) +{ + USED(v); + if(Npadlong <= MallocOffset) + return ~0; + return ((ulong*)v)[-Npadlong+MallocOffset]; +} + +ulong +getrealloctag(void *v) +{ + USED(v); + if(Npadlong <= ReallocOffset) + return ((ulong*)v)[-Npadlong+ReallocOffset]; + return ~0; +} |