ultimatepp/uppdev/Malloc/Small2.cpp
cxl 351994a6cc Adding uppdev....
git-svn-id: svn://ultimatepp.org/upp/trunk@328 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2008-08-15 08:36:24 +00:00

159 lines
3.2 KiB
C++

#include "Malloc.h"
#ifdef V2
#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)
{
// RTIMING("Format");
LOG("Formatting " << (void *)this << " to " << k);
klass = k;
sz = Ksz(k);
count = sKount[k];
ASSERT(count == (4096 - HEADERSZ) / sz);
active = 0;
free = Begin() + sFreem[k];
ASSERT(free == Begin() + count * sz - sz);
freelist = NULL;
#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]->LinkSelf();
full[i]->LinkSelf();
work[i]->LinkSelf();
work[i]->freelist = NULL;
work[i]->free = (byte *)work[i];
work[i]->klass = i;
}
emptypages = 0;
}
inline void *MSmall::AllocK(int k)
{
LOG("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->free > page->Begin()) { // Try swapping with freelist
void *p = page->free;
page->free -= page->sz;
++page->active;
return p;
}
if(page->next != page) {
page->active = 255;
page->Unlink();
page->Link(full[k]);
page = work[k]->next;
}
else {
page = empty[k]->next;
if(page->next == page) {
if(emptypages) {
emptypages--;
for(int i = 0; i < 16; i++) { // try inverse direction
page = empty[i]->next;
if(page->next != page) {
page->Unlink();
break;
}
}
ASSERT(page->next != page);
}
else // remote delete should be here!
page = (Page *)AllocRaw4KB();
page->Format(k);
ASSERT(page->klass == k);
}
else {
ASSERT(emptypages > 0);
page->Unlink();
emptypages--;
ASSERT(page->klass == k);
}
page->Link(work[k]);
ASSERT(page->klass == k);
}
}
}
inline void MSmall::FreeK(void *ptr, Page *page, int k)
{
((FreeLink *)ptr)->next = page->freelist;
page->freelist = (FreeLink *)ptr;
if(--page->active == 254) {
page->active = page->count - 1;
page->Unlink();
page->Link(work[k]);
}
else
if(page->active == 0) {
page->Unlink();
page->Link(empty[k]);
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