Fix formatting and remove namespaces in libmaxsi heap.cpp.
What a mess.
This commit is contained in:
parent
d81cdc09e9
commit
31df7c0c93
|
@ -54,41 +54,37 @@
|
||||||
typedef uintptr_t addr_t;
|
typedef uintptr_t addr_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Maxsi
|
//
|
||||||
{
|
// This first section is just magic compiler/platform stuff, you should
|
||||||
namespace Memory
|
// skip ahead to the actual algorithm.
|
||||||
{
|
//
|
||||||
//
|
|
||||||
// This first section is just magic compiler/platform stuff, you should
|
|
||||||
// skip ahead to the actual algorithm.
|
|
||||||
//
|
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
const size_t MAGIC = 0xDEADDEADDEADDEADUL;
|
const size_t MAGIC = 0xDEADDEADDEADDEADUL;
|
||||||
const size_t ALIGNMENT = 16UL;
|
const size_t ALIGNMENT = 16UL;
|
||||||
#else
|
#else
|
||||||
const size_t MAGIC = 0xDEADDEADUL;
|
const size_t MAGIC = 0xDEADDEADUL;
|
||||||
const size_t ALIGNMENT = 8UL;
|
const size_t ALIGNMENT = 8UL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const size_t PAGESIZE = 4UL * 1024UL; // 4 KiB
|
const size_t PAGESIZE = 4UL * 1024UL; // 4 KiB
|
||||||
const size_t NUMBINS = 8UL * sizeof(size_t);
|
const size_t NUMBINS = 8UL * sizeof(size_t);
|
||||||
|
|
||||||
extern addr_t wilderness;
|
extern addr_t wilderness;
|
||||||
|
|
||||||
#ifdef SORTIX_KERNEL
|
#ifdef SORTIX_KERNEL
|
||||||
addr_t GetHeapStart()
|
static addr_t GetHeapStart()
|
||||||
{
|
{
|
||||||
return Sortix::Memory::GetHeapUpper();
|
return Sortix::Memory::GetHeapUpper();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetHeapMaxSize()
|
static size_t GetHeapMaxSize()
|
||||||
{
|
{
|
||||||
return Sortix::Memory::GetHeapUpper() - Sortix::Memory::GetHeapLower();
|
return Sortix::Memory::GetHeapUpper() - Sortix::Memory::GetHeapLower();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeMemory(addr_t where, size_t bytes)
|
static void FreeMemory(addr_t where, size_t bytes)
|
||||||
{
|
{
|
||||||
assert(Sortix::Page::IsAligned(where + bytes));
|
assert(Sortix::Page::IsAligned(where + bytes));
|
||||||
|
|
||||||
while ( bytes )
|
while ( bytes )
|
||||||
|
@ -99,10 +95,10 @@ namespace Maxsi
|
||||||
bytes -= PAGESIZE;
|
bytes -= PAGESIZE;
|
||||||
where += PAGESIZE;
|
where += PAGESIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AllocateMemory(addr_t where, size_t bytes)
|
static bool AllocateMemory(addr_t where, size_t bytes)
|
||||||
{
|
{
|
||||||
assert(Sortix::Page::IsAligned(where + bytes));
|
assert(Sortix::Page::IsAligned(where + bytes));
|
||||||
|
|
||||||
addr_t pos = where;
|
addr_t pos = where;
|
||||||
|
@ -128,10 +124,10 @@ namespace Maxsi
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtendHeap(size_t bytesneeded)
|
static bool ExtendHeap(size_t bytesneeded)
|
||||||
{
|
{
|
||||||
#ifdef HEAP_GROWS_DOWNWARDS
|
#ifdef HEAP_GROWS_DOWNWARDS
|
||||||
addr_t newwilderness = wilderness - bytesneeded;
|
addr_t newwilderness = wilderness - bytesneeded;
|
||||||
#else
|
#else
|
||||||
|
@ -139,10 +135,10 @@ namespace Maxsi
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return AllocateMemory(newwilderness, bytesneeded);
|
return AllocateMemory(newwilderness, bytesneeded);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
addr_t GetHeapStart()
|
static addr_t GetHeapStart()
|
||||||
{
|
{
|
||||||
addr_t base = (addr_t) sbrk(0);
|
addr_t base = (addr_t) sbrk(0);
|
||||||
addr_t unaligned = base % ALIGNMENT;
|
addr_t unaligned = base % ALIGNMENT;
|
||||||
if ( unaligned )
|
if ( unaligned )
|
||||||
|
@ -151,28 +147,28 @@ namespace Maxsi
|
||||||
}
|
}
|
||||||
addr_t result = (addr_t) sbrk(0);
|
addr_t result = (addr_t) sbrk(0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetHeapMaxSize()
|
static size_t GetHeapMaxSize()
|
||||||
{
|
{
|
||||||
// TODO: A bit of a hack!
|
// TODO: A bit of a hack!
|
||||||
return SIZE_MAX;
|
return SIZE_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtendHeap(size_t bytesneeded)
|
static bool ExtendHeap(size_t bytesneeded)
|
||||||
{
|
{
|
||||||
void* newheapend = sbrk(bytesneeded);
|
void* newheapend = sbrk(bytesneeded);
|
||||||
return newheapend != (void*) -1UL;
|
return newheapend != (void*) -1UL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: BitScanForward and BitScanReverse are x86 instructions, but
|
// TODO: BitScanForward and BitScanReverse are x86 instructions, but
|
||||||
// directly using them messes with the optimizer. Once possible, use
|
// directly using them messes with the optimizer. Once possible, use
|
||||||
// the inline assembly instead of the C-version of the functions.
|
// the inline assembly instead of the C-version of the functions.
|
||||||
|
|
||||||
// Returns the index of the most significant set bit.
|
// Returns the index of the most significant set bit.
|
||||||
inline size_t BSR(size_t Value)
|
inline size_t BSR(size_t Value)
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
assert(Value > 0);
|
assert(Value > 0);
|
||||||
for ( size_t I = 8*sizeof(size_t); I > 0; I-- )
|
for ( size_t I = 8*sizeof(size_t); I > 0; I-- )
|
||||||
|
@ -185,11 +181,11 @@ namespace Maxsi
|
||||||
asm("bsr %0, %1" : "=r"(Result) : "r"(Value));
|
asm("bsr %0, %1" : "=r"(Result) : "r"(Value));
|
||||||
return Result;
|
return Result;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the index of the least significant set bit.
|
// Returns the index of the least significant set bit.
|
||||||
inline size_t BSF(size_t Value)
|
inline size_t BSF(size_t Value)
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
assert(Value > 0);
|
assert(Value > 0);
|
||||||
for ( size_t I = 0; I < 8*sizeof(size_t); I++ )
|
for ( size_t I = 0; I < 8*sizeof(size_t); I++ )
|
||||||
|
@ -202,46 +198,46 @@ namespace Maxsi
|
||||||
asm("bsf %0, %1" : "=r"(Result) : "r"(Value));
|
asm("bsf %0, %1" : "=r"(Result) : "r"(Value));
|
||||||
return Result;
|
return Result;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now for some helper functions and structures.
|
// Now for some helper functions and structures.
|
||||||
//
|
//
|
||||||
|
|
||||||
struct Chunk;
|
struct Chunk;
|
||||||
struct Trailer;
|
struct Trailer;
|
||||||
|
|
||||||
#ifdef SORTIX_KERNEL
|
#ifdef SORTIX_KERNEL
|
||||||
Sortix::kthread_mutex_t heaplock;
|
Sortix::kthread_mutex_t heaplock;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The location where the heap originally grows from.
|
// The location where the heap originally grows from.
|
||||||
addr_t heapstart;
|
addr_t heapstart;
|
||||||
|
|
||||||
// If heap grows down: Location of the first mapped page.
|
// If heap grows down: Location of the first mapped page.
|
||||||
// If heap grows up: Location of the first not-mapped page.
|
// If heap grows up: Location of the first not-mapped page.
|
||||||
addr_t wilderness;
|
addr_t wilderness;
|
||||||
|
|
||||||
// How many bytes remain in the wilderness.
|
// How many bytes remain in the wilderness.
|
||||||
size_t wildernesssize;
|
size_t wildernesssize;
|
||||||
|
|
||||||
// How many bytes are the heap allow to grow to (including wilderness).
|
// How many bytes are the heap allow to grow to (including wilderness).
|
||||||
size_t heapmaxsize;
|
size_t heapmaxsize;
|
||||||
|
|
||||||
// How many bytes are currently used for chunks in the heap, which
|
// How many bytes are currently used for chunks in the heap, which
|
||||||
// excludes the wilderness.
|
// excludes the wilderness.
|
||||||
size_t heapsize;
|
size_t heapsize;
|
||||||
|
|
||||||
// bins[N] contain a linked list of chunks that are at least 2^(N+1)
|
// bins[N] contain a linked list of chunks that are at least 2^(N+1)
|
||||||
// bytes, but less than 2^(N+2) bytes. By selecting the proper bin in
|
// bytes, but less than 2^(N+2) bytes. By selecting the proper bin in
|
||||||
// constant time, we can allocate chunks in constant time.
|
// constant time, we can allocate chunks in constant time.
|
||||||
Chunk* bins[NUMBINS];
|
Chunk* bins[NUMBINS];
|
||||||
|
|
||||||
// Bit N is set if bin[N] contains a chunk.
|
// Bit N is set if bin[N] contains a chunk.
|
||||||
size_t bincontainschunks;
|
size_t bincontainschunks;
|
||||||
|
|
||||||
static bool IsGoodHeapPointer(void* ptr, size_t size)
|
static bool IsGoodHeapPointer(void* ptr, size_t size)
|
||||||
{
|
{
|
||||||
uintptr_t ptrlower = (uintptr_t) ptr;
|
uintptr_t ptrlower = (uintptr_t) ptr;
|
||||||
uintptr_t ptrupper = ptrlower + size;
|
uintptr_t ptrupper = ptrlower + size;
|
||||||
#ifdef HEAP_GROWS_DOWNWARDS
|
#ifdef HEAP_GROWS_DOWNWARDS
|
||||||
|
@ -252,12 +248,12 @@ namespace Maxsi
|
||||||
uintptr_t heapupper = wilderness;
|
uintptr_t heapupper = wilderness;
|
||||||
#endif
|
#endif
|
||||||
return heaplower <= ptrlower && ptrupper <= heapupper;
|
return heaplower <= ptrlower && ptrupper <= heapupper;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A preamble to every chunk providing meta-information.
|
// A preamble to every chunk providing meta-information.
|
||||||
struct Chunk
|
struct Chunk
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
size_t size; // Includes size of Chunk and Trailer
|
size_t size; // Includes size of Chunk and Trailer
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
@ -265,19 +261,19 @@ namespace Maxsi
|
||||||
Chunk* nextunused;
|
Chunk* nextunused;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool IsUsed() { return magic == MAGIC; }
|
bool IsUsed() { return magic == MAGIC; }
|
||||||
Trailer* GetTrailer();
|
Trailer* GetTrailer();
|
||||||
Chunk* LeftNeighbor();
|
Chunk* LeftNeighbor();
|
||||||
Chunk* RightNeighbor();
|
Chunk* RightNeighbor();
|
||||||
bool IsSane();
|
bool IsSane();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// A trailer ro every chunk providing meta-information.
|
// A trailer to every chunk providing meta-information.
|
||||||
struct Trailer
|
struct Trailer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
size_t magic;
|
size_t magic;
|
||||||
|
@ -285,45 +281,45 @@ namespace Maxsi
|
||||||
};
|
};
|
||||||
size_t size; // Includes size of Chunk and Trailer
|
size_t size; // Includes size of Chunk and Trailer
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool IsUsed() { return magic == MAGIC; }
|
bool IsUsed() { return magic == MAGIC; }
|
||||||
Chunk* GetChunk();
|
Chunk* GetChunk();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t OVERHEAD = sizeof(Chunk) + sizeof(Trailer);
|
const size_t OVERHEAD = sizeof(Chunk) + sizeof(Trailer);
|
||||||
|
|
||||||
// This is how a real chunk actually looks:
|
// This is how a real chunk actually looks:
|
||||||
//struct RealChunk
|
//struct RealChunk
|
||||||
//{
|
//{
|
||||||
// Chunk header;
|
// Chunk header;
|
||||||
// byte data[...];
|
// byte data[...];
|
||||||
// Trailer footer;
|
// Trailer footer;
|
||||||
// };
|
// };
|
||||||
|
|
||||||
Trailer* Chunk::GetTrailer()
|
Trailer* Chunk::GetTrailer()
|
||||||
{
|
{
|
||||||
return (Trailer*) (((addr_t) this) + size - sizeof(Trailer));
|
return (Trailer*) (((addr_t) this) + size - sizeof(Trailer));
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk* Chunk::LeftNeighbor()
|
Chunk* Chunk::LeftNeighbor()
|
||||||
{
|
{
|
||||||
Trailer* trailer = (Trailer*) (((addr_t) this) - sizeof(Trailer));
|
Trailer* trailer = (Trailer*) (((addr_t) this) - sizeof(Trailer));
|
||||||
return trailer->GetChunk();
|
return trailer->GetChunk();
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk* Chunk::RightNeighbor()
|
Chunk* Chunk::RightNeighbor()
|
||||||
{
|
{
|
||||||
return (Chunk*) (((addr_t) this) + size);
|
return (Chunk*) (((addr_t) this) + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk* Trailer::GetChunk()
|
Chunk* Trailer::GetChunk()
|
||||||
{
|
{
|
||||||
return (Chunk*) (((addr_t) this) + sizeof(Trailer) - size);
|
return (Chunk*) (((addr_t) this) + sizeof(Trailer) - size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Chunk::IsSane()
|
bool Chunk::IsSane()
|
||||||
{
|
{
|
||||||
if ( !IsGoodHeapPointer(this, sizeof(*this)) )
|
if ( !IsGoodHeapPointer(this, sizeof(*this)) )
|
||||||
return false;
|
return false;
|
||||||
if ( !size ) { return false; }
|
if ( !size ) { return false; }
|
||||||
|
@ -361,10 +357,10 @@ namespace Maxsi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertChunk(Chunk* chunk)
|
static void InsertChunk(Chunk* chunk)
|
||||||
{
|
{
|
||||||
// Insert the chunk into the right bin.
|
// Insert the chunk into the right bin.
|
||||||
size_t binindex = BSR(chunk->size);
|
size_t binindex = BSR(chunk->size);
|
||||||
chunk->GetTrailer()->prevunused = NULL;
|
chunk->GetTrailer()->prevunused = NULL;
|
||||||
|
@ -377,10 +373,10 @@ namespace Maxsi
|
||||||
bins[binindex] = chunk;
|
bins[binindex] = chunk;
|
||||||
bincontainschunks |= (1UL << binindex);
|
bincontainschunks |= (1UL << binindex);
|
||||||
assert(chunk->IsSane());
|
assert(chunk->IsSane());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ValidateHeap()
|
static bool ValidateHeap()
|
||||||
{
|
{
|
||||||
bool foundbin[NUMBINS];
|
bool foundbin[NUMBINS];
|
||||||
for ( size_t i = 0; i < NUMBINS; i++ ) { foundbin[i] = false; }
|
for ( size_t i = 0; i < NUMBINS; i++ ) { foundbin[i] = false; }
|
||||||
|
|
||||||
|
@ -415,14 +411,14 @@ namespace Maxsi
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// This is where the actual memory allocation algorithm starts.
|
// This is where the actual memory allocation algorithm starts.
|
||||||
//
|
//
|
||||||
|
|
||||||
void Init()
|
extern "C" void _init_heap()
|
||||||
{
|
{
|
||||||
heapstart = GetHeapStart();
|
heapstart = GetHeapStart();
|
||||||
heapmaxsize = GetHeapMaxSize();
|
heapmaxsize = GetHeapMaxSize();
|
||||||
heapsize = 0;
|
heapsize = 0;
|
||||||
|
@ -433,18 +429,13 @@ namespace Maxsi
|
||||||
#ifdef SORTIX_KERNEL
|
#ifdef SORTIX_KERNEL
|
||||||
heaplock = Sortix::KTHREAD_MUTEX_INITIALIZER;
|
heaplock = Sortix::KTHREAD_MUTEX_INITIALIZER;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void _init_heap()
|
// Attempts to expand the wilderness such that it contains at least
|
||||||
{
|
// bytesneeded bytes. This is done by mapping new pages onto into the
|
||||||
Init();
|
// virtual address-space.
|
||||||
}
|
static bool ExpandWilderness(size_t bytesneeded)
|
||||||
|
{
|
||||||
// Attempts to expand the wilderness such that it contains at least
|
|
||||||
// bytesneeded bytes. This is done by mapping new pages onto into the
|
|
||||||
// virtual address-space.
|
|
||||||
bool ExpandWilderness(size_t bytesneeded)
|
|
||||||
{
|
|
||||||
if ( bytesneeded <= wildernesssize ) { return true; }
|
if ( bytesneeded <= wildernesssize ) { return true; }
|
||||||
|
|
||||||
bytesneeded -= wildernesssize;
|
bytesneeded -= wildernesssize;
|
||||||
|
@ -475,10 +466,10 @@ namespace Maxsi
|
||||||
wilderness = newwilderness;
|
wilderness = newwilderness;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void* malloc(size_t size)
|
extern "C" void* malloc(size_t size)
|
||||||
{
|
{
|
||||||
#ifdef SORTIX_KERNEL
|
#ifdef SORTIX_KERNEL
|
||||||
Sortix::ScopedLock scopedlock(&heaplock);
|
Sortix::ScopedLock scopedlock(&heaplock);
|
||||||
#endif
|
#endif
|
||||||
|
@ -585,29 +576,29 @@ namespace Maxsi
|
||||||
|
|
||||||
addr_t result = ((addr_t) chunk) + sizeof(Chunk);
|
addr_t result = ((addr_t) chunk) + sizeof(Chunk);
|
||||||
return (void*) result;
|
return (void*) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsLeftmostChunk(Chunk* chunk)
|
static bool IsLeftmostChunk(Chunk* chunk)
|
||||||
{
|
{
|
||||||
#ifdef HEAP_GROWS_DOWNWARDS
|
#ifdef HEAP_GROWS_DOWNWARDS
|
||||||
return (addr_t) chunk <= wilderness + wildernesssize;
|
return (addr_t) chunk <= wilderness + wildernesssize;
|
||||||
#else
|
#else
|
||||||
return heapstart <= (addr_t) chunk;
|
return heapstart <= (addr_t) chunk;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsRightmostChunk(Chunk* chunk)
|
static bool IsRightmostChunk(Chunk* chunk)
|
||||||
{
|
{
|
||||||
#ifdef HEAP_GROWS_DOWNWARDS
|
#ifdef HEAP_GROWS_DOWNWARDS
|
||||||
return heapstart <= (addr_t) chunk + chunk->size;
|
return heapstart <= (addr_t) chunk + chunk->size;
|
||||||
#else
|
#else
|
||||||
return heapstart + heapsize <= (addr_t) chunk + chunk->size;
|
return heapstart + heapsize <= (addr_t) chunk + chunk->size;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes a chunk from its bin.
|
// Removes a chunk from its bin.
|
||||||
void UnlinkChunk(Chunk* chunk)
|
static void UnlinkChunk(Chunk* chunk)
|
||||||
{
|
{
|
||||||
assert(chunk->IsSane());
|
assert(chunk->IsSane());
|
||||||
Trailer* trailer = chunk->GetTrailer();
|
Trailer* trailer = chunk->GetTrailer();
|
||||||
if ( trailer->prevunused )
|
if ( trailer->prevunused )
|
||||||
|
@ -633,11 +624,11 @@ namespace Maxsi
|
||||||
if ( !bins[binindex] ) { bincontainschunks ^= 1UL << binindex; }
|
if ( !bins[binindex] ) { bincontainschunks ^= 1UL << binindex; }
|
||||||
else { assert(bins[binindex]->IsSane()); }
|
else { assert(bins[binindex]->IsSane()); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transforms a chunk and its neighbors into a single chunk if possible.
|
// Transforms a chunk and its neighbors into a single chunk if possible.
|
||||||
void UnifyNeighbors(Chunk** chunk)
|
static void UnifyNeighbors(Chunk** chunk)
|
||||||
{
|
{
|
||||||
if ( !IsLeftmostChunk(*chunk) )
|
if ( !IsLeftmostChunk(*chunk) )
|
||||||
{
|
{
|
||||||
Chunk* neighbor = (*chunk)->LeftNeighbor();
|
Chunk* neighbor = (*chunk)->LeftNeighbor();
|
||||||
|
@ -662,10 +653,10 @@ namespace Maxsi
|
||||||
(*chunk)->GetTrailer()->size = (*chunk)->size;
|
(*chunk)->GetTrailer()->size = (*chunk)->size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void free(void* addr)
|
extern "C" void free(void* addr)
|
||||||
{
|
{
|
||||||
#ifdef SORTIX_KERNEL
|
#ifdef SORTIX_KERNEL
|
||||||
Sortix::ScopedLock scopedlock(&heaplock);
|
Sortix::ScopedLock scopedlock(&heaplock);
|
||||||
#endif
|
#endif
|
||||||
|
@ -700,20 +691,20 @@ namespace Maxsi
|
||||||
#if 2 <= PARANOIA
|
#if 2 <= PARANOIA
|
||||||
assert(ValidateHeap());
|
assert(ValidateHeap());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void* calloc(size_t nmemb, size_t size)
|
extern "C" void* calloc(size_t nmemb, size_t size)
|
||||||
{
|
{
|
||||||
size_t total = nmemb * size;
|
size_t total = nmemb * size;
|
||||||
void* result = malloc(total);
|
void* result = malloc(total);
|
||||||
if ( !result ) { return NULL; }
|
if ( !result ) { return NULL; }
|
||||||
memset(result, 0, total);
|
memset(result, 0, total);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement this function properly.
|
// TODO: Implement this function properly.
|
||||||
extern "C" void* realloc(void* ptr, size_t size)
|
extern "C" void* realloc(void* ptr, size_t size)
|
||||||
{
|
{
|
||||||
if ( !ptr ) { return malloc(size); }
|
if ( !ptr ) { return malloc(size); }
|
||||||
Chunk* chunk = (Chunk*) ((addr_t) ptr - sizeof(Chunk));
|
Chunk* chunk = (Chunk*) ((addr_t) ptr - sizeof(Chunk));
|
||||||
assert(chunk->IsUsed());
|
assert(chunk->IsUsed());
|
||||||
|
@ -725,6 +716,4 @@ namespace Maxsi
|
||||||
memcpy(newptr, ptr, allocsize);
|
memcpy(newptr, ptr, allocsize);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
return newptr;
|
return newptr;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue