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;
|
||||
const char *file;
|
||||
int line;
|
||||
void *pointer;
|
||||
|
||||
MemoryInfo *next;
|
||||
MemoryInfo *prev;
|
||||
|
@ -46,30 +45,20 @@ static void *hookArgs = NULL;
|
|||
void *
|
||||
MemoryAllocate(size_t size, const char *file, int line)
|
||||
{
|
||||
void *p;
|
||||
MemoryInfo *a;
|
||||
|
||||
pthread_mutex_lock(&lock);
|
||||
|
||||
p = malloc(size);
|
||||
if (!p)
|
||||
{
|
||||
pthread_mutex_unlock(&lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a = malloc(sizeof(MemoryInfo));
|
||||
a = malloc(sizeof(MemoryInfo) + size);
|
||||
if (!a)
|
||||
{
|
||||
free(p);
|
||||
pthread_mutex_unlock(&lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a->size = size;
|
||||
a->size = sizeof(MemoryInfo) + size;
|
||||
a->file = file;
|
||||
a->line = line;
|
||||
a->pointer = p;
|
||||
a->next = NULL;
|
||||
a->prev = lastAllocation;
|
||||
|
||||
|
@ -86,7 +75,7 @@ MemoryAllocate(size_t size, const char *file, int line)
|
|||
}
|
||||
|
||||
pthread_mutex_unlock(&lock);
|
||||
return p;
|
||||
return MemoryInfoGetPointer(a);
|
||||
}
|
||||
|
||||
void *
|
||||
|
@ -95,34 +84,55 @@ MemoryReallocate(void *p, size_t size)
|
|||
MemoryInfo *a;
|
||||
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);
|
||||
|
||||
a = lastAllocation;
|
||||
while (a)
|
||||
new = realloc(a, sizeof(MemoryInfo) + size);
|
||||
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);
|
||||
if (new)
|
||||
a->prev->next = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
a->pointer = new;
|
||||
a->size = size;
|
||||
lastAllocation = a;
|
||||
}
|
||||
|
||||
if (a->next)
|
||||
{
|
||||
a->next->prev = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastAllocation = a;
|
||||
}
|
||||
|
||||
if (hook)
|
||||
{
|
||||
hook(MEMORY_REALLOCATE, a, hookArgs);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
a = a->prev;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&lock);
|
||||
|
||||
return new;
|
||||
return MemoryInfoGetPointer(a);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -132,12 +142,17 @@ MemoryFree(void *p)
|
|||
|
||||
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)
|
||||
{
|
||||
a->prev->next = a->next;
|
||||
|
@ -162,13 +177,6 @@ MemoryFree(void *p)
|
|||
}
|
||||
|
||||
free(a);
|
||||
free(p);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
a = a->prev;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
|
@ -205,9 +213,7 @@ MemoryFreeAll(void)
|
|||
{
|
||||
MemoryInfo *prev = a->prev;
|
||||
|
||||
free(a->pointer);
|
||||
free(a);
|
||||
|
||||
a = prev;
|
||||
}
|
||||
|
||||
|
@ -221,12 +227,18 @@ MemoryInfoGet(void *p)
|
|||
{
|
||||
MemoryInfo *a;
|
||||
|
||||
pthread_mutex_lock(&lock);
|
||||
if (!p)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = &(((MemoryInfo *) p)[-1]);
|
||||
|
||||
a = lastAllocation;
|
||||
|
||||
while (a)
|
||||
{
|
||||
if (a->pointer == p)
|
||||
if (a == p)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -278,7 +290,7 @@ MemoryInfoGetPointer(MemoryInfo * a)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return a->pointer;
|
||||
return &(a[1]);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -57,6 +57,9 @@ TelodendriaMemoryHook(MemoryAction a, MemoryInfo * i, void *args)
|
|||
case MEMORY_FREE:
|
||||
action = "Freed";
|
||||
break;
|
||||
case MEMORY_BAD_POINTER:
|
||||
Log(lc, LOG_WARNING, "Bad pointer passed into a memory function.");
|
||||
return;
|
||||
default:
|
||||
action = "Unknown operation on";
|
||||
break;
|
||||
|
@ -76,9 +79,9 @@ TelodendriaMemoryIterator(MemoryInfo * i, void *args)
|
|||
/* We haven't freed the logger memory yet */
|
||||
if (MemoryInfoGetPointer(i) != lc)
|
||||
{
|
||||
Log(lc, LOG_DEBUG, "%lu bytes of memory at %p leaked from %s:%d",
|
||||
MemoryInfoGetSize(i), MemoryInfoGetPointer(i),
|
||||
MemoryInfoGetFile(i), MemoryInfoGetLine(i));
|
||||
Log(lc, LOG_WARNING, "%s:%d: %lu bytes of memory at %p leaked.",
|
||||
MemoryInfoGetFile(i), MemoryInfoGetLine(i),
|
||||
MemoryInfoGetSize(i), MemoryInfoGetPointer(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,6 +151,8 @@ main(int argc, char **argv)
|
|||
|
||||
MatrixHttpHandlerArgs matrixArgs;
|
||||
|
||||
memset(&matrixArgs, 0, sizeof(matrixArgs));
|
||||
|
||||
lc = LogConfigCreate();
|
||||
|
||||
if (!lc)
|
||||
|
|
|
@ -30,7 +30,8 @@ typedef enum MemoryAction
|
|||
{
|
||||
MEMORY_ALLOCATE,
|
||||
MEMORY_REALLOCATE,
|
||||
MEMORY_FREE
|
||||
MEMORY_FREE,
|
||||
MEMORY_BAD_POINTER
|
||||
} MemoryAction;
|
||||
|
||||
#define Malloc(x) MemoryAllocate(x, __FILE__, __LINE__)
|
||||
|
|
Loading…
Reference in a new issue