ref: f801657f77f3923ec2388c25bdcb036c8019ba89
dir: /alloc.c/
#include <u.h>
#include "dat.h"
#include "fns.h"
#include "mem.h"
#include "debug.h"
#include "libkern/kern.h"
#define CMEMSIZE DATASIZE
#define BHDR_MAGIC 0xcafebafe
#define BHDR_POISON 0xdeadbeef
#define BPTR(h) ((void *)((ulong)h + sizeof(Bhdr)))
#define BHDR(p) ((Bhdr *)((ulong)p - sizeof(Bhdr)))
#define BNEXT(h) ((Bhdr *)((ulong)h + sizeof(Bhdr) + h->size))
enum {
Bfree = 0,
Balloc,
};
typedef struct Bhdr {
ulong magic;
ulong size;
int tp;
Lock l;
} Bhdr;
#define first ((Bhdr*) DATASADDR)
void
allocinit()
{
first->magic = BHDR_MAGIC;
first->size = DATASIZE - sizeof(Bhdr);
first->tp = Bfree;
memset(&first->l, 0, sizeof(Lock));
memset(BPTR(first), 0, first->size);
}
void
allocdump()
{
int s = splhi();
for(Bhdr *hdr = first; ((ulong)hdr - (ulong)first) < CMEMSIZE; hdr = BNEXT(hdr)) {
if(hdr->magic != BHDR_MAGIC)
print("corrupt: ");
print("alloc: BPTR(hdr) 0x%08x BNEXT(hdr) 0x%08x hdr->size %ud\n", BPTR(hdr), BNEXT(hdr), hdr->size);
}
splx(s);
}
Bhdr*
cmfindsmallest(ulong size)
{
Bhdr *t = nil;
DBGALLOC print("alloc: finding %uld size block\n", size);
for(Bhdr *hdr = first; ((ulong)hdr - (ulong)first) < CMEMSIZE;
hdr = BNEXT(hdr)) {
DBGALLOC print("alloc: checking block with size %uld\n", hdr->size);
if(hdr->magic != BHDR_MAGIC) {
allocdump();
panic("block at 0x%08ux has bad magic number 0x%08ux\n", hdr, hdr->magic);
}
if(hdr->size < size || hdr->tp == Balloc)
continue;
if(hdr->size >= size && t == nil)
t = hdr;
if(hdr->size >= size && hdr->size < t->size)
t = hdr;
}
DBGALLOC print("alloc: block selected\n");
return t;
}
void*
mallocz(ulong size, int clr)
{
if(size % 8 != 0)
size = size + 8 - (size % 8);
lock(&first->l);
Bhdr* ohdr;
Bhdr* hdr = cmfindsmallest(size);
ulong osize;
void *ptr;
if(hdr == nil)
return nil;
// lock(&hdr->l);
// allocate block
DBGALLOC print("alloc: allocating block of %uld\n", size);
osize = hdr->size;
hdr->tp = Balloc;
hdr->size = size;
ohdr = hdr;
ptr = BPTR(hdr);
// create next block
DBGALLOC print("alloc: creating next block 0x%08x\n", (uint)BNEXT(hdr));
if((ulong)BNEXT(hdr) < ((ulong)first + CMEMSIZE - sizeof(Bhdr)) &&
BNEXT(hdr)->magic != BHDR_MAGIC) {
hdr = BNEXT(hdr);
hdr->magic = BHDR_MAGIC;
hdr->tp = Bfree;
hdr->size = osize - size - sizeof(Bhdr);
memset(&hdr->l, 0, sizeof(Lock));
DBGALLOC print("alloc: created next block of size %uld\n", hdr->size);
}
// unlock(&ohdr->l);
unlock(&first->l);
// return pointer
DBGALLOC print("alloc: finished; memset and return\n");
if(clr)
memset(ptr, 0, size);
return ptr;
}
void*
malloc(ulong size)
{
return mallocz(size, 1);
}
void*
smalloc(ulong size)
{
void *ptr;
while((ptr = malloc(size)) == nil)
_wait(100);
return ptr;
}
void
free(void *ptr)
{
Bhdr *hdr = nil;
Bhdr *c = nil;
// first pass: find and free the block
DBGALLOC print("alloc: free'ing block\n");
hdr = BHDR(ptr);
if(hdr == nil)
return;
lock(&first->l);
// lock(&hdr->l);
hdr->tp = Bfree;
memset(ptr, 0, hdr->size);
// second pass: coalesce with the next block
DBGALLOC print("alloc: coalesce with next block\n");
if((ulong)BNEXT(hdr) < (ulong)first + CMEMSIZE) {
c = BNEXT(hdr);
// lock(&c->l);
if(c->tp == Bfree) {
c->magic = BHDR_POISON;
hdr->size = hdr->size + c->size + sizeof(Bhdr);
}
// unlock(&c->l);
}
// third pass: coalesce with the previous block
DBGALLOC print("alloc: coalesce with previous block\n");
c = nil;
for(Bhdr *t = first; (ulong)t - (ulong)first < CMEMSIZE && c == nil;
t = BNEXT(t))
if(t != hdr) {
// lock(&t->l);
if(BNEXT(t) < first + CMEMSIZE && BNEXT(t) == hdr && t->tp == Bfree) {
c = t;
// unlock(&t->l);
break;
}
// unlock(&t->l);
}
if(c != nil) {
// lock(&c->l);
c->size = c->size + hdr->size + sizeof(Bhdr);
hdr->magic = BHDR_POISON;
// unlock(&c->l);
}
// free is done; return
// unlock(&hdr->l);
unlock(&first->l);
DBGALLOC print("alloc: updating size to %uld\n", c->size);
}
void*
realloc(void *ptr, ulong size)
{
Bhdr *hdr = nil;
void *nptr;
hdr = BHDR(ptr);
if(hdr == nil)
return nil;
// lock(&first->l);
// lock(&hdr->l);
// first pass: see if the block is extendable
// TODO
// second pass: find a new block
nptr = malloc(size);
if(nptr == nil)
return nil;
if(hdr->size < size)
size = hdr->size;
memcpy(nptr, BPTR(hdr), size);
// unlock(&hdr->l);
// unlock(&first->l);
free(ptr);
return nptr;
}
/* maximizing memory usage */
/* a noop; should be an overhead for the STM; implementing
it is coalescing with the next block */
ulong
msize(void *ptr)
{
Bhdr *hdr = nil;
void *t_ptr;
DBGALLOC print("alloc: msizing'ing block\n");
hdr = BHDR(ptr);
if(hdr == nil)
return 0;
return hdr->size;
}
/* memory allocation tracing off */
enum {
Npadlong = 2,
MallocOffset = 0,
ReallocOffset = 1
};
void
setmalloctag(void *v, ulong pc)
{
return;
}
ulong
getmalloctag(void *v)
{
return ~0;
}
void
setrealloctag(void *v, ulong pc)
{
return;
}
ulong
getrealloctag(void *v)
{
return ~0;
}