#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"/* * Allocate memory for use in kernel bitblts. * The allocated memory must have a flushed instruction * cache, and the data cache must be flushed by bbdflush(). * To avoid the need for frequent cache flushes, the memory * is allocated out of an arena, and the i-cache is only * flushed when it has to be reused. By returning an * address in non-cached space, the need for flushing the * d-cache is avoided. * * This code will have to be interlocked if we ever get * a multiprocessor with a bitmapped display. *//* a 0->3 bitblt can take 800 longs */enum { narena=2, /* put interrupt time stuff in separate arena */ nbbarena=4096 /* number of words in an arena */};static ulong bbarena[narena][nbbarena];static ulong *bbcur[narena] = {&bbarena[0][0], &bbarena[1][0]};static ulong *bblast[narena] = {0, 0};#define INTLEVEL(v) ((v)&0x700)extern flushvirtpage(void (*)(void));void *bbmalloc(int nbytes){ int nw, a; int s; ulong *ans; nw = nbytes/sizeof(long); s = splhi(); a = INTLEVEL(s)? 1 : 0; if(bbcur[a] + nw > &bbarena[a][nbbarena]) ans = bbarena[a]; else ans = bbcur[a]; bbcur[a] = ans + nw; splx(s); bblast[a] = ans; return ans;}voidbbfree(void *p, int n){ int a, s; s = splhi(); a = INTLEVEL(s)? 1 : 0; if(p == bblast[a]) bbcur[a] = (ulong *)(((char *)bblast[a]) + n); splx(s);}voidbbdflush(void *p, int n){ ulong pe, l; pe = (ulong)(((char *)p) + n + (BY2PG-1)); for(l = (ulong)p; l < pe; l += BY2PG) flushpage(l);}intbbonstack(void){ if(u) return 1; return 0;}voidbbexec(void (*memstart)(void), int len, int onstack){ if(onstack) { flushvirtpage(memstart); memstart(); } else { bbdflush(memstart, len); memstart(); bbfree(memstart, len); }}
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
/*
* Allocate memory for use in kernel bitblts.
* The allocated memory must have a flushed instruction
* cache, and the data cache must be flushed by bbdflush().
* To avoid the need for frequent cache flushes, the memory
* is allocated out of an arena, and the i-cache is only
* flushed when it has to be reused. By returning an
* address in non-cached space, the need for flushing the
* d-cache is avoided.
*
* This code will have to be interlocked if we ever get
* a multiprocessor with a bitmapped display.
*/
/* a 0->3 bitblt can take 800 longs */
enum {
narena=2, /* put interrupt time stuff in separate arena */
nbbarena=4096 /* number of words in an arena */
};
static ulong bbarena[narena][nbbarena];
static ulong *bbcur[narena] = {&bbarena[0][0], &bbarena[1][0]};
static ulong *bblast[narena] = {0, 0};
#define INTLEVEL(v) ((v)&0x700)
extern flushvirtpage(void (*)(void));
void *
bbmalloc(int nbytes)
{
int nw, a;
int s;
ulong *ans;
nw = nbytes/sizeof(long);
s = splhi();
a = INTLEVEL(s)? 1 : 0;
if(bbcur[a] + nw > &bbarena[a][nbbarena])
ans = bbarena[a];
else
ans = bbcur[a];
bbcur[a] = ans + nw;
splx(s);
bblast[a] = ans;
return ans;
}
void
bbfree(void *p, int n)
{
int a, s;
s = splhi();
a = INTLEVEL(s)? 1 : 0;
if(p == bblast[a])
bbcur[a] = (ulong *)(((char *)bblast[a]) + n);
splx(s);
}
void
bbdflush(void *p, int n)
{
ulong pe, l;
pe = (ulong)(((char *)p) + n + (BY2PG-1));
for(l = (ulong)p; l < pe; l += BY2PG)
flushpage(l);
}
int
bbonstack(void)
{
if(u)
return 1;
return 0;
}
void
bbexec(void (*memstart)(void), int len, int onstack)
{
if(onstack) {
flushvirtpage(memstart);
memstart();
} else {
bbdflush(memstart, len);
memstart();
bbfree(memstart, len);
}
}