mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 22:02:49 -06:00
194 lines
3.8 KiB
C++
194 lines
3.8 KiB
C++
#include "Malloc.h"
|
|
|
|
#define LTIMING(x)
|
|
|
|
static MemoryProfile *sPeak;
|
|
|
|
void *MemoryAllocPermanentRaw(size_t size)
|
|
{
|
|
if(size >= 256)
|
|
return malloc(size);
|
|
static byte *ptr = NULL;
|
|
static byte *limit = NULL;
|
|
if(ptr + size >= limit) {
|
|
ptr = (byte *)AllocRaw4KB();
|
|
limit = ptr + 4096;
|
|
}
|
|
void *p = ptr;
|
|
ptr += size;
|
|
return p;
|
|
}
|
|
|
|
|
|
void *MemoryAllocPermanent(size_t size)
|
|
{
|
|
#ifdef _MULTITHREADED
|
|
Mutex::Lock __(sHeapLock);
|
|
#endif
|
|
return MemoryAllocPermanentRaw(size);
|
|
}
|
|
|
|
MemoryProfile *MemGetPeak()
|
|
{
|
|
if(sPeak)
|
|
return sPeak;
|
|
sPeak = (MemoryProfile *)MemoryAllocPermanent(sizeof(MemoryProfile));
|
|
memset(sPeak, 0, sizeof(MemoryProfile));
|
|
return NULL;
|
|
}
|
|
|
|
void DoPeakProfile()
|
|
{
|
|
if(sPeak)
|
|
heap.Make(*sPeak);
|
|
}
|
|
|
|
int sKB;
|
|
|
|
void *SysAllocRaw(size_t size)
|
|
{
|
|
LTIMING("SysAllocRaw");
|
|
sKB += int(((size + 4095) & ~4095) >> 10);
|
|
#ifdef PLATFORM_WIN32
|
|
void *ptr = VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
|
|
#else
|
|
#ifdef PLATFORM_LINUX
|
|
void *ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
|
#else
|
|
void *ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
|
|
#endif
|
|
#endif
|
|
if(!ptr)
|
|
Panic("Out of memory!");
|
|
DoPeakProfile();
|
|
return ptr;
|
|
}
|
|
|
|
void SysFreeRaw(void *ptr, size_t size)
|
|
{
|
|
LTIMING("SysFreeRaw");
|
|
// LOGF("SysFreeRaw %X - %d\n", ptr, size);
|
|
sKB -= int(((size + 4095) & ~4095) >> 10);
|
|
#ifdef PLATFORM_WIN32
|
|
VirtualFree(ptr, 0, MEM_RELEASE);
|
|
#else
|
|
munmap(ptr, size);
|
|
#endif
|
|
}
|
|
|
|
int s4kb__;
|
|
int s64kb__;
|
|
|
|
void *AllocRaw4KB()
|
|
{
|
|
static int left;
|
|
static byte *ptr;
|
|
static int n = 32;
|
|
if(left == 0) {
|
|
left = n >> 5;
|
|
ptr = (byte *)SysAllocRaw(left * 4096);
|
|
}
|
|
n = n + 1;
|
|
if(n > 4096) n = 4096;
|
|
void *p = ptr;
|
|
ptr += 4096;
|
|
left--;
|
|
s4kb__++;
|
|
DoPeakProfile();
|
|
return p;
|
|
}
|
|
|
|
void *AllocRaw64KB()
|
|
{
|
|
static int left;
|
|
static byte *ptr;
|
|
static int n = 32;
|
|
if(left == 0) {
|
|
left = n >> 5;
|
|
ptr = (byte *)SysAllocRaw(left * 65536);
|
|
}
|
|
n = n + 1;
|
|
if(n > 256) n = 256;
|
|
void *p = ptr;
|
|
ptr += 65536;
|
|
left--;
|
|
s64kb__++;
|
|
DoPeakProfile();
|
|
return p;
|
|
}
|
|
|
|
void HeapPanic(const char *text, void *pos, int size)
|
|
{
|
|
RLOG("\n\n" << text << "\n");
|
|
HexDump(VppLog(), pos, size, 64);
|
|
Panic(text);
|
|
}
|
|
|
|
#ifdef HEAPDBG
|
|
|
|
void Heap::DbgFreeFill(void *p, int size)
|
|
{
|
|
int count = size >> 2;
|
|
dword *ptr = (dword *)p;
|
|
while(count--)
|
|
*ptr++ = 0x65657246;
|
|
}
|
|
|
|
void Heap::DbgFreeCheck(void *p, int size)
|
|
{
|
|
int count = size >> 2;
|
|
dword *ptr = (dword *)p;
|
|
while(count--)
|
|
if(*ptr++ != 0x65657246)
|
|
HeapPanic("Writes to freed blocks detected", p, size);
|
|
}
|
|
|
|
void *Heap::DbgFreeCheckK(void *p, int k)
|
|
{
|
|
Page *page = (Page *)((uintptr_t)p & ~(uintptr_t)4095);
|
|
ASSERT((byte *)page + sizeof(Page) <= (byte *)p && (byte *)p < (byte *)page + 4096);
|
|
ASSERT((4096 - ((uintptr_t)p & (uintptr_t)4095)) % Ksz(k) == 0);
|
|
ASSERT(page->klass == k);
|
|
DbgFreeCheck((FreeLink *)p + 1, Ksz(k) - sizeof(FreeLink));
|
|
return p;
|
|
}
|
|
|
|
void Heap::DbgFreeFillK(void *p, int k)
|
|
{
|
|
DbgFreeFill((FreeLink *)p + 1, Ksz(k) - sizeof(FreeLink));
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef flagHEAPSTAT
|
|
int stat[65536];
|
|
int bigstat;
|
|
|
|
void Heap::Stat(size_t sz)
|
|
{
|
|
if(sz < 65536)
|
|
stat[sz]++;
|
|
else
|
|
bigstat++;
|
|
}
|
|
|
|
EXITBLOCK {
|
|
int sum = 0;
|
|
for(int i = 0; i < 65536; i++)
|
|
sum += stat[i];
|
|
sum += bigstat;
|
|
int total = 0;
|
|
VppLog() << Sprintf("Allocation statistics: (total allocations: %d)\n", sum);
|
|
for(int i = 0; i < 65536; i++)
|
|
if(stat[i]) {
|
|
total += stat[i];
|
|
VppLog() << Sprintf("%5d %8dx %2d%%, total %8dx %2d%%\n",
|
|
i, stat[i], 100 * stat[i] / sum, total, 100 * total / sum);
|
|
}
|
|
if(bigstat) {
|
|
total += bigstat;
|
|
VppLog() << Sprintf(">64KB %8dx %2d%%, total %8dx %2d%%\n",
|
|
bigstat, 100 * bigstat / sum, total, 100 * total / sum);
|
|
}
|
|
}
|
|
#endif
|