Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
#include "PancakeDebug.h"
#include "PancakeWorkers.h"
#ifdef PANCAKE_DEBUG
/* Directly allocate memory allocation information hash tables to prevent recursion in allocator */
#undef uthash_malloc
#undef uthash_free
#define uthash_malloc malloc
#define uthash_free(ptr, sz) free(ptr)
static PancakeAllocatedMemory *allocated = NULL;
static UNative totalAllocated = 0;
static UNative peakAllocated = 0;
#ifdef HAVE_PANCAKE_SIGSEGV
void PancakeDebugHandleSegfault(Int32 signum, siginfo_t *info, void *context) {
ucontext_t *ucontext = (ucontext_t*) context;
void *array[50], *caller;
Native size, i;
Byte **strings;
#ifdef PANCAKE_64
caller = (void*) ucontext->uc_mcontext.gregs[REG_RIP];
#else
caller = (void*) ucontext->uc_mcontext.gregs[REG_EIP];
#endif
printf("Segmentation fault at %p (called by %p)\n", info->si_addr, caller);
printf("Backtrace:\n");
size = backtrace(array, 50);
array[1] = caller;
strings = backtrace_symbols(array, size);
if(strings == NULL) {
exit(1);
}
for(i = 0; i < size; i++) {
printf("#%li %s\n", size - i, strings[i]);
}
free(strings);
printf("in worker %s\n", PancakeCurrentWorker->name.value);
exit(1);
}
#endif
PANCAKE_API void _PancakeAssert(Native result, Byte *condition, Byte *file, Int32 line) {
if(!result) {
printf("Assertion failed: %s in file %s on line %i\n", condition, file, line);
#ifdef HAVE_EXECINFO_H
void *array[50];
Native size, i;
Byte **strings;
printf("Backtrace:\n");
size = backtrace(array, 50);
strings = backtrace_symbols(array, size);
if(strings == NULL) {
exit(1);
}
for(i = 0; i < size; i++) {
printf("#%li %s\n", size - i, strings[i]);
}
free(strings);
#endif
exit(1);
}
}
PANCAKE_API void *_PancakeAllocate(Native size, Byte *file, Int32 line) {
void *ptr = malloc(size + 1);
PancakeAllocatedMemory *mem;
_PancakeAssert(ptr != NULL, "Out of memory", file, line);
mem = malloc(sizeof(PancakeAllocatedMemory));
_PancakeAssert(mem != NULL, "Out of memory", file, line);
mem->file = file;
mem->line = line;
mem->ptr = ptr;
mem->size = size;
totalAllocated += size;
if(totalAllocated > peakAllocated) {
peakAllocated = totalAllocated;
}
// Set overflow detection byte
((UByte*) ptr)[size] = 0xff;
HASH_ADD(hh, allocated, ptr, sizeof(void*), mem);
return ptr;
}
PANCAKE_API void *_PancakeReallocate(void *ptr, Native size, Byte *file, Int32 line) {
PancakeAllocatedMemory *mem;
void *newPtr;
if(ptr == NULL) {
return _PancakeAllocate(size, file, line);
}
if(size == 0) {
_PancakeFree(ptr, file, line);
return NULL;
}
HASH_FIND(hh, allocated, &ptr, sizeof(void*), mem);
_PancakeAssert(mem != NULL, "Trying to reallocate invalid pointer", file, line);
// Check for memory overflow
_PancakeAssert(((UByte*) ptr)[mem->size] == 0xff, "Overflow detected in memory allocated", mem->file, mem->line);
newPtr = realloc(ptr, size + 1);
_PancakeAssert(newPtr != NULL, "Out of memory", file, line);
// Set overflow detection byte
((UByte*) newPtr)[size] = 0xff;
totalAllocated -= mem->size;
mem->ptr = newPtr;
mem->size = size;
totalAllocated += mem->size;
if(totalAllocated > peakAllocated) {
peakAllocated = totalAllocated;
}
HASH_DEL(allocated, mem);
HASH_ADD(hh, allocated, ptr, sizeof(void*), mem);
return newPtr;
}
PANCAKE_API void _PancakeFree(void *ptr, Byte *file, Int32 line) {
PancakeAllocatedMemory *mem;
_PancakeAssert(ptr != NULL, "Trying to free NULL pointer", file, line);
HASH_FIND(hh, allocated, &ptr, sizeof(void*), mem);
_PancakeAssert(mem != NULL, "Trying to free invalid pointer", file, line);
// Check for memory overflow
_PancakeAssert(((UByte*) ptr)[mem->size] == 0xff, "Overflow detected in memory allocated", mem->file, mem->line);
totalAllocated -= mem->size;
free(ptr);
HASH_DEL(allocated, mem);
free(mem);
}
PANCAKE_API Byte *_PancakeDuplicateString(Byte *string, Byte *file, Int32 line) {
Byte *ptr;
PancakeAllocatedMemory *mem;
UInt32 size;
_PancakeAssert(string != NULL, "Trying to duplicate NULL pointer", file, line);
size = strlen(string);
ptr = malloc(size + 2);
_PancakeAssert(ptr != NULL, "Out of memory", file, line);
memcpy(ptr, string, size + 1);
mem = malloc(sizeof(PancakeAllocatedMemory));
_PancakeAssert(mem != NULL, "Out of memory", file, line);
mem->file = file;
mem->line = line;
mem->ptr = ptr;
mem->size = size + 1;
totalAllocated += mem->size;
if(totalAllocated > peakAllocated) {
peakAllocated = totalAllocated;
}
// Set overflow detection byte
ptr[size + 2] = 0xff;
HASH_ADD(hh, allocated, ptr, sizeof(void*), mem);
return ptr;
}
PANCAKE_API Byte *_PancakeDuplicateStringLength(Byte *string, Int32 length, Byte *file, Int32 line) {
Byte *ptr;
PancakeAllocatedMemory *mem;
_PancakeAssert(string != NULL, "Trying to duplicate NULL pointer", file, line);
ptr = malloc(length + 2);
_PancakeAssert(ptr != NULL, "Out of memory", file, line);
memcpy(ptr, string, length + 1);
mem = malloc(sizeof(PancakeAllocatedMemory));
_PancakeAssert(mem != NULL, "Out of memory", file, line);
mem->file = file;
mem->line = line;
mem->ptr = ptr;
mem->size = length + 1;
totalAllocated += mem->size;
if(totalAllocated > peakAllocated) {
peakAllocated = totalAllocated;
}
// Set overflow detection byte
ptr[length + 2] = 0xff;
HASH_ADD(hh, allocated, ptr, sizeof(void*), mem);
return ptr;
}
PANCAKE_API void PancakeCheckHeap() {
PancakeAllocatedMemory *mem;
for(mem = allocated; mem != NULL; mem = mem->hh.next) {
_PancakeAssert(((UByte*) mem->ptr)[mem->size] == 0xff, "Overflow detected in memory allocated", mem->file, mem->line);
}
}
PANCAKE_API void PancakeDumpHeap() {
PancakeAllocatedMemory *mem;
pid_t pid = getpid();
for(mem = allocated; mem != NULL; mem = mem->hh.next) {
printf("[%i] [%#lx] %u bytes allocated in %s on line %i\n", pid, (UNative) mem->ptr, mem->size, mem->file, mem->line);
}
}
PANCAKE_API void PancakeDumpMemoryUsage() {
pid_t pid = getpid();
if(totalAllocated) {
printf("[%i] %lu bytes total allocated\n", pid, totalAllocated);
}
printf("[%i] %lu bytes allocated at peak\n", pid, peakAllocated);
}
PANCAKE_API void PancakeFreeAllocatorMeta() {
PancakeAllocatedMemory *mem, *tmp;
HASH_ITER(hh, allocated, mem, tmp) {
HASH_DEL(allocated, mem);
free(mem);
}
}
PANCAKE_API void PancakePrintString(String *string) {
printf("String(%lu) \"%.*s\"\n", string->length, (Int32) string->length, string->value);
}
PANCAKE_API void PancakePrintNetworkBuffer(PancakeNetworkBuffer *buf) {
printf("NetworkBuffer(%u, %u) \"%.*s\"\n", buf->length, buf->size, buf->length, buf->value);
}
PANCAKE_API void PancakeBacktrace() {
#ifdef HAVE_EXECINFO_H
void *array[50];
Native size, i;
Byte **strings;
size = backtrace(array, 50);
strings = backtrace_symbols(array, size);
if(strings == NULL) {
exit(1);
}
for(i = 0; i < size; i++) {
printf("#%li %s\n", size - i, strings[i]);
}
free(strings);
#else
printf("Backtraces not available\n");
#endif
}
#endif