summaryrefslogtreecommitdiff
path: root/sys/src/9/port/ucalloc.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-01-26 17:25:23 +0100
committercinap_lenrek <cinap_lenrek@gmx.de>2013-01-26 17:25:23 +0100
commit7592fa3e68f6f42510a5a4f72c4d18c4a1879d1f (patch)
tree3868f86b96f3b66d7e61f735b6f2bd630b074b0a /sys/src/9/port/ucalloc.c
parent14d663b1695df1144ee19b6481f9c68bb8be21b2 (diff)
kernel: add portable uncached memory allocator (ucalloc) (from sources)
Diffstat (limited to 'sys/src/9/port/ucalloc.c')
-rw-r--r--sys/src/9/port/ucalloc.c137
1 files changed, 137 insertions, 0 deletions
diff --git a/sys/src/9/port/ucalloc.c b/sys/src/9/port/ucalloc.c
new file mode 100644
index 000000000..625553fe2
--- /dev/null
+++ b/sys/src/9/port/ucalloc.c
@@ -0,0 +1,137 @@
+/*
+ * allocate uncached memory
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#include <pool.h>
+
+typedef struct Private Private;
+struct Private {
+ Lock;
+ char msg[256];
+ char* cur;
+};
+
+static Private ucprivate;
+
+static void
+ucpoolpanic(Pool* p, char* fmt, ...)
+{
+ va_list v;
+ Private *pv;
+ char msg[sizeof pv->msg];
+
+ pv = p->private;
+ va_start(v, fmt);
+ vseprint(pv->cur, &pv->msg[sizeof pv->msg], fmt, v);
+ va_end(v);
+ memmove(msg, pv->msg, sizeof msg);
+ iunlock(pv);
+ panic("%s", msg);
+}
+
+static void
+ucpoolprint(Pool* p, char* fmt, ...)
+{
+ va_list v;
+ Private *pv;
+
+ pv = p->private;
+ va_start(v, fmt);
+ pv->cur = vseprint(pv->cur, &pv->msg[sizeof pv->msg], fmt, v);
+ va_end(v);
+}
+
+static void
+ucpoolunlock(Pool* p)
+{
+ Private *pv;
+ char msg[sizeof pv->msg];
+
+ pv = p->private;
+ if(pv->cur == pv->msg){
+ iunlock(pv);
+ return;
+ }
+
+ memmove(msg, pv->msg, sizeof msg);
+ pv->cur = pv->msg;
+ iunlock(pv);
+
+ iprint("%.*s", sizeof pv->msg, msg);
+}
+
+static void
+ucpoollock(Pool* p)
+{
+ Private *pv;
+
+ pv = p->private;
+ ilock(pv);
+ pv->pc = getcallerpc(&p);
+ pv->cur = pv->msg;
+}
+
+static void*
+ucarena(usize size)
+{
+ void *uv, *v;
+
+ assert(size == 1*MiB);
+
+ mainmem->maxsize += 1*MiB;
+ if((v = mallocalign(1*MiB, 1*MiB, 0, 0)) == nil ||
+ (uv = mmuuncache(v, 1*MiB)) == nil){
+ free(v);
+ mainmem->maxsize -= 1*MiB;
+ return nil;
+ }
+ return uv;
+}
+
+static Pool ucpool = {
+ .name = "Uncached",
+ .maxsize = 4*MiB,
+ .minarena = 1*MiB-32,
+ .quantum = 32,
+ .alloc = ucarena,
+ .merge = nil,
+ .flags = /*POOL_TOLERANCE|POOL_ANTAGONISM|POOL_PARANOIA|*/0,
+
+ .lock = ucpoollock,
+ .unlock = ucpoolunlock,
+ .print = ucpoolprint,
+ .panic = ucpoolpanic,
+
+ .private = &ucprivate,
+};
+
+void
+ucfree(void* v)
+{
+ if(v == nil)
+ return;
+ poolfree(&ucpool, v);
+}
+
+void*
+ucallocalign(usize size, int align, int span)
+{
+ void *v;
+
+ assert(size < ucpool.minarena-128);
+ v = poolallocalign(&ucpool, size, align, 0, span);
+ if(v)
+ memset(v, 0, size);
+ return v;
+}
+
+void*
+ucalloc(usize size)
+{
+ return ucallocalign(size, 32, 0);
+}