// RETOOR - Nov 28 2024 #ifndef RMALLOC_H #define RMALLOC_H #ifndef RMALLOC_OVERRIDE #define RMALLOC_OVERRIDE 1 #endif #ifdef _POSIX_C_SOURCE #define _POSIX_C_SOURCE_TEMP _POSIX_C_SOURCE #undef _POSIX_C_SOURCE #endif #ifndef _POSIX_C_SOURCE #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200112L #endif #ifndef ulonglong #define ulonglong unsigned long long #endif #include #include #include #include #ifndef RTEMP_H #define RTEMP_H #ifndef RTYPES_H #define RTYPES_H #ifdef _POSIX_C_SOURCE #define _POSIX_C_SOURCE_TEMP _POSIX_C_SOURCE #undef _POSIX_C_SOURCE #endif #ifndef _POSIX_C_SOURCE #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200112L #endif #include #include // uint #include #include // ulong #ifndef ulonglong #define ulonglong unsigned long long #endif #ifndef uint typedef unsigned int uint; #endif #ifndef byte typedef unsigned char byte; #endif #ifdef _POSIX_C_SOURCE_TEMP #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE _POSIX_C_SOURCE_TEMP #undef _POSIX_C_SOURCE_TEMP #else #undef _POSIX_C_SOURCE #endif #endif #include #ifndef RTEMPC_SLOT_COUNT #define RTEMPC_SLOT_COUNT 20 #endif #ifndef RTEMPC_SLOT_SIZE #define RTEMPC_SLOT_SIZE 1024 * 64 * 128 #endif bool _rtempc_initialized = false; pthread_mutex_t _rtempc_thread_lock; bool rtempc_use_mutex = true; byte _current_rtempc_slot = 1; char _rtempc_buffer[RTEMPC_SLOT_COUNT][RTEMPC_SLOT_SIZE]; char *rtempc(char *data) { if (rtempc_use_mutex) { if (!_rtempc_initialized) { _rtempc_initialized = true; pthread_mutex_init(&_rtempc_thread_lock, NULL); } pthread_mutex_lock(&_rtempc_thread_lock); } uint current_rtempc_slot = _current_rtempc_slot; _rtempc_buffer[current_rtempc_slot][0] = 0; strcpy(_rtempc_buffer[current_rtempc_slot], data); _current_rtempc_slot++; if (_current_rtempc_slot == RTEMPC_SLOT_COUNT) { _current_rtempc_slot = 0; } if (rtempc_use_mutex) pthread_mutex_unlock(&_rtempc_thread_lock); return _rtempc_buffer[current_rtempc_slot]; } #define sstring(_pname, _psize) \ static char _##_pname[_psize]; \ _##_pname[0] = 0; \ char *_pname = _##_pname; #define string(_pname, _psize) \ char _##_pname[_psize]; \ _##_pname[0] = 0; \ char *_pname = _##_pname; #define sreset(_pname, _psize) _pname = _##_pname; #define sbuf(val) rtempc(val) #endif #ifdef _POSIX_C_SOURCE_TEMP #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE _POSIX_C_SOURCE_TEMP #undef _POSIX_C_SOURCE_TEMP #else #undef _POSIX_C_SOURCE #endif ulonglong rmalloc_count = 0; ulonglong rmalloc_alloc_count = 0; ulonglong rmalloc_free_count = 0; ulonglong rmalloc_total_bytes_allocated = 0; void *_rmalloc_prev_realloc_obj = NULL; size_t _rmalloc_prev_realloc_obj_size = 0; void *rmalloc(size_t size) { void *result; while (!(result = malloc(size))) { fprintf(stderr, "Warning: malloc failed, trying again.\n"); } rmalloc_count++; rmalloc_alloc_count++; rmalloc_total_bytes_allocated += size; return result; } void *rcalloc(size_t count, size_t size) { void *result; while (!(result = calloc(count, size))) { fprintf(stderr, "Warning: calloc failed, trying again.\n"); } rmalloc_alloc_count++; rmalloc_count++; rmalloc_total_bytes_allocated += count * size; return result; } void *rrealloc(void *obj, size_t size) { if (!obj) { rmalloc_count++; } rmalloc_alloc_count++; if (obj == _rmalloc_prev_realloc_obj) { rmalloc_total_bytes_allocated += size - _rmalloc_prev_realloc_obj_size; _rmalloc_prev_realloc_obj_size = size - _rmalloc_prev_realloc_obj_size; } else { _rmalloc_prev_realloc_obj_size = size; } void *result; while (!(result = realloc(obj, size))) { fprintf(stderr, "Warning: realloc failed, trying again.\n"); } _rmalloc_prev_realloc_obj = result; return result; } char *rstrdup(const char *s) { if (!s) return NULL; char *result; size_t size = strlen(s) + 1; result = rmalloc(size); memcpy(result, s, size); rmalloc_total_bytes_allocated += size; return result; } void *rfree(void *obj) { rmalloc_count--; rmalloc_free_count++; free(obj); return NULL; } #if RMALLOC_OVERRIDE #define malloc rmalloc #define calloc rcalloc #define realloc rrealloc #define free rfree #define strdup rstrdup #endif char *rmalloc_lld_format(ulonglong num) { char res[100]; res[0] = 0; sprintf(res, "%'llu", num); char *resp = res; while (*resp) { if (*resp == ',') *resp = '.'; resp++; } return sbuf(res); } char *rmalloc_bytes_format(int factor, ulonglong num) { char *sizes[] = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}; if (num > 1024) { return rmalloc_bytes_format(factor + 1, num / 1024); } char res[100]; res[0] = 0; sprintf(res, "%s %s", rmalloc_lld_format(num), sizes[factor]); return sbuf(res); } char *rmalloc_stats() { static char res[300]; res[0] = 0; setlocale(LC_NUMERIC, "en_US.UTF-8"); sprintf(res, "Memory usage: %s, %s (re)allocated, %s unqiue free'd, %s in use.", rmalloc_bytes_format(0, rmalloc_total_bytes_allocated), rmalloc_lld_format(rmalloc_alloc_count), rmalloc_lld_format(rmalloc_free_count), rmalloc_lld_format(rmalloc_count)); setlocale(LC_NUMERIC, ""); return res; } #endif