[oasl]: Add debug function to mpp_mem

1. Add memory node record.
2. Add runtime log with memory count and total size.
3. Add extra room for overflow detection.
4. Add memory poison after free to detect write after free.

Change-Id: I4f0fe7295f18a746c3b4c135681127a18337585e
Signed-off-by: Herman Chen <herman.chen@rock-chips.com>
This commit is contained in:
Herman Chen 2018-01-24 18:22:40 +08:00
parent c8baa3490a
commit 82bc016bbb
3 changed files with 670 additions and 226 deletions

View File

@ -22,25 +22,26 @@
#include "rk_type.h"
#include "mpp_err.h"
#define mpp_malloc_tagged(type, count, tag) \
(type*)mpp_osal_malloc(tag, sizeof(type) * (count))
#define mpp_malloc_with_caller(type, count, caller) \
(type*)mpp_osal_malloc(caller, sizeof(type) * (count))
#define mpp_malloc(type, count) \
(type*)mpp_osal_malloc(MODULE_TAG, sizeof(type) * (count))
(type*)mpp_osal_malloc(__FUNCTION__, sizeof(type) * (count))
#define mpp_malloc_size(type, size) \
(type*)mpp_osal_malloc(MODULE_TAG, size)
(type*)mpp_osal_malloc(__FUNCTION__, size)
#define mpp_calloc_size(type, size) \
(type*)mpp_osal_calloc(MODULE_TAG, size)
(type*)mpp_osal_calloc(__FUNCTION__, size)
#define mpp_calloc(type, count) \
(type*)mpp_osal_calloc(MODULE_TAG, sizeof(type) * (count))
(type*)mpp_osal_calloc(__FUNCTION__, sizeof(type) * (count))
#define mpp_realloc(ptr, type, count) \
(type*)mpp_osal_realloc(MODULE_TAG, ptr, sizeof(type) * (count))
(type*)mpp_osal_realloc(__FUNCTION__, ptr, sizeof(type) * (count))
#define mpp_free(ptr) mpp_osal_free(ptr)
#define mpp_free(ptr) \
mpp_osal_free(__FUNCTION__, ptr)
#define MPP_FREE(ptr) do { if(ptr) mpp_free(ptr); ptr = NULL; } while (0)
#define MPP_FCLOSE(fp) do { if(fp) fclose(fp); fp = NULL; } while (0)
@ -49,10 +50,10 @@
extern "C" {
#endif
void *mpp_osal_malloc(const char *tag, size_t size);
void *mpp_osal_calloc(const char *tag, size_t size);
void *mpp_osal_realloc(const char *tag, void *ptr, size_t size);
void mpp_osal_free(void *ptr);
void *mpp_osal_malloc(const char *caller, size_t size);
void *mpp_osal_calloc(const char *caller, size_t size);
void *mpp_osal_realloc(const char *caller, void *ptr, size_t size);
void mpp_osal_free(const char *caller, void *ptr);
void mpp_show_mem_status();

View File

@ -29,272 +29,716 @@
#include "os_mem.h"
// mpp_mem_flag bit mask
#define OSAL_MEM_LIST_EN (0x00000001)
#define OSAL_MEM_RUNTIME_LOG (0x00000002)
// mpp_mem_debug bit mask
#define MEM_DEBUG_EN (0x00000001)
// NOTE: runtime log need debug enable
#define MEM_RUNTIME_LOG (0x00000002)
#define MEM_NODE_LOG (0x00000004)
#define MEM_EXT_ROOM (0x00000010)
#define MEM_POISON (0x00000020)
// default memory align size is set to 32
#define RK_OSAL_MEM_ALIGN 32
#define MEM_MAX_INDEX (0x7fffffff)
#define MEM_ALIGN 32
#define MEM_ALIGN_MASK (MEM_ALIGN - 1)
#define MEM_ALIGNED(x) (((x) + MEM_ALIGN) & (~MEM_ALIGN_MASK))
#define MEM_HEAD_ROOM(debug) ((debug & MEM_EXT_ROOM) ? (MEM_ALIGN) : (0))
#define MEM_NODE_MAX (1024)
#define MEM_FREE_MAX (512)
#define MEM_LOG_MAX (1024)
#define MEM_CHECK_MARK (0xdd)
#define MEM_HEAD_MASK (0xab)
#define MEM_TAIL_MASK (0xcd)
static RK_U32 mpp_mem_flag = 0;
static RK_U64 osal_mem_index = 0;
static struct list_head mem_list;
static pthread_mutex_t mem_list_lock;
#define MPP_MEM_ASSERT(cond) \
do { \
if (!(cond)) { \
mpp_err("found mpp_mem assert failed, start dumping:\n"); \
service.dump(__FUNCTION__); \
mpp_assert(cond); \
} \
} while (0)
struct mem_node {
struct list_head list;
void *ptr;
size_t size;
RK_U64 index;
typedef enum MppMemOps_e {
MEM_MALLOC,
MEM_REALLOC,
MEM_FREE,
MEM_FREE_DELAY,
/* memory node extra information */
char tag[MPP_TAG_SIZE];
MEM_OPS_BUTT,
} MppMemOps;
/*
* Here we combined valid flag with index value to keep node structure small
* If index >= 0 this node is valid otherwise it is invalid
* When we need to invalid one index use ~ to revert all bit
* Then max valid index is 0x7fffffff. When index goes beyond it and becomes
* negative value index will be reset to zero.
*/
typedef struct MppMemNode_s {
RK_S32 index;
size_t size;
void *ptr;
const char *caller;
} MppMemNode;
typedef struct MppMemLog_s {
RK_U32 index;
MppMemOps ops;
size_t size_0; // size at input
size_t size_1; // size at output
void *ptr; // ptr at input
void *ret; // ptr at output
MppMemNode *node; // node for operation
const char *caller;
} MppMemLog;
class MppMemService
{
public:
// avoid any unwanted function
MppMemService();
~MppMemService();
void add_node(const char *caller, void *ptr, size_t size);
/*
* try delete node will return index in nodes
* return 1 for need os_free call to real free
* return 0 for reserve memory for check
*/
RK_S32 find_node(const char *caller, void *ptr, size_t *size, RK_S32 *idx);
/*
*/
void del_node(const char *caller, void *ptr, size_t *size);
void* delay_del_node(const char *caller, void *ptr, size_t *size);
void reset_node(const char *caller, void *ptr, void *ret, size_t size);
void chk_node(const char *caller, MppMemNode *node);
void chk_mem(const char *caller, void *ptr, size_t size);
RK_S32 chk_poison(MppMemNode *node);
void add_log(MppMemOps ops, const char *caller, void *ptr, void *ret,
size_t size_0, size_t size_1);
void dump(const char *caller);
Mutex lock;
RK_U32 debug;
private:
// data for node record and delay free check
RK_S32 nodes_max;
RK_S32 nodes_idx;
RK_S32 nodes_cnt;
RK_S32 frees_max;
RK_S32 frees_idx;
RK_S32 frees_cnt;
MppMemNode *nodes;
MppMemNode *frees;
// data for log record
RK_U32 log_index;
RK_S32 log_max;
RK_S32 log_idx;
RK_S32 log_cnt;
MppMemLog *logs;
RK_U32 total_size;
MppMemService(const MppMemService &);
MppMemService &operator=(const MppMemService &);
};
static void get_osal_mem_flag()
static MppMemService service;
static const char *ops2str[MEM_OPS_BUTT] = {
"malloc",
"realloc",
"free",
"delayed",
};
static void show_mem(RK_U32 *buf, RK_S32 size)
{
static RK_U32 once = 1;
if (once) {
mpp_env_get_u32("mpp_mem_flag", &mpp_mem_flag, 0);
mpp_err("dumping buf %p size %d start\n", buf, size);
while (size > 0) {
if (size >= 16) {
mpp_err("%08x %08x %08x %08x\n", buf[0], buf[1], buf[2], buf[3]);
buf += 4;
size -= 16;
} else if (size >= 12) {
mpp_err("%08x %08x %08x\n", buf[0], buf[1], buf[2]);
buf += 3;
size -= 12;
} else if (size >= 8) {
mpp_err("%08x %08x\n", buf[0], buf[1]);
buf += 2;
size -= 8;
} else if (size >= 4) {
mpp_err("%08x\n", buf[0]);
buf += 1;
size -= 4;
} else {
mpp_log("end with size %d\n", size);
break;
}
}
mpp_err("dumping buf %p size %d end\n", buf, size);
}
INIT_LIST_HEAD(&mem_list);
static void set_mem_ext_room(void *p, size_t size)
{
memset((RK_U8 *)p - MEM_ALIGN, MEM_HEAD_MASK, MEM_ALIGN);
memset((RK_U8 *)p + size, MEM_TAIL_MASK, MEM_ALIGN);
}
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mem_list_lock, &attr);
pthread_mutexattr_destroy(&attr);
once = 0;
MppMemService::MppMemService()
: debug(0),
nodes_max(MEM_NODE_MAX),
nodes_idx(0),
nodes_cnt(0),
frees_max(MEM_FREE_MAX),
frees_idx(0),
frees_cnt(0),
nodes(NULL),
frees(NULL),
log_index(0),
log_max(MEM_LOG_MAX),
log_idx(0),
log_cnt(0),
logs(NULL),
total_size(0)
{
mpp_env_get_u32("mpp_mem_debug", &debug, 0);
// add more flag if debug enabled
if (debug)
debug |= MEM_DEBUG_EN;
if (debug & MEM_DEBUG_EN) {
mpp_env_get_u32("mpp_mem_node_max", (RK_U32 *)&nodes_max, MEM_NODE_MAX);
mpp_log_f("mpp_mem_debug enabled %x max node %d\n",
debug, nodes_max);
size_t size = nodes_max * sizeof(MppMemNode);
os_malloc((void **)&nodes, MEM_ALIGN, size);
mpp_assert(nodes);
memset(nodes, 0xff, size);
add_node(__FUNCTION__, nodes, size);
size = frees_max * sizeof(MppMemNode);
os_malloc((void **)&frees, MEM_ALIGN, size);
mpp_assert(frees);
memset(frees, 0xff, size);
add_node(__FUNCTION__, frees, size);
size = log_max * sizeof(MppMemLog);
os_malloc((void **)&logs, MEM_ALIGN, size);
mpp_assert(logs);
add_node(__FUNCTION__, logs, size);
add_node(__FUNCTION__, this, sizeof(MppMemService));
}
}
void *mpp_osal_malloc(const char *tag, size_t size)
MppMemService::~MppMemService()
{
if (debug & MEM_DEBUG_EN) {
AutoMutex auto_lock(&lock);
RK_S32 i = 0;
MppMemNode *node = nodes;
// delete self node first
size_t size = 0;
del_node(__FUNCTION__, this, &size);
del_node(__FUNCTION__, nodes, &size);
del_node(__FUNCTION__, frees, &size);
del_node(__FUNCTION__, logs, &size);
// then check leak memory
if (nodes_cnt) {
for (i = 0; i < nodes_max; i++, node++) {
if (node->index >= 0) {
mpp_log("found idx %8d mem %10p size %d leaked\n",
node->ptr, node->size);
nodes_cnt--;
add_log(MEM_FREE, __FUNCTION__, node->ptr, NULL,
node->size, 0);
}
}
mpp_assert(nodes_cnt == 0);
}
// finally release all delay free memory
if (frees_cnt) {
node = frees;
for (i = 0; i < frees_max; i++, node++) {
if (node->index >= 0) {
os_free((RK_U8 *)node->ptr - MEM_HEAD_ROOM(debug));
node->index = ~node->index;
frees_cnt--;
add_log(MEM_FREE_DELAY, __FUNCTION__, node->ptr, NULL,
node->size, 0);
}
}
mpp_assert(frees_cnt == 0);
}
os_free(nodes);
os_free(frees);
os_free(logs);
}
}
void MppMemService::add_node(const char *caller, void *ptr, size_t size)
{
RK_S32 i = 0;
if (debug & MEM_NODE_LOG)
mpp_log("mem cnt: %5d total %8d inc size %8d at %s\n",
nodes_cnt, total_size, size, caller);
if (nodes_cnt > nodes_max) {
mpp_err("failed to trace more memory node disable trace\n");
mpp_abort();
}
MppMemNode *node = nodes;
for (i = 0; i < nodes_max; i++, node++) {
if (node->index < 0) {
node->index = nodes_idx++;
node->size = size;
node->ptr = ptr;
node->caller = caller;
// NOTE: reset node index on revert
if (nodes_idx < 0)
nodes_idx = 0;
nodes_cnt++;
total_size += size;
break;
}
}
}
RK_S32 MppMemService::find_node(const char *caller, void *ptr, size_t *size, RK_S32 *idx)
{
RK_S32 i = 0;
MppMemNode *node = nodes;
MPP_MEM_ASSERT(nodes_cnt <= nodes_max);
for (i = 0; i < nodes_max; i++, node++) {
if (node->index >= 0 && node->ptr == ptr) {
*size = node->size;
*idx = i;
return 1;
}
}
mpp_err("%s can NOT found node with ptr %p\n", caller, ptr);
mpp_abort();
return 0;
}
void MppMemService::del_node(const char *caller, void *ptr, size_t *size)
{
RK_S32 i = 0;
MppMemNode *node = nodes;
MPP_MEM_ASSERT(nodes_cnt <= nodes_max);
for (i = 0; i < nodes_max; i++, node++) {
if (node->index >= 0 && node->ptr == ptr) {
*size = node->size;
node->index = ~node->index;
nodes_cnt--;
total_size -= node->size;
if (debug & MEM_NODE_LOG)
mpp_log("mem cnt: %5d total %8d dec size %8d at %s\n",
nodes_cnt, total_size, node->size, caller);
return ;
}
}
mpp_err("%s fail to find node with ptr %p\n", caller, ptr);
mpp_abort();
return ;
}
void *MppMemService::delay_del_node(const char *caller, void *ptr, size_t *size)
{
RK_S32 i = 0;
MppMemNode *node = nodes;
// clear output first
void *ret = NULL;
*size = 0;
// find the node to save
MPP_MEM_ASSERT(nodes_cnt <= nodes_max);
for (i = 0; i < nodes_max; i++, node++) {
if (node->index >= 0 && node->ptr == ptr) {
chk_node(caller, node);
break;
}
}
MPP_MEM_ASSERT(i < nodes_max);
if (debug & MEM_NODE_LOG)
mpp_log("mem cnt: %5d total %8d dec size %8d at %s\n",
nodes_cnt, total_size, node->size, caller);
MppMemNode *free_node = NULL;
MPP_MEM_ASSERT(frees_cnt <= frees_max);
if (frees_cnt) {
MppMemNode *tmp = frees;
// NODE: check all data here
for (i = 0; i < frees_max; i++, tmp++) {
if (tmp->index >= 0) {
chk_node(caller, tmp);
chk_poison(tmp);
}
}
}
if (frees_cnt >= frees_max) {
// free list full start del
RK_S32 frees_last = frees_idx - frees_cnt;
if (frees_last < 0)
frees_last += frees_max;
free_node = &frees[frees_last];
if (free_node->index >= 0) {
chk_node(caller, free_node);
chk_poison(free_node);
ret = free_node->ptr;
*size = free_node->size;
free_node->index = ~free_node->index;
frees_cnt--;
}
}
MPP_MEM_ASSERT(frees_cnt <= frees_max);
// free list is NOT full just store
free_node = &frees[frees_idx];
frees_idx++;
if (frees_idx >= frees_max)
frees_idx = 0;
if (frees_cnt < frees_max)
frees_cnt++;
MPP_MEM_ASSERT(frees_cnt <= frees_max);
memcpy(&frees[frees_idx], node, sizeof(*node));
if ((debug & MEM_POISON) && (node->size < 1024))
memset(node->ptr, MEM_CHECK_MARK, node->size);
node->index = ~node->index;
total_size -= node->size;
nodes_cnt--;
return ret;
}
void MppMemService::chk_node(const char *caller, MppMemNode *node)
{
if ((debug & MEM_EXT_ROOM) == 0)
return ;
chk_mem(caller, node->ptr, node->size);
}
void MppMemService::chk_mem(const char *caller, void *ptr, size_t size)
{
if ((debug & MEM_EXT_ROOM) == 0)
return ;
RK_S32 i = 0;
RK_U8 *p = (RK_U8 *)ptr - MEM_ALIGN;
for (i = 0; i < MEM_ALIGN; i++) {
if (p[i] != MEM_HEAD_MASK) {
mpp_err("%s checking ptr %p head room found error!\n", caller, ptr);
dump(caller);
show_mem((RK_U32 *)p, MEM_ALIGN);
mpp_abort();
}
}
p = (RK_U8 *)ptr + size;
for (i = 0; i < MEM_ALIGN; i++) {
if (p[i] != MEM_TAIL_MASK) {
mpp_err("%s checking ptr %p tail room found error!\n", caller, ptr);
dump(caller);
show_mem((RK_U32 *)p, MEM_ALIGN);
mpp_abort();
}
}
}
RK_S32 MppMemService::chk_poison(MppMemNode *node)
{
if ((debug & MEM_POISON) == 0)
return 0;
// check oldest memory and free it
RK_U8 *node_ptr = (RK_U8 *)node->ptr;
RK_S32 size = node->size;
RK_S32 i = 0;
RK_S32 start = -1;
RK_S32 end = -1;
if (size >= 1024)
return 0;
for (; i < size; i++) {
if (node_ptr[i] != MEM_CHECK_MARK) {
if (start < 0) {
start = i;
}
end = i + 1;
}
}
if (start >= 0 || end >= 0) {
mpp_err_f("found memory %p size %d caller %s overwrite from %d to %d\n",
node_ptr, size, node->caller, start, end);
dump(node->caller);
}
return end - start;
}
void MppMemService::reset_node(const char *caller, void *ptr, void *ret, size_t size)
{
RK_S32 i = 0;
MppMemNode *node = nodes;
if (debug & MEM_NODE_LOG)
mpp_log("mem cnt: %5d total %8d equ size %8d at %s\n",
nodes_cnt, total_size, size, __FUNCTION__);
MPP_MEM_ASSERT(nodes_cnt <= nodes_max);
for (i = 0; i < nodes_max; i++, node++) {
if (node->index >= 0 && node->ptr == ptr) {
total_size += size;
total_size -= node->size;
node->ptr = ret;
node->size = size;
node->caller = caller;
if (debug & MEM_EXT_ROOM)
set_mem_ext_room(ret, size);
break;
}
}
}
void MppMemService::add_log(MppMemOps ops, const char *caller,
void *ptr, void *ret, size_t size_0, size_t size_1)
{
MppMemLog *log = &logs[log_idx];
if (service.debug & MEM_RUNTIME_LOG)
mpp_log("%-7s ptr %010p %010p size %8u %8u at %s\n",
ops2str[ops], ptr, ret, size_0, size_1, caller);
log->index = log_index++;
log->ops = ops;
log->size_0 = size_0;
log->size_1 = size_1;
log->ptr = ptr;
log->ret = ret;
log->node = NULL;
log->caller = caller;
log_idx++;
if (log_idx >= log_max)
log_idx = 0;
if (log_cnt < log_max)
log_cnt++;
}
void MppMemService::dump(const char *caller)
{
RK_S32 i;
MppMemNode *node = nodes;
mpp_log("mpp_mem enter status dumping from %s:\n", caller);
mpp_log("mpp_mem node count %d:\n", nodes_cnt);
if (nodes_cnt) {
for (i = 0; i < nodes_max; i++, node++) {
if (!node->index < 0)
continue;
mpp_log("mpp_memory index %d caller %-32s size %-8u ptr %p\n",
node->index, node->caller, node->size, node->ptr);
}
}
node = frees;
mpp_log("mpp_mem free count %d:\n", frees_cnt);
if (frees_cnt) {
for (i = 0; i < frees_max; i++, node++) {
if (!node->index < 0)
continue;
mpp_log("mpp_freed index %d caller %-32s size %-8u ptr %p\n",
node->index, node->caller, node->size, node->ptr);
}
}
RK_S32 start = log_idx - log_cnt;
RK_S32 tmp_cnt = log_cnt;
if (start < 0)
start += log_max;
mpp_log("mpp_mem enter log dumping:\n");
while (tmp_cnt) {
MppMemLog *log = &logs[start];
mpp_log("idx %-8d op: %-7s from %-32s ptr %10p %10p size %7d %7d\n",
log->index, ops2str[log->ops], log->caller,
log->ptr, log->ret, log->size_0, log->size_1);
start++;
if (start >= log_max)
start = 0;
tmp_cnt--;
}
}
void *mpp_osal_malloc(const char *caller, size_t size)
{
AutoMutex auto_lock(&service.lock);
RK_U32 debug = service.debug;
size_t size_align = MEM_ALIGNED(size);
size_t size_real = (debug & MEM_EXT_ROOM) ? (size_align + 2 * MEM_ALIGN) :
(size_align);
void *ptr;
get_osal_mem_flag();
os_malloc(&ptr, MEM_ALIGN, size_real);
os_malloc(&ptr, RK_OSAL_MEM_ALIGN, size);
if (debug) {
service.add_log(MEM_MALLOC, caller, NULL, ptr, size, size_real);
if (mpp_mem_flag & OSAL_MEM_RUNTIME_LOG)
mpp_log("mpp_malloc tag %-16s size %-8u ret %p\n", tag, size, ptr);
if (ptr) {
if (debug & MEM_EXT_ROOM) {
ptr = (RK_U8 *)ptr + MEM_ALIGN;
set_mem_ext_room(ptr, size);
}
if ((mpp_mem_flag & OSAL_MEM_LIST_EN) && ptr) {
struct mem_node *node = (struct mem_node *)malloc(sizeof(struct mem_node));
mpp_assert(node);
INIT_LIST_HEAD(&node->list);
node->ptr = ptr;
node->size = size;
snprintf(node->tag, sizeof(node->tag), "%s", tag);
pthread_mutex_lock(&mem_list_lock);
node->index = osal_mem_index++;
list_add_tail(&node->list, &mem_list);
pthread_mutex_unlock(&mem_list_lock);
service.add_node(caller, ptr, size);
}
}
return ptr;
}
void *mpp_osal_calloc(const char *tag, size_t size)
void *mpp_osal_calloc(const char *caller, size_t size)
{
void *ptr = mpp_osal_malloc(tag, size);
void *ptr = mpp_osal_malloc(caller, size);
if (ptr)
memset(ptr, 0, size);
return ptr;
}
void *mpp_osal_realloc(const char *tag, void *ptr, size_t size)
void *mpp_osal_realloc(const char *caller, void *ptr, size_t size)
{
AutoMutex auto_lock(&service.lock);
RK_U32 debug = service.debug;
void *ret;
if (NULL == ptr)
return mpp_osal_malloc(tag, size);
return mpp_osal_malloc(caller, size);
if (0 == size)
if (0 == size) {
mpp_err("warning: realloc %p to zero size\n", ptr);
return NULL;
get_osal_mem_flag();
if (mpp_mem_flag & OSAL_MEM_LIST_EN) {
struct mem_node *pos, *n;
ret = NULL;
pthread_mutex_lock(&mem_list_lock);
list_for_each_entry_safe(pos, n, &mem_list, struct mem_node, list) {
if (ptr == pos->ptr) {
if (MPP_OK == os_realloc(ptr, &pos->ptr, RK_OSAL_MEM_ALIGN, size)) {
pos->size = size;
strncpy(pos->tag, tag, sizeof(pos->tag));
ret = pos->ptr;
} else {
list_del_init(&pos->list);
free(pos);
}
break;
}
}
pthread_mutex_unlock(&mem_list_lock);
} else {
os_realloc(ptr, &ret, RK_OSAL_MEM_ALIGN, size);
}
if (mpp_mem_flag & OSAL_MEM_RUNTIME_LOG)
mpp_log("mpp_realloc tag %-16s size %-8u ptr %p ret %p\n", tag, size, ptr, ret);
size_t size_align = MEM_ALIGNED(size);
size_t size_real = (debug & MEM_EXT_ROOM) ? (size_align + 2 * MEM_ALIGN) :
(size_align);
void *ptr_real = (RK_U8 *)ptr - MEM_HEAD_ROOM(debug);
if (NULL == ret)
os_realloc(ptr_real, &ret, MEM_ALIGN, size_align);
if (NULL == ret) {
// if realloc fail the original buffer will be kept the same.
mpp_err("mpp_realloc ptr %p to size %d failed\n", ptr, size);
} else {
// if realloc success reset the node and record
if (debug) {
void *ret_ptr = (debug & MEM_EXT_ROOM) ?
((RK_U8 *)ret + MEM_ALIGN) : (ret);
service.reset_node(caller, ptr, ret_ptr, size);
service.add_log(MEM_REALLOC, caller, ptr, ret_ptr, size, size_real);
ret = ret_ptr;
}
}
return ret;
}
void mpp_osal_free(void *ptr)
void mpp_osal_free(const char *caller, void *ptr)
{
AutoMutex auto_lock(&service.lock);
RK_U32 debug = service.debug;
if (NULL == ptr)
return;
get_osal_mem_flag();
if (mpp_mem_flag & OSAL_MEM_LIST_EN) {
struct mem_node *pos, *n;
RK_U32 found_match = 0;
pthread_mutex_lock(&mem_list_lock);
list_for_each_entry_safe(pos, n, &mem_list, struct mem_node, list) {
if (ptr == pos->ptr) {
list_del_init(&pos->list);
free(pos);
found_match = 1;
break;
}
}
pthread_mutex_unlock(&mem_list_lock);
if (!found_match)
mpp_err_f("can not found match on free %p\n", ptr);
if (!debug) {
os_free(ptr);
return ;
}
if (mpp_mem_flag & OSAL_MEM_RUNTIME_LOG)
mpp_log("mpp_free %p\n", ptr);
size_t size = 0;
os_free(ptr);
if (debug & MEM_POISON) {
// NODE: keep this node and delete delay node
void *ret = service.delay_del_node(caller, ptr, &size);
if (ret)
os_free((RK_U8 *)ret - MEM_ALIGN);
service.add_log(MEM_FREE_DELAY, caller, ptr, ret, size, 0);
} else {
void *ptr_real = (RK_U8 *)ptr - MEM_HEAD_ROOM(debug);
// NODE: delete node and return size here
service.del_node(caller, ptr, &size);
service.chk_mem(caller, ptr, size);
os_free(ptr_real);
service.add_log(MEM_FREE, caller, ptr, ptr_real, size, 0);
}
}
/*
* dump memory status
* this function need MODULE_TAG statistic information
*/
/* dump memory status */
void mpp_show_mem_status()
{
struct mem_node *pos, *n;
pthread_mutex_lock(&mem_list_lock);
list_for_each_entry_safe(pos, n, &mem_list, struct mem_node, list) {
mpp_log("unfree memory %p size %d tag %s index %llu",
pos->ptr, pos->size, pos->tag, pos->index);
}
pthread_mutex_unlock(&mem_list_lock);
AutoMutex auto_lock(&service.lock);
if (service.debug & MEM_DEBUG_EN)
service.dump(__FUNCTION__);
}
typedef struct MppMemSnapshotImpl {
struct list_head list;
RK_U64 total_size;
RK_U32 total_count;
} MppMemSnapshotImpl;
MPP_RET mpp_mem_get_snapshot(MppMemSnapshot *hnd)
{
struct mem_node *pos, *n;
MppMemSnapshotImpl *p = (MppMemSnapshotImpl *)malloc(sizeof(MppMemSnapshotImpl));
if (!p) {
mpp_err_f("failed to alloc");
*hnd = NULL;
return MPP_NOK;
}
INIT_LIST_HEAD(&p->list);
p->total_size = 0;
p->total_count = 0;
pthread_mutex_lock(&mem_list_lock);
list_for_each_entry_safe(pos, n, &mem_list, struct mem_node, list) {
struct mem_node *node = (struct mem_node *)malloc(sizeof(struct mem_node));
mpp_assert(node);
memcpy(node, pos, sizeof(*pos));
INIT_LIST_HEAD(&node->list);
list_add_tail(&node->list, &p->list);
p->total_size += pos->size;
p->total_count++;
}
*hnd = p;
pthread_mutex_unlock(&mem_list_lock);
return MPP_OK;
}
MPP_RET mpp_mem_put_snapshot(MppMemSnapshot *hnd)
{
if (hnd && *hnd) {
MppMemSnapshotImpl *p = (MppMemSnapshotImpl *)*hnd;
struct mem_node *pos, *n;
pthread_mutex_lock(&mem_list_lock);
list_for_each_entry_safe(pos, n, &p->list, struct mem_node, list) {
list_del_init(&pos->list);
free(pos);
}
free(p);
*hnd = NULL;
pthread_mutex_unlock(&mem_list_lock);
}
return MPP_OK;
}
MPP_RET mpp_mem_squash_snapshot(MppMemSnapshot hnd0, MppMemSnapshot hnd1)
{
if (!hnd0 || !hnd1) {
mpp_err_f("invalid input %p %p\n", hnd0, hnd1);
return MPP_NOK;
}
MppMemSnapshotImpl *p0 = (MppMemSnapshotImpl *)hnd0;
MppMemSnapshotImpl *p1 = (MppMemSnapshotImpl *)hnd1;
struct mem_node *pos0, *n0;
struct mem_node *pos1, *n1;
mpp_log_f("snapshot0 total count %6d size %d\n", p0->total_count, p0->total_size);
mpp_log_f("snapshot1 total count %6d size %d\n", p1->total_count, p1->total_size);
pthread_mutex_lock(&mem_list_lock);
/* handle 0 search */
list_for_each_entry_safe(pos0, n0, &p0->list, struct mem_node, list) {
RK_U32 found_match = 0;
list_for_each_entry_safe(pos1, n1, &p1->list, struct mem_node, list) {
if (pos0->index == pos1->index) {
list_del_init(&pos0->list);
list_del_init(&pos1->list);
free(pos0);
free(pos1);
found_match = 1;
break;
}
}
if (!found_match) {
mpp_log_f("snapshot0 %p found mismatch memory %p size %d tag %s index %llu",
p0, pos0->ptr, pos0->size, pos0->tag, pos0->index);
}
}
/* handle 1 search */
list_for_each_entry_safe(pos1, n1, &p1->list, struct mem_node, list) {
mpp_log_f("snapshot1 %p found mismatch memory %p size %d tag %s index %llu",
p1, pos1->ptr, pos1->size, pos1->tag, pos1->index);
}
pthread_mutex_unlock(&mem_list_lock);
return MPP_OK;
}

View File

@ -26,7 +26,6 @@ int main()
{
void *tmp = NULL;
mpp_env_set_u32("mpp_mem_flag", 0x3);
tmp = mpp_calloc(int, 100);
if (tmp) {
mpp_log("calloc success ptr 0x%p\n", tmp);