1
0
Fork 0
forked from lda/telodendria

Add custom memory management code.

This will be helpful in detecting leaks among other things, and may help
with controlling the cache size as well.
This commit is contained in:
Jordan Bancino 2022-10-12 21:29:05 -04:00
parent ad7c486501
commit 2d49ac78b8
2 changed files with 301 additions and 0 deletions

272
src/Memory.c Normal file
View file

@ -0,0 +1,272 @@
#include <Memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct MemoryInfo
{
size_t size;
const char *file;
const char *func;
int line;
void *pointer;
MemoryInfo *next;
MemoryInfo *prev;
};
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static MemoryInfo *lastAllocation = NULL;
void *
MemoryAllocate(size_t size, const char *file, int line, const char *func)
{
void *p;
MemoryInfo *a;
pthread_mutex_lock(&lock);
p = malloc(size);
if (!p)
{
pthread_mutex_unlock(&lock);
return NULL;
}
a = malloc(sizeof(MemoryInfo));
if (!a)
{
free(p);
pthread_mutex_unlock(&lock);
return NULL;
}
a->size = size;
a->file = file;
a->line = line;
a->func = func;
a->pointer = p;
a->next = NULL;
a->prev = lastAllocation;
if (lastAllocation)
{
lastAllocation->next = a;
}
lastAllocation = a;
pthread_mutex_unlock(&lock);
return p;
}
void *
MemoryReallocate(void *p, size_t size)
{
MemoryInfo *a;
void *new = NULL;
pthread_mutex_lock(&lock);
a = lastAllocation;
while (a)
{
if (a->pointer == p)
{
new = realloc(p, size);
if (new)
{
a->pointer = new;
a->size = size;
}
break;
}
a = a->prev;
}
pthread_mutex_unlock(&lock);
return new;
}
void
MemoryFree(void *p)
{
MemoryInfo *a;
pthread_mutex_lock(&lock);
a = lastAllocation;
while (a)
{
if (a->pointer == p)
{
if (a->prev)
{
a->prev->next = a->next;
}
else
{
lastAllocation = a->next;
}
if (a->next)
{
a->next->prev = a->prev;
}
else
{
lastAllocation = a->prev;
}
free(a);
free(p);
break;
}
a = a->prev;
}
pthread_mutex_unlock(&lock);
}
size_t
MemoryAllocated(void)
{
MemoryInfo *a;
size_t total = 0;
pthread_mutex_lock(&lock);
a = lastAllocation;
while (a)
{
total += a->size;
a = a->prev;
}
pthread_mutex_unlock(&lock);
return total;
}
void
MemoryFreeAll(void)
{
MemoryInfo *a;
pthread_mutex_lock(&lock);
a = lastAllocation;
while (a)
{
MemoryInfo *prev = a->prev;
free(a->pointer);
free(a);
a = prev;
}
lastAllocation = NULL;
pthread_mutex_unlock(&lock);
}
MemoryInfo *
MemoryInfoGet(void *p)
{
MemoryInfo *a;
pthread_mutex_lock(&lock);
a = lastAllocation;
while (a)
{
if (a->pointer == p)
{
break;
}
a = a->prev;
}
return a;
}
size_t
MemoryInfoGetSize(MemoryInfo *a)
{
if (!a)
{
return 0;
}
return a->size;
}
const char *
MemoryInfoGetFile(MemoryInfo *a)
{
if (!a)
{
return NULL;
}
return a->file;
}
const char *
MemoryInfoGetFunc(MemoryInfo *a)
{
if (!a)
{
return NULL;
}
return a->func;
}
int
MemoryInfoGetLine(MemoryInfo *a)
{
if (!a)
{
return -1;
}
return a->line;
}
void *
MemoryInfoGetPointer(MemoryInfo *a)
{
if (!a)
{
return NULL;
}
return a->pointer;
}
void
MemoryIterate(void (*iterFunc)(MemoryInfo *, void *), void *args)
{
MemoryInfo *a;
pthread_mutex_lock(&lock);
a = lastAllocation;
while (a)
{
iterFunc(a, args);
a = a->prev;
}
pthread_mutex_unlock(&lock);
}

29
src/include/Memory.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef TELODENDRIA_MEMORY_H
#define TELODENDRIA_MEMORY_H
#include <stddef.h>
#define Malloc(x) MemoryAllocate(x, __FILE__, __LINE__, __FUNCTION__)
#define Realloc(x, s) MemoryReallocate(x, s)
#define Free(x) MemoryFree(x)
typedef struct MemoryInfo MemoryInfo;
extern void *MemoryAllocate(size_t, const char *, int, const char *);
extern void *MemoryReallocate(void *, size_t);
extern void MemoryFree(void *);
extern size_t MemoryAllocated(void);
extern void MemoryFreeAll(void);
extern MemoryInfo * MemoryInfoGet(void *);
extern size_t MemoryInfoGetSize(MemoryInfo *);
extern const char * MemoryInfoGetFile(MemoryInfo *);
extern const char * MemoryInfoGetFunc(MemoryInfo *);
extern int MemoryInfoGetLine(MemoryInfo *);
extern void * MemoryInfoGetPointer(MemoryInfo *);
extern void MemoryIterate(void (*)(MemoryInfo *, void *), void *);
#endif