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; }