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

203 lines
4.1 KiB
C++

#include "Malloc.h"
#define LTIMING(x) // RTIMING(x)
struct Link;
word Heap::BinSz[LBINS];
byte Heap::SzBin[MAXBLOCK / 8 + 1];
byte Heap::BlBin[MAXBLOCK / 8 + 1];
Heap::DLink Heap::allmedium;
Heap::DLink Heap::allbig;
void Heap::GlobalLInit()
{
ONCELOCK {
int p = 24;
int bi = 0;
while(p < MAXBLOCK) {
BinSz[bi++] = p;
int add = minmax(6 * p / 100 / 32 * 32, 32, 2048);
p += add;
}
ASSERT(bi == LBINS - 1);
BinSz[LBINS - 1] = MAXBLOCK;
int k = 0;
for(int i = 0; i < MAXBLOCK / 8; i++) {
while(i * 8 + 7 > BinSz[k])
k++;
SzBin[i] = k;
}
k = LBINS - 1;
for(int i = MAXBLOCK / 8; i >= 0; i--) {
while(i * 8 < BinSz[k]) k--;
BlBin[i] = k;
}
BlBin[0] = 0;
allmedium.LinkSelf();
allbig.LinkSelf();
}
}
void Heap::LInit()
{
ASSERT(sizeof(Header) == 8);
ASSERT(sizeof(DLink) <= 16);
GlobalLInit();
for(int i = 0; i < LBINS; i++)
freebin[i]->LinkSelf();
}
Heap::DLink *Heap::AddChunk()
{
Mutex::Lock __(global_lock);
DLink *ml = (DLink *)AllocRaw64KB();
if(!ml) return NULL;
ml->Link(&allmedium);
Header *bh = (Header *)((byte *)ml + 16);
bh->size = MAXBLOCK;
bh->prev = 0;
bh->free = true;
// bh->heap = this; //!!!!!
DLink *b = bh->GetBlock();
LinkFree(b, MAXBLOCK);
bh = bh->Next();
bh->prev = MAXBLOCK;
bh->size = 0;
bh->free = false;
return b;
}
void *Heap::DivideBlock(DLink *b, int size, int ii)
{
b->Unlink();
Header *bh = b->GetHeader();
ASSERT(bh->size >= size);
bh->free = false;
int sz2 = bh->size - size - sizeof(Header);
if(sz2 >= 32) {
Header *bh2 = (Header *)((byte *)b + size);
bh2->prev = size;
bh2->free = true;
// bh2->heap = this; // Heap here!!!
LinkFree(bh2->GetBlock(), sz2);
bh->Next()->prev = bh2->size = sz2;
bh->size = size;
}
return b;
}
void *Heap::LAlloc(size_t& size) {
ASSERT(size > 256);
static bool inited;
if(!inited) {
LInit();
inited = true;
}
if(size > MAXBLOCK) {
Mutex::Lock __(global_lock);
LTIMING("Big alloc");
sHeapStat(17);
DLink *b = (DLink *)SysAllocRaw(size + 40);
if(!b)
Panic("Out of memory!");
b->Link(&allbig);
size = ((size + 40 + 4095) & ~4095) - 40;
*(size_t *)((byte *)b + 16) = size;
Header *h = (Header *)((byte *)b + 32);
h->size = 0;
h->free = false;
return (byte *)b + 40;
}
sHeapStat(16);
int ii = SizeToBin((int)size);
size = BinSz[ii];
while(ii < LBINS) {
DLink *b = freebin[ii];
DLink *n = b->next;
if(b != n) {
void *ptr = DivideBlock(n, (int)size, ii);
sDoPeakProfile();
return ptr;
}
ii++;
}
DLink *n = AddChunk();
if(!n)
Panic("Out of memory!");
void *ptr = DivideBlock(n, (int)size, LBINS - 1);
sDoPeakProfile();
return ptr;
}
void Heap::LFree(void *ptr) {
DLink *b = (DLink *)ptr;
Header *bh = b->GetHeader();
if(bh->size == 0) {
Mutex::Lock __(global_lock);
LTIMING("Big free");
ASSERT(((dword)(uintptr_t)bh & 4095) == 32);
b = (DLink *)((byte *)bh - 32);
b->Unlink();
SysFreeRaw(b, *(size_t *)((byte *)b + 16));
return;
}
LTIMING("Large free");
if(bh->prev) {
Header *p = bh->Prev();
if(p->free) {
b = p->GetBlock();
b->Unlink();
p->size += bh->size + sizeof(Header);
p->Next()->prev = p->size;
bh = p;
}
}
Header *n = bh->Next();
if(n->free) {
n->GetBlock()->Unlink();
bh->size += n->size + sizeof(Header);
n->Next()->prev = bh->size;
}
bh->free = true;
LinkFree(b, bh->size);
}
/*
void LMake(MemoryProfile& p)
{
CriticalSection::Lock __(llock);
int ii = 0;
int fi = 0;
Link *m = s_ball.next;
while(m != &s_ball) {
int sz = (int)*(size_t *)((byte *)m + 16);
p.large_count++;
p.large_total += sz;
if(ii < 4096)
p.large_size[ii++] = sz;
m = m->next;
}
m = s_mall.next;
while(m != &s_mall) {
Header *h = (Header *)((byte *)m + 16);
int sz = h->size;
if(h->free) {
p.large_free_count++;
p.large_free_total += sz;
if(fi < 4096)
p.large_free_size[fi++] = sz;
}
else {
p.large_count++;
p.large_total += sz;
if(ii < 4096)
p.large_size[ii++] = sz;
}
m = m->next;
}
}
*/