Commit ae57894
Changed files (3)
memory
memory/heap/heap_debug.h
@@ -19,6 +19,74 @@ STRUCT( Heap,
HeapEntry blocklist; /* The existing blocks in a list */
);
+static inline Status _Heap_find_block( Heap *h, HeapEntry *e, HeapEntry **out_prev ) {
+ u8 ptr_correct = 0;
+ HeapEntry *prev = &h->blocklist;
+
+ for( HeapEntry *i = h->blocklist.next; i != 0; i = i->next ) {
+ if( e == i ) {
+ ptr_correct = 1;
+ break;
+ }
+ prev = i;
+ }
+
+ /* The pointer is not pointing to a previously allocated block if this fails or perhaps it is a double-free. */
+ assert( ptr_correct );
+ if( !ptr_correct ) {
+ return S_FAILURE;
+ }
+
+ *out_prev = prev;
+ return S_SUCCESS;
+}
+
+static inline Status _Heap_check_entry( HeapEntry *e ) {
+ u8 ok = 1;
+
+ assert( e->checksum == (e->size ^ e->allowed_size ^ (usize)e->next ^ HEAP_XOR_KEY) || (ok = 0) );
+ assert( e->header_start_guard == HEAP_HEADER_GUARD_NUMBER || (ok = 0) );
+ assert( e->header_end_guard == HEAP_HEADER_GUARD_NUMBER || (ok = 0) );
+ assert( e->allowed_size >= e->size || (ok = 0) );
+
+ u8* data = (u8*)(&e->header_end_guard + 1);
+ assert( *(usize*)(data + e->allowed_size) = HEAP_OVERRUN_GUARD_NUMBER || (ok = 0) );
+
+ if( !ok ) {
+ return S_FAILURE;
+ } else {
+ return S_SUCCESS;
+ }
+}
+
+static inline void _Heap_unlink_entry( HeapEntry *prev, HeapEntry *e ) {
+ prev->next = e->next;
+ prev->checksum = prev->size ^ prev->allowed_size ^ (usize)prev->next ^ HEAP_XOR_KEY;
+}
+
+static inline void _Heap_link_free_entry( Heap *h, HeapEntry *e ) {
+ e->next = h->freelist.next;
+ h->freelist.next = e;
+ e->checksum = e->size ^ e->allowed_size ^ (usize)e->next ^ HEAP_XOR_KEY;
+}
+
+
+static inline void _Heap_link_block( Heap *h, HeapEntry *e ) {
+ e->next = h->blocklist.next;
+ h->blocklist.next = e;
+ e->checksum = e->size ^ e->allowed_size ^ (usize)e->next ^ HEAP_XOR_KEY;
+}
+
+static inline usize Heap_get_asize( Heap *h, u8 *ptr ) {
+ HeapEntry *e = (HeapEntry*)( ptr - sizeof(HeapEntry) );
+ HeapEntry *prev = 0;
+ _Heap_check_entry( e );
+ _Heap_find_block( h, e, &prev );
+ return e->size;
+}
+
+#ifdef NOTLIBC_IMPLEMENT
+
Status Heap_create( Heap *out, usize size ) {
assert( out != 0 );
assert( size != 0 );
@@ -53,19 +121,14 @@ Status Heap_alloc( Heap *h, usize amount, u8 **out ) {
u8* data = (u8*)(&i->header_end_guard + 1);
/* If any of these fails, then your freelist has been corrupted somehow - it should not be iterated */
- assert( i->header_start_guard == HEAP_HEADER_GUARD_NUMBER );
- assert( i->header_end_guard == HEAP_HEADER_GUARD_NUMBER );
- assert( i->checksum == (i->size ^ i->allowed_size ^ (usize)i->next ^ HEAP_XOR_KEY) );
- assert( i->allowed_size >= i->size );
- assert( *(usize*)(data + i->allowed_size) == HEAP_OVERRUN_GUARD_NUMBER );
+ _Heap_check_entry(i);
if( i->allowed_size >= amount && i->allowed_size <= max_size ) {
new = i;
for( usize i = 0; i < new->allowed_size; ++i ) {
assert( data[i] == MAGIC_FREED_MEM );
}
- prev->next = new->next;
- prev->checksum = (prev->size ^ prev->allowed_size ^ (usize)prev->next ^ HEAP_XOR_KEY);
+ _Heap_unlink_entry( prev, new );
new->next = 0;
break;
}
@@ -85,12 +148,10 @@ Status Heap_alloc( Heap *h, usize amount, u8 **out ) {
*(usize*)(data + new->allowed_size) = HEAP_OVERRUN_GUARD_NUMBER;
- new->next = h->blocklist.next;
- h->blocklist.next = new;
new->size = amount;
- new->checksum = new->size ^ new->allowed_size ^ (usize)new->next ^ HEAP_XOR_KEY;
new->header_start_guard = HEAP_HEADER_GUARD_NUMBER;
new->header_end_guard = HEAP_HEADER_GUARD_NUMBER;
+ _Heap_link_block( h, new );
*out = data;
@@ -103,31 +164,13 @@ Status Heap_free( Heap *h, u8 **ptr ) {
HeapEntry *e = (HeapEntry*)( (u8*)*ptr - sizeof(HeapEntry) );
- u8 ptr_correct = 0;
- HeapEntry *prev = &h->blocklist;
+ HeapEntry *prev = 0;
- for( HeapEntry *i = h->blocklist.next; i != 0; i = i->next ) {
- if( e == i ) {
- ptr_correct = 1;
- break;
- }
- prev = i;
- }
-
- /* The pointer is not pointing to a previously allocated block if this fails or perhaps it is a double-free. */
- assert(ptr_correct);
-
- /* Check header corruption */
- assert( e->checksum == (e->size ^ e->allowed_size ^ (usize)e->next ^ HEAP_XOR_KEY) );
- assert( e->header_start_guard == HEAP_HEADER_GUARD_NUMBER );
- assert( e->header_end_guard == HEAP_HEADER_GUARD_NUMBER );
+ assert(S_OK( _Heap_find_block( h, e, &prev ) ));
+ assert(S_OK( _Heap_check_entry( e ) ));
- prev->next = e->next;
- prev->checksum = prev->size ^ prev->allowed_size ^ (usize)prev->next ^ HEAP_XOR_KEY;
-
- e->next = h->freelist.next;
- h->freelist.next = e;
- e->checksum = e->size ^ e->allowed_size ^ (usize)e->next ^ HEAP_XOR_KEY;
+ _Heap_unlink_entry( prev, e );
+ _Heap_link_free_entry( h, e );
u8* data = (u8*)(&e->header_end_guard + 1);
mem_set( data, e->allowed_size, MAGIC_FREED_MEM );
@@ -138,5 +181,6 @@ Status Heap_free( Heap *h, u8 **ptr ) {
return S_SUCCESS;
}
+#endif
#endif
memory/heap/heap_release.h
@@ -13,6 +13,13 @@ STRUCT( Heap,
HeapEntry *freelist_data;
);
+static inline usize Heap_get_asize( Heap *h, u8 *ptr ) {
+ (void)h;
+ return *((usize*)ptr - 1);
+}
+
+#ifdef NOTLIBC_IMPLEMENT
+
Status Heap_create( Heap *out, usize size ) {
TRY( Arena_create( &out->arena, size ) );
out->freelist = (HeapEntry){0};
@@ -78,5 +85,7 @@ Status Heap_free( Heap *h, u8 **ptr ) {
return S_SUCCESS;
}
+#endif
+
#endif
memory/heap.h
@@ -4,12 +4,10 @@
#include "datatypes/error.h"
#include "platform/info/build.h"
-#ifdef NOTLIBC_IMPLEMENT
- #if BUILD_TYPE == BUILD_RELEASE
- #include "./heap/heap_release.h"
- #elif BUILD_TYPE == BUILD_DEBUG
- #include "./heap/heap_debug.h"
- #endif
+#if BUILD_TYPE == BUILD_RELEASE
+ #include "./heap/heap_release.h"
+#elif BUILD_TYPE == BUILD_DEBUG
+ #include "./heap/heap_debug.h"
#endif
ASSERT( sizeof(HeapEntry)%sizeof(usize) == 0 );
@@ -21,6 +19,8 @@ Status Heap_create( Heap *out, usize size ); /* size - size of underlying arena.
Status Heap_alloc( Heap *h, usize amount, u8 **out );
Status Heap_free( Heap *h, u8 **ptr ); /* u8** cause it zeroes the pointer on success automatically. */
+static inline usize Heap_get_asize( Heap *h, u8 *ptr );
+
Status Heap_destroy( Heap *h );
#endif