ultimatepp/uppdev/Malloc/Malloc4.cpp
cxl 2e4b276e07 Merge continued
git-svn-id: svn://ultimatepp.org/upp/trunk@10263 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2016-10-04 08:34:39 +00:00

160 lines
3.1 KiB
C++

#include "Malloc.h"
#ifdef V4
#define ATIMING(x)
#define sHeapStat(k)
#define FreeFill(p, c)
#define CheckFree(p, k) p
inline int Ksz(int k) { return (k + 1) << 4; }
static byte sKount[16];
static word sFreem[16];
inline void MSmall::Page::Format(int k)
{
LOG("Formatting " << (void *)this << " to " << k);
klass = k;
sz = Ksz(k);
count = sKount[k];
ASSERT(count == (4096 - HEADERSZ) / sz);
// freecount = count;
active = 0;
byte *ptr = Begin();
byte *end = (byte *)this + 4096;
FreeLink *l = NULL;
while(ptr < end) {
((FreeLink *)ptr)->next = l;
l = (FreeLink *)ptr;
ptr += sz;
}
freelist = l;
#ifdef HEAPDBG
FreeFill((dword *)Begin(), (4096 - HEADERSZ) / 4);
#endif
}
void MSmall::Init()
{
for(int i = 0; i < 16; i++) {
int sz = Ksz(i);
sKount[i] = (4096 - HEADERSZ) / sz;
sFreem[i] = sKount[i] * sz - sz;
}
for(int i = 0; i < 16; i++) {
empty[i] = NULL;
full[i]->LinkSelf();
work[i]->LinkSelf();
work[i]->freelist = NULL;
work[i]->klass = i;
}
emptypages = 0;
}
inline void *MSmall::AllocK(int k)
{
Page *page = work[k]->next;
for(;;) {
ASSERT(page->klass == k);
FreeLink *p = page->freelist;
if(p) {
page->freelist = p->next;
++page->active;
return p;
}
if(page->next != page) {
ATIMING("NextWork");
page->Unlink();
page->Link(full[k]);
page = work[k]->next;
}
else {
page = empty[k];
if(!page) {
if(emptypages) {
ATIMING("FromEmpty other");
emptypages--;
for(int i = 0; i < 16; i++) { // try inverse direction
if(empty[i]) {
page = empty[i];
empty[i] = page->next;
break;
}
}
ASSERT(page);
}
else // remote delete should be here!
page = (Page *)AllocRaw4KB();
page->Format(k);
ASSERT(page->klass == k);
}
else {
ATIMING("FromEmpty");
ASSERT(emptypages > 0);
empty[k] = page->next;
emptypages--;
ASSERT(page->klass == k);
}
page->Link(work[k]);
ASSERT(page->klass == k);
}
}
}
inline void MSmall::FreeK(void *ptr, Page *page, int k)
{
if(page->freelist)
((FreeLink *)ptr)->next = page->freelist;
else {
page->Unlink();
page->Link(work[k]);
}
page->freelist = (FreeLink *)ptr;
if(--page->active == 0) {
ATIMING("ToEmpty");
page->Unlink();
page->next = empty[k];
empty[k] = page;
emptypages++;
return;
}
}
void *MSmall::Alloc(size_t sz)
{
if(sz <= 256) {
ATIMING("Small alloc");
int k = ((int)sz + (sz == 0) - 1) >> 4;
sHeapStat(k);
return CheckFree(AllocK(k), k);
}
NEVER();
return NULL;
// return LAlloc(sz);
}
void MSmall::Free(void *ptr)
{
if(!ptr) return;
if(((dword)(uintptr_t)ptr) & 8)
NEVER();
// LFree(ptr);
else {
ATIMING("Small free");
Page *page = (Page *)((uintptr_t)ptr & ~(uintptr_t)4095);
int k = page->klass;
ASSERT((((uintptr_t)ptr & (uintptr_t)4095) - HEADERSZ) % Ksz(k & 15) == 0);
#ifdef HEAPDBG
#ifdef CPU_64
FreeFill((dword *)ptr + 2, (Ksz(k & 15) >> 2) - 2);
#else
FreeFill((dword *)ptr + 1, (Ksz(k & 15) >> 2) - 1);
#endif
#endif
FreeK(ptr, page, k);
}
}
#endif