wakaama/examples/shared/memtrace.c
David Navarro 8045de5fbd Remove platforms folder.
Signed-off-by: David Navarro <david.navarro@intel.com>
2016-04-07 22:45:37 +02:00

183 lines
5.5 KiB
C

/*******************************************************************************
*
* Copyright (c) 2015 Bosch Software Innvoations GmbH and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* The Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Bosch Software Innovations GmbH - Please refer to git log
*
*******************************************************************************/
#include "internals.h"
#ifdef LWM2M_MEMORY_TRACE
#undef malloc
#undef free
#undef strdup
typedef struct MemoryEntry {
struct MemoryEntry* next;
const char *file;
const char *function;
int lineno;
size_t size;
int count;
uint32_t data[1];
} memory_entry_t;
static memory_entry_t prv_memory_malloc_list = { .next = NULL, .file = "head", .function="malloc", .lineno = 0, .size = 0, .count = 0};
static memory_entry_t prv_memory_free_list = { .next = NULL, .file = "head", .function="free", .lineno = 0, .size = 0, .count = 0};
static memory_entry_t* prv_memory_find_previous(memory_entry_t* list, void* memory)
{
while (NULL != list->next)
{
if (list->next->data == memory)
{
return list;
}
list = list->next;
}
return NULL;
}
static void prv_trace_add_free_list(memory_entry_t* remove, const char* file, const char* function, int lineno)
{
remove->next = prv_memory_free_list.next;
prv_memory_free_list.next = remove;
remove->file = file;
remove->function = function;
remove->lineno = lineno;
if (prv_memory_free_list.count < 200)
{
++prv_memory_free_list.count;
}
else if (NULL != remove->next)
{
while (NULL != remove->next->next)
{
remove = remove->next;
}
free(remove->next);
remove->next = NULL;
}
}
char* lwm2m_trace_strdup(const char* str, const char* file, const char* function, int lineno)
{
size_t length = strlen(str);
char* result = lwm2m_trace_malloc(length +1, file, function, lineno);
memcpy(result, str, length);
result[length] = 0;
return result;
}
void* lwm2m_trace_malloc(size_t size, const char* file, const char* function, int lineno)
{
static int counter = 0;
memory_entry_t* entry = malloc(size + sizeof(memory_entry_t));
entry->next = prv_memory_malloc_list.next;
prv_memory_malloc_list.next = entry;
++prv_memory_malloc_list.count;
prv_memory_malloc_list.size += size;
prv_memory_malloc_list.lineno = 1;
entry->file = file;
entry->function = function;
entry->lineno = lineno;
entry->size = size;
entry->count = ++counter;
return &(entry->data);
}
void lwm2m_trace_free(void* mem, const char* file, const char* function, int lineno)
{
if (NULL != mem)
{
memory_entry_t* entry = prv_memory_find_previous(&prv_memory_malloc_list, mem);
if (NULL != entry)
{
memory_entry_t* remove = entry->next;
entry->next = remove->next;
--prv_memory_malloc_list.count;
prv_memory_malloc_list.size -= remove->size;
prv_memory_malloc_list.lineno = 1;
prv_trace_add_free_list(remove, file, function, lineno);
}
else
{
fprintf(stderr, "memory: free error (no malloc) %s, %d, %s\n", file, lineno, function);
memory_entry_t* entry = prv_memory_find_previous(&prv_memory_free_list, mem);
if (NULL != entry)
{
entry = entry->next;
fprintf(stderr, "memory: already frees at %s, %d, %s\n", entry->file, entry->lineno, entry->function);
}
}
}
}
void trace_print(int loops, int level)
{
static int counter = 0;
if (0 == loops)
{
counter = 0;
}
else
{
++counter;
}
if (0 == loops || (((counter % loops) == 0) && prv_memory_malloc_list.lineno))
{
prv_memory_malloc_list.lineno = 0;
if (1 == level)
{
size_t total = 0;
int entries = 0;
memory_entry_t* entry = prv_memory_malloc_list.next;
while (NULL != entry)
{
fprintf(stdout,"memory: #%d, %lu bytes, %s, %d, %s\n", entry->count, (unsigned long) entry->size, entry->file, entry->lineno, entry->function);
++entries;
total += entry->size;
entry = entry->next;
}
if (entries != prv_memory_malloc_list.count)
{
fprintf(stderr,"memory: error %d entries != %d\n", prv_memory_malloc_list.count, entries);
}
if (total != prv_memory_malloc_list.size)
{
fprintf(stdout,"memory: error %lu total bytes != %lu\n", (unsigned long) prv_memory_malloc_list.size, (unsigned long) total);
}
}
fprintf(stdout,"memory: %d entries, %lu total bytes\n", prv_memory_malloc_list.count, (unsigned long) prv_memory_malloc_list.size);
}
}
void trace_status(int* blocks, size_t* size)
{
if (NULL != blocks)
{
*blocks = prv_memory_malloc_list.count;
}
if (NULL != size)
{
*size = prv_memory_malloc_list.size;
}
}
#endif