diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-01-26 17:25:23 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-01-26 17:25:23 +0100 |
commit | 7592fa3e68f6f42510a5a4f72c4d18c4a1879d1f (patch) | |
tree | 3868f86b96f3b66d7e61f735b6f2bd630b074b0a /sys/src/9/port/ucalloc.c | |
parent | 14d663b1695df1144ee19b6481f9c68bb8be21b2 (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.c | 137 |
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); +} |