117 lines
3.7 KiB
C
117 lines
3.7 KiB
C
|
|
#include "guf_common.h"
|
|
#include "guf_alloc.h"
|
|
#include "math.h"
|
|
|
|
typedef struct guf_alloc_tracker {
|
|
FILE *log, *err_log;
|
|
size_t alloc_count, realloc_count, free_count;
|
|
ptrdiff_t allocated_bytes;
|
|
uint32_t id;
|
|
} guf_alloc_tracker;
|
|
|
|
static bool guf_track_alloc(guf_alloc_tracker *t, ptrdiff_t size)
|
|
{
|
|
GUF_ASSERT(t);
|
|
GUF_ASSERT(size >= 0);
|
|
bool success = true;
|
|
if (t->err_log && t->alloc_count == SIZE_MAX) {
|
|
fprintf(t->err_log, "guf_alloc_track (id %" PRIu32 ") WARNING: alloc_count overflow\n", t->id);
|
|
//success = false;
|
|
}
|
|
t->alloc_count = guf_add_saturated_size_t(t->alloc_count, 1);
|
|
|
|
if (guf_add_is_overflow_ptrdiff(t->allocated_bytes, size)) {
|
|
if (t->err_log) {
|
|
fprintf(t->err_log, "guf_alloc_track (id %" PRIu32 ") ERROR: allocated_byte overflow\n", t->id);
|
|
}
|
|
success = false;
|
|
}
|
|
t->allocated_bytes = guf_add_saturated_ptrdiff(t->allocated_bytes, size);
|
|
if (t->allocated_bytes < 0) {
|
|
if (t->err_log) {
|
|
fprintf(t->err_log, "guf_alloc_track (id %" PRIu32 ") ERROR: allocated_bytes < 0\n", t->id);
|
|
}
|
|
success = false;
|
|
}
|
|
|
|
if (t->log) {
|
|
fprintf(t->log, "guf_alloc_track (id %" PRIu32 "): alloc (%td bytes) %s\n", t->id, size, success ? "SUCCESS" : "FAILURE");
|
|
}
|
|
return success;
|
|
}
|
|
|
|
|
|
static bool guf_track_realloc(guf_alloc_tracker *t, ptrdiff_t old_size, ptrdiff_t new_size)
|
|
{
|
|
GUF_ASSERT(t);
|
|
GUF_ASSERT(old_size >= 0 && new_size >= 0);
|
|
bool success = true;
|
|
if (t->err_log && t->realloc_count == SIZE_MAX) {
|
|
fprintf(t->err_log, "guf_realloc_track (id %" PRIu32 ") WARNING: realloc_count overflow\n");
|
|
//success = false;
|
|
}
|
|
t->realloc_count = guf_add_saturated_size_t(t->realloc_count, 1);
|
|
|
|
if (old_size < 0 || new_size < 0) {
|
|
if (t->err_log) {
|
|
fprintf(t->err_log, "guf_realloc_track (id %" PRIu32 ") ERROR: old_size < 0 or new_size < 0\n");
|
|
}
|
|
success = false;
|
|
}
|
|
|
|
t->allocated_bytes = guf_sub_saturated_ptrdiff(t->allocated_bytes, old_size);
|
|
if (t->allocated_bytes < 0) {
|
|
success = false;
|
|
fprintf(t->err_log, "guf_realloc_track (id %" PRIu32 ") ERROR: allocated_bytes < 0 after subtracting old_size\n", t->id);
|
|
}
|
|
if (guf_add_is_overflow_ptrdiff(t->allocated_bytes, new_size)) {
|
|
success = false;
|
|
if (t->err_log) {
|
|
fprintf(t->err_log, "guf_realloc_track (id %" PRIu32 ") ERROR: allocated_bytes overflow \n");
|
|
}
|
|
}
|
|
t->allocated_bytes = guf_add_saturated_ptrdiff(t->allocated_bytes, new_size);
|
|
|
|
if (t->allocated_bytes < 0) {
|
|
success = false;
|
|
fprintf(t->err_log, "guf_realloc_track (id %" PRIu32 ") ERROR: allocated_bytes < 0 after adding new_size\n", t->id);
|
|
}
|
|
|
|
if (t->log) {
|
|
fprintf(t->log, "guf_realloc_track (id %" PRIu32 "): realloc (from %td to %td bytes) %s", t->id, old_size, new_size, (success ? "SUCCESS" : "FAILURE"));
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
static bool guf_track_free(guf_alloc_tracker *t, ptrdiff_t size)
|
|
{
|
|
GUF_ASSERT(t);
|
|
GUF_ASSERT(size >= 0);
|
|
|
|
if (t->err_log && t->free_count == SIZE_MAX) {
|
|
fprintf(t->err_log, "guf_track_free (id %" PRIu32 ") WARNING: free_count overflow\n");
|
|
}
|
|
bool success = true;
|
|
|
|
if (size < 0) {
|
|
success = false;
|
|
if (t->err_log) {
|
|
fprintf(t->err_log, "guf_track_free (id %" PRIu32 ") ERROR: size < 0\n");
|
|
}
|
|
}
|
|
|
|
if (t->allocated_bytes < size) {
|
|
success = false;
|
|
if (t->err_log) {
|
|
fprintf(t->err_log, "guf_track_free (id %" PRIu32 ") ERROR: freed more bytes than allocated\n");
|
|
}
|
|
}
|
|
t->allocated_bytes = guf_sub_saturated_ptrdiff(t->allocated_bytes, size);
|
|
|
|
return success;
|
|
}
|
|
|
|
|