summaryrefslogtreecommitdiff
path: root/sys/src/9/port/alloc.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /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-xsys/src/9/port/alloc.c315
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;
+}