mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 14:16:09 -06:00
203 lines
4.1 KiB
C++
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;
|
|
}
|
|
}
|
|
*/
|