diff --git a/osal/inc/mpp_mem.h b/osal/inc/mpp_mem.h index 715e59cc..f3551fb8 100644 --- a/osal/inc/mpp_mem.h +++ b/osal/inc/mpp_mem.h @@ -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(); diff --git a/osal/mpp_mem.cpp b/osal/mpp_mem.cpp index 3d4937e9..19fa108d 100644 --- a/osal/mpp_mem.cpp +++ b/osal/mpp_mem.cpp @@ -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; -} - diff --git a/osal/test/mpp_mem_test.c b/osal/test/mpp_mem_test.c index a9d6f4c4..8c572bb4 100644 --- a/osal/test/mpp_mem_test.c +++ b/osal/test/mpp_mem_test.c @@ -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);