Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

/*
 * 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);
}