#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <termios.h>
#include "string.h"
#include "debug.h"
#include "btracer.h"
void * btracer_malloc(int size, const char *moudle, int line);
void btracer_free(void *p);
static mem_header_t s_mem_list_head =
{
.magic_number = MEM_DEBUG_MAGIC_NUMBER,
.next = NULL,
.prev = NULL,
.size = 0,
.comment = "HEAD",
.line = 0,
};
static int block_list_insert(mem_header_t *header)
{
if (!header) {
return -1;
}
// TODO: thread safe operations
// mutex_lock
mem_header_t *p = s_mem_list_head.next;
s_mem_list_head.next = header;
header->next = p;
header->prev = &s_mem_list_head;
if (header->next) {
header->next->prev = header;
}
// TODO: thread safe operations
// mutex_unlock
return 0;
}
static int block_list_delete(mem_header_t *header)
{
if (!header) {
return -1;
}
// DUDO_LOGI("%.8X\n", header);
// TODO: thread safe operations
// mutex_lock
if (header->prev) {
header->prev->next = header->next;
}
if (header->next) {
header->next->prev = header->prev;
}
// TODO: thread safe operations
// mutex_unlock
return 0;
}
void * btracer_malloc(int size, const char *moudle, int line)
{
if (!size) {
return NULL;
}
mem_header_t *header = malloc(size + sizeof(mem_header_t));
if (header) {
header->magic_number = MEM_DEBUG_MAGIC_NUMBER;
header->next = NULL;
header->prev = NULL;
header->size = size;
header->comment = moudle;
header->line = line;
block_list_insert(header);
// DUDO_LOGI("size:%d, comment:%s, line:%d",
// header->size, header->comment, header->line);
// DUDO_LOGI("header:%.8X\n", header);
return (void *)((char *)header + sizeof(mem_header_t));
} else {
return NULL;
}
}
void * btracer_realloc(void *p, int size, const char *moudle, int line)
{
if (!size) {
return NULL;
}
mem_header_t *header = (mem_header_t *)((unsigned long)p - sizeof(mem_header_t));
// 1. remove old block from list, this operation has to be performed befor realloc executed,
// because new address is different with old address.
block_list_delete(header);
// 2. reallocate memory space, please remember that new address is different with old address.
void *new = realloc(header, size + sizeof(mem_header_t));
if (!new) {
// 3. if realloc failed, insert old block to block list.
block_list_insert(header);
return NULL;
}
// 4. create new block and insert into list
header = (mem_header_t *)new;
if (header) {
header->magic_number = MEM_DEBUG_MAGIC_NUMBER;
header->next = NULL;
header->prev = NULL;
header->size = size;
header->comment = moudle;
header->line = line;
block_list_insert(header);
return (void *)((char *)header + sizeof(mem_header_t));
} else {
return NULL;
}
}
void btracer_free(void *p)
{
if (!p) {
return;
}
mem_header_t *header = (mem_header_t *)((unsigned long)p - sizeof(mem_header_t));
// DUDO_LOGI("size:%d, comment:%s, line:%d",
// header->size, header->comment, header->line);
// DUDO_LOGI("header:%.8X\n", header);
block_list_delete(header);
free(header);
}
void btracer_trace(void)
{
int used_cnt = 0;
int total_size = 0;
mem_header_t *p = s_mem_list_head.next;
while (p) {
DUDO_LOGI("h:%.8X, p:%.8X, s:%4d, m:\"%16s\", l:%4d",
(uint32_t)p, (uint32_t)p + sizeof(mem_header_t), p->size, p->comment, p->line);
used_cnt++;
total_size += p->size;
p = p->next;
}
DUDO_LOGI("\n");
DUDO_LOGI("Block count:%d\n", used_cnt);
DUDO_LOGI("Total memory size:%d\n", total_size);
DUDO_LOGI("Total memory footprint:%d\n", total_size + used_cnt * sizeof(mem_header_t));
}
#ifndef __BTRACER_H__
#define __BTRACER_H__
#include "stdint.h"
#define MEM_DEBUG_MAGIC_NUMBER 0x55AA55AA
#define MALLOC(_SIZE) btracer_malloc(_SIZE, __FUNCTION__, __LINE__)
#define REALLOC(_P, _SIZE) btracer_realloc(_P, _SIZE, __FUNCTION__, __LINE__)
#define FREE(_P) btracer_free(_P)
typedef struct mem_header
{
unsigned int magic_number;
struct mem_header *prev;
struct mem_header *next;
unsigned int size;
char *comment;
int line;
} mem_header_t;
void * btracer_malloc(int size, const char *moudle, int line);
void btracer_free(void *p);
void btracer_trace(void);
#endif
BEDO
TODO
DONE