forked from Telodendria/Telodendria
Store memory info in the allocated block, not as a separate block.
This will eventually enable us to get memory information in O(1) time. Right now, we're still O(n) because MemoryInfoGet() still has to check to see if the allocation is known or not.
This commit is contained in:
parent
2791dbdcc8
commit
bcff59bacb
3 changed files with 92 additions and 74 deletions
104
src/Memory.c
104
src/Memory.c
|
@ -32,7 +32,6 @@ struct MemoryInfo
|
||||||
size_t size;
|
size_t size;
|
||||||
const char *file;
|
const char *file;
|
||||||
int line;
|
int line;
|
||||||
void *pointer;
|
|
||||||
|
|
||||||
MemoryInfo *next;
|
MemoryInfo *next;
|
||||||
MemoryInfo *prev;
|
MemoryInfo *prev;
|
||||||
|
@ -46,30 +45,20 @@ static void *hookArgs = NULL;
|
||||||
void *
|
void *
|
||||||
MemoryAllocate(size_t size, const char *file, int line)
|
MemoryAllocate(size_t size, const char *file, int line)
|
||||||
{
|
{
|
||||||
void *p;
|
|
||||||
MemoryInfo *a;
|
MemoryInfo *a;
|
||||||
|
|
||||||
pthread_mutex_lock(&lock);
|
pthread_mutex_lock(&lock);
|
||||||
|
|
||||||
p = malloc(size);
|
a = malloc(sizeof(MemoryInfo) + size);
|
||||||
if (!p)
|
|
||||||
{
|
|
||||||
pthread_mutex_unlock(&lock);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = malloc(sizeof(MemoryInfo));
|
|
||||||
if (!a)
|
if (!a)
|
||||||
{
|
{
|
||||||
free(p);
|
|
||||||
pthread_mutex_unlock(&lock);
|
pthread_mutex_unlock(&lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
a->size = size;
|
a->size = sizeof(MemoryInfo) + size;
|
||||||
a->file = file;
|
a->file = file;
|
||||||
a->line = line;
|
a->line = line;
|
||||||
a->pointer = p;
|
|
||||||
a->next = NULL;
|
a->next = NULL;
|
||||||
a->prev = lastAllocation;
|
a->prev = lastAllocation;
|
||||||
|
|
||||||
|
@ -86,7 +75,7 @@ MemoryAllocate(size_t size, const char *file, int line)
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&lock);
|
pthread_mutex_unlock(&lock);
|
||||||
return p;
|
return MemoryInfoGetPointer(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
|
@ -95,34 +84,55 @@ MemoryReallocate(void *p, size_t size)
|
||||||
MemoryInfo *a;
|
MemoryInfo *a;
|
||||||
void *new = NULL;
|
void *new = NULL;
|
||||||
|
|
||||||
|
a = MemoryInfoGet(p);
|
||||||
|
|
||||||
|
if (!a)
|
||||||
|
{
|
||||||
|
if (hook)
|
||||||
|
{
|
||||||
|
hook(MEMORY_BAD_POINTER, NULL, hookArgs);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&lock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&lock);
|
pthread_mutex_lock(&lock);
|
||||||
|
|
||||||
a = lastAllocation;
|
new = realloc(a, sizeof(MemoryInfo) + size);
|
||||||
while (a)
|
if (!new)
|
||||||
{
|
{
|
||||||
if (a->pointer == p)
|
pthread_mutex_unlock(&lock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
a = new;
|
||||||
|
a->size = sizeof(MemoryInfo) + size;
|
||||||
|
|
||||||
|
if (a->prev)
|
||||||
{
|
{
|
||||||
new = realloc(p, size);
|
a->prev->next = a;
|
||||||
if (new)
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
a->pointer = new;
|
lastAllocation = a;
|
||||||
a->size = size;
|
}
|
||||||
|
|
||||||
|
if (a->next)
|
||||||
|
{
|
||||||
|
a->next->prev = a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastAllocation = a;
|
||||||
|
}
|
||||||
|
|
||||||
if (hook)
|
if (hook)
|
||||||
{
|
{
|
||||||
hook(MEMORY_REALLOCATE, a, hookArgs);
|
hook(MEMORY_REALLOCATE, a, hookArgs);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = a->prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&lock);
|
pthread_mutex_unlock(&lock);
|
||||||
|
|
||||||
return new;
|
return MemoryInfoGetPointer(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -132,12 +142,17 @@ MemoryFree(void *p)
|
||||||
|
|
||||||
pthread_mutex_lock(&lock);
|
pthread_mutex_lock(&lock);
|
||||||
|
|
||||||
a = lastAllocation;
|
a = MemoryInfoGet(p);
|
||||||
|
if (!a)
|
||||||
|
{
|
||||||
|
if (hook)
|
||||||
|
{
|
||||||
|
hook(MEMORY_BAD_POINTER, NULL, hookArgs);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (a)
|
|
||||||
{
|
|
||||||
if (a->pointer == p)
|
|
||||||
{
|
|
||||||
if (a->prev)
|
if (a->prev)
|
||||||
{
|
{
|
||||||
a->prev->next = a->next;
|
a->prev->next = a->next;
|
||||||
|
@ -162,13 +177,6 @@ MemoryFree(void *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
free(a);
|
free(a);
|
||||||
free(p);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = a->prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&lock);
|
pthread_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
@ -205,9 +213,7 @@ MemoryFreeAll(void)
|
||||||
{
|
{
|
||||||
MemoryInfo *prev = a->prev;
|
MemoryInfo *prev = a->prev;
|
||||||
|
|
||||||
free(a->pointer);
|
|
||||||
free(a);
|
free(a);
|
||||||
|
|
||||||
a = prev;
|
a = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,12 +227,18 @@ MemoryInfoGet(void *p)
|
||||||
{
|
{
|
||||||
MemoryInfo *a;
|
MemoryInfo *a;
|
||||||
|
|
||||||
pthread_mutex_lock(&lock);
|
if (!p)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = &(((MemoryInfo *) p)[-1]);
|
||||||
|
|
||||||
a = lastAllocation;
|
a = lastAllocation;
|
||||||
|
|
||||||
while (a)
|
while (a)
|
||||||
{
|
{
|
||||||
if (a->pointer == p)
|
if (a == p)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -278,7 +290,7 @@ MemoryInfoGetPointer(MemoryInfo * a)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return a->pointer;
|
return &(a[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -57,6 +57,9 @@ TelodendriaMemoryHook(MemoryAction a, MemoryInfo * i, void *args)
|
||||||
case MEMORY_FREE:
|
case MEMORY_FREE:
|
||||||
action = "Freed";
|
action = "Freed";
|
||||||
break;
|
break;
|
||||||
|
case MEMORY_BAD_POINTER:
|
||||||
|
Log(lc, LOG_WARNING, "Bad pointer passed into a memory function.");
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
action = "Unknown operation on";
|
action = "Unknown operation on";
|
||||||
break;
|
break;
|
||||||
|
@ -76,9 +79,9 @@ TelodendriaMemoryIterator(MemoryInfo * i, void *args)
|
||||||
/* We haven't freed the logger memory yet */
|
/* We haven't freed the logger memory yet */
|
||||||
if (MemoryInfoGetPointer(i) != lc)
|
if (MemoryInfoGetPointer(i) != lc)
|
||||||
{
|
{
|
||||||
Log(lc, LOG_DEBUG, "%lu bytes of memory at %p leaked from %s:%d",
|
Log(lc, LOG_WARNING, "%s:%d: %lu bytes of memory at %p leaked.",
|
||||||
MemoryInfoGetSize(i), MemoryInfoGetPointer(i),
|
MemoryInfoGetFile(i), MemoryInfoGetLine(i),
|
||||||
MemoryInfoGetFile(i), MemoryInfoGetLine(i));
|
MemoryInfoGetSize(i), MemoryInfoGetPointer(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,6 +151,8 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
MatrixHttpHandlerArgs matrixArgs;
|
MatrixHttpHandlerArgs matrixArgs;
|
||||||
|
|
||||||
|
memset(&matrixArgs, 0, sizeof(matrixArgs));
|
||||||
|
|
||||||
lc = LogConfigCreate();
|
lc = LogConfigCreate();
|
||||||
|
|
||||||
if (!lc)
|
if (!lc)
|
||||||
|
|
|
@ -30,7 +30,8 @@ typedef enum MemoryAction
|
||||||
{
|
{
|
||||||
MEMORY_ALLOCATE,
|
MEMORY_ALLOCATE,
|
||||||
MEMORY_REALLOCATE,
|
MEMORY_REALLOCATE,
|
||||||
MEMORY_FREE
|
MEMORY_FREE,
|
||||||
|
MEMORY_BAD_POINTER
|
||||||
} MemoryAction;
|
} MemoryAction;
|
||||||
|
|
||||||
#define Malloc(x) MemoryAllocate(x, __FILE__, __LINE__)
|
#define Malloc(x) MemoryAllocate(x, __FILE__, __LINE__)
|
||||||
|
|
Loading…
Reference in a new issue