mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-09-26 21:15:53 +08:00
refactor[mpp_mem]: Refactor C++ mpp_mem to C
Signed-off-by: Chandler Chen <chandler.chen@rock-chips.com> Signed-off-by: Hongjin Li <vic.hong@rock-chips.com> Signed-off-by: Herman Chen <herman.chen@rock-chips.com> Change-Id: I927346dfdb0edea486b8dda61f379f96059b01ba
This commit is contained in:
@@ -44,7 +44,7 @@ add_library(osal OBJECT
|
|||||||
mpp_lock.cpp
|
mpp_lock.cpp
|
||||||
mpp_time.cpp
|
mpp_time.cpp
|
||||||
mpp_list.cpp
|
mpp_list.cpp
|
||||||
mpp_mem.cpp
|
mpp_mem.c
|
||||||
mpp_env.cpp
|
mpp_env.cpp
|
||||||
mpp_log.cpp
|
mpp_log.cpp
|
||||||
osal_2str.c
|
osal_2str.c
|
||||||
|
@@ -1,17 +1,6 @@
|
|||||||
|
/* SPDX-License-Identifier: Apache-2.0 OR MIT */
|
||||||
/*
|
/*
|
||||||
* Copyright 2015 Rockchip Electronics Co. LTD
|
* Copyright (c) 2015 Rockchip Electronics Co., Ltd.
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __MPP_MEM_H__
|
#ifndef __MPP_MEM_H__
|
||||||
@@ -59,23 +48,8 @@ void *mpp_osal_realloc(const char *caller, void *ptr, size_t size);
|
|||||||
void mpp_osal_free(const char *caller, void *ptr);
|
void mpp_osal_free(const char *caller, void *ptr);
|
||||||
|
|
||||||
void mpp_show_mem_status();
|
void mpp_show_mem_status();
|
||||||
RK_U32 mpp_mem_total_now();
|
rk_u32 mpp_mem_total_now();
|
||||||
RK_U32 mpp_mem_total_max();
|
rk_u32 mpp_mem_total_max();
|
||||||
|
|
||||||
/*
|
|
||||||
* mpp memory usage snapshot tool
|
|
||||||
*
|
|
||||||
* usage:
|
|
||||||
* call mpp_mem_get_snapshot on context init get one snapshot
|
|
||||||
* call mpp_mem_get_snapshot on context deinit get another snapshot
|
|
||||||
* call mpp_mem_diff_snapshot to show the difference between these two snapshot
|
|
||||||
* call mpp_mem_put_snapshot twice to release these two snapshot
|
|
||||||
*/
|
|
||||||
typedef void* MppMemSnapshot;
|
|
||||||
|
|
||||||
MPP_RET mpp_mem_get_snapshot(MppMemSnapshot *hnd);
|
|
||||||
MPP_RET mpp_mem_put_snapshot(MppMemSnapshot *hnd);
|
|
||||||
MPP_RET mpp_mem_squash_snapshot(MppMemSnapshot hnd0, MppMemSnapshot hnd1);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
799
osal/mpp_mem.c
Normal file
799
osal/mpp_mem.c
Normal file
@@ -0,0 +1,799 @@
|
|||||||
|
/* SPDX-License-Identifier: Apache-2.0 OR MIT */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Rockchip Electronics Co., Ltd.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MODULE_TAG "mpp_mem"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "mpp_env.h"
|
||||||
|
#include "mpp_mem.h"
|
||||||
|
#include "mpp_list.h"
|
||||||
|
#include "mpp_debug.h"
|
||||||
|
#include "mpp_common.h"
|
||||||
|
#include "mpp_singleton.h"
|
||||||
|
|
||||||
|
#include "os_mem.h"
|
||||||
|
|
||||||
|
// 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 MEM_MAX_INDEX (0x7fffffff)
|
||||||
|
#define MEM_ALIGN 32
|
||||||
|
#define MEM_ALIGN_MASK (MEM_ALIGN - 1)
|
||||||
|
#define MEM_ALIGNED(x) (((x) + MEM_ALIGN_MASK) & (~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)
|
||||||
|
|
||||||
|
#define MPP_MEM_ASSERT(srv, cond) \
|
||||||
|
do { \
|
||||||
|
if (!(cond)) { \
|
||||||
|
mpp_err("found mpp_mem assert failed, start dumping:\n"); \
|
||||||
|
mpp_mem_srv_dump(srv, __FUNCTION__); \
|
||||||
|
mpp_assert(cond); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define get_srv_mem(caller) \
|
||||||
|
({ \
|
||||||
|
MppMemSrv *__tmp; \
|
||||||
|
if (!srv_mem) { \
|
||||||
|
mpp_mem_srv_init(); \
|
||||||
|
} \
|
||||||
|
if (srv_mem) { \
|
||||||
|
__tmp = srv_mem; \
|
||||||
|
} else { \
|
||||||
|
mpp_err("mpp mem srv not init at %s : %s\n", __FUNCTION__, caller); \
|
||||||
|
__tmp = NULL; \
|
||||||
|
} \
|
||||||
|
__tmp; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define get_srv_mem_f() \
|
||||||
|
({ \
|
||||||
|
MppMemSrv *__tmp; \
|
||||||
|
if (!srv_mem) { \
|
||||||
|
mpp_mem_srv_init(); \
|
||||||
|
} \
|
||||||
|
if (srv_mem) { \
|
||||||
|
__tmp = srv_mem; \
|
||||||
|
} else { \
|
||||||
|
mpp_err("mpp mem srv not init at %s\n", __FUNCTION__); \
|
||||||
|
__tmp = NULL; \
|
||||||
|
} \
|
||||||
|
__tmp; \
|
||||||
|
})
|
||||||
|
|
||||||
|
typedef enum MppMemOps_e {
|
||||||
|
MEM_MALLOC,
|
||||||
|
MEM_REALLOC,
|
||||||
|
MEM_FREE,
|
||||||
|
MEM_FREE_DELAY,
|
||||||
|
|
||||||
|
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_t {
|
||||||
|
rk_s32 index;
|
||||||
|
size_t size;
|
||||||
|
void *ptr;
|
||||||
|
const char *caller;
|
||||||
|
} MppMemNode;
|
||||||
|
|
||||||
|
typedef struct MppMemLog_t {
|
||||||
|
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;
|
||||||
|
|
||||||
|
typedef struct MppMemSrv_t {
|
||||||
|
// 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;
|
||||||
|
rk_u32 total_max;
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
rk_u32 debug;
|
||||||
|
} MppMemSrv;
|
||||||
|
|
||||||
|
static MppMemSrv *srv_mem = NULL;
|
||||||
|
|
||||||
|
static const char *ops2str[MEM_OPS_BUTT] = {
|
||||||
|
"malloc",
|
||||||
|
"realloc",
|
||||||
|
"free",
|
||||||
|
"delayed",
|
||||||
|
};
|
||||||
|
|
||||||
|
static void show_mem(rk_u32 *buf, rk_s32 size)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mpp_mem_srv_dump(MppMemSrv *srv, const char *caller)
|
||||||
|
{
|
||||||
|
MppMemNode *node = srv->nodes;
|
||||||
|
rk_s32 start;
|
||||||
|
rk_s32 tmp_cnt;
|
||||||
|
rk_s32 i;
|
||||||
|
|
||||||
|
mpp_log("mpp_mem enter status dumping from %s:\n", caller);
|
||||||
|
|
||||||
|
mpp_log("mpp_mem node count %d:\n", srv->nodes_cnt);
|
||||||
|
if (srv->nodes_cnt) {
|
||||||
|
for (i = 0; i < srv->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 = srv->frees;
|
||||||
|
mpp_log("mpp_mem free count %d:\n", srv->frees_cnt);
|
||||||
|
if (srv->frees_cnt) {
|
||||||
|
for (i = 0; i < srv->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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start = srv->log_idx - srv->log_cnt;
|
||||||
|
tmp_cnt = srv->log_cnt;
|
||||||
|
|
||||||
|
if (start < 0)
|
||||||
|
start += srv->log_max;
|
||||||
|
|
||||||
|
mpp_log("mpp_mem enter log dumping:\n");
|
||||||
|
|
||||||
|
while (tmp_cnt) {
|
||||||
|
MppMemLog *log = &srv->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 >= srv->log_max)
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
tmp_cnt--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_mem(MppMemSrv *srv, void *ptr, size_t size, const char *caller)
|
||||||
|
{
|
||||||
|
rk_u8 *p;
|
||||||
|
rk_s32 i;
|
||||||
|
|
||||||
|
if ((srv->debug & MEM_EXT_ROOM) == 0)
|
||||||
|
return ;
|
||||||
|
|
||||||
|
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);
|
||||||
|
mpp_mem_srv_dump(srv, 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);
|
||||||
|
mpp_mem_srv_dump(srv, caller);
|
||||||
|
show_mem((rk_u32 *)p, MEM_ALIGN);
|
||||||
|
mpp_abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_node(MppMemSrv *srv, MppMemNode *node, const char *caller)
|
||||||
|
{
|
||||||
|
if ((srv->debug & MEM_EXT_ROOM) == 0)
|
||||||
|
return ;
|
||||||
|
|
||||||
|
check_mem(srv, node->ptr, node->size, caller);
|
||||||
|
}
|
||||||
|
|
||||||
|
static rk_s32 check_poison(MppMemSrv *srv, MppMemNode *node)
|
||||||
|
{
|
||||||
|
if ((srv->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);
|
||||||
|
mpp_mem_srv_dump(srv, node->caller);
|
||||||
|
}
|
||||||
|
|
||||||
|
return end - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_node(MppMemSrv *srv, void *ptr, void *ret, size_t size, const char *caller)
|
||||||
|
{
|
||||||
|
MppMemNode *node = srv->nodes;
|
||||||
|
rk_s32 i = 0;
|
||||||
|
|
||||||
|
if (srv->debug & MEM_NODE_LOG)
|
||||||
|
mpp_log("mem cnt: %5d total %8d equ size %8d at %s\n",
|
||||||
|
srv->nodes_cnt, srv->total_size, size, __FUNCTION__);
|
||||||
|
|
||||||
|
MPP_MEM_ASSERT(srv, srv->nodes_cnt <= srv->nodes_max);
|
||||||
|
|
||||||
|
for (i = 0; i < srv->nodes_max; i++, node++) {
|
||||||
|
if (node->index >= 0 && node->ptr == ptr) {
|
||||||
|
srv->total_size += size;
|
||||||
|
srv->total_size -= node->size;
|
||||||
|
|
||||||
|
node->ptr = ret;
|
||||||
|
node->size = size;
|
||||||
|
node->caller = caller;
|
||||||
|
|
||||||
|
if (srv->debug & MEM_EXT_ROOM)
|
||||||
|
set_mem_ext_room(ret, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_log(MppMemSrv *srv, MppMemOps ops, const char *caller, void *ptr,
|
||||||
|
void *ret, size_t size_0, size_t size_1)
|
||||||
|
{
|
||||||
|
MppMemLog *log = &srv->logs[srv->log_idx];
|
||||||
|
|
||||||
|
if (srv->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 = srv->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;
|
||||||
|
|
||||||
|
srv->log_idx++;
|
||||||
|
if (srv->log_idx >= srv->log_max)
|
||||||
|
srv->log_idx = 0;
|
||||||
|
|
||||||
|
if (srv->log_cnt < srv->log_max)
|
||||||
|
srv->log_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_node(MppMemSrv *srv, void *ptr, size_t size, const char *caller)
|
||||||
|
{
|
||||||
|
MppMemNode *node;
|
||||||
|
rk_s32 i;
|
||||||
|
|
||||||
|
if (srv->debug & MEM_NODE_LOG)
|
||||||
|
mpp_log("mem cnt: %5d total %8d inc size %8d at %s\n",
|
||||||
|
srv->nodes_cnt, srv->total_size, size, caller);
|
||||||
|
|
||||||
|
if (srv->nodes_cnt >= srv->nodes_max) {
|
||||||
|
mpp_err("******************************************************\n");
|
||||||
|
mpp_err("* Reach max limit of mpp_mem counter %5d *\n", srv->nodes_max);
|
||||||
|
mpp_err("* Increase limit by setup env mpp_mem_node_max or *\n");
|
||||||
|
mpp_err("* recompile mpp with larger macro MEM_NODE_MAX value *\n");
|
||||||
|
mpp_err("******************************************************\n");
|
||||||
|
mpp_abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
node = srv->nodes;
|
||||||
|
for (i = 0; i < srv->nodes_max; i++, node++) {
|
||||||
|
if (node->index < 0) {
|
||||||
|
node->index = srv->nodes_idx++;
|
||||||
|
node->size = size;
|
||||||
|
node->ptr = ptr;
|
||||||
|
node->caller = caller;
|
||||||
|
|
||||||
|
// NOTE: reset node index on revert
|
||||||
|
if (srv->nodes_idx < 0)
|
||||||
|
srv->nodes_idx = 0;
|
||||||
|
|
||||||
|
srv->nodes_cnt++;
|
||||||
|
srv->total_size += size;
|
||||||
|
if (srv->total_size > srv->total_max)
|
||||||
|
srv->total_max = srv->total_size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void del_node(MppMemSrv *srv, void *ptr, size_t *size, const char *caller)
|
||||||
|
{
|
||||||
|
MppMemNode *node = srv->nodes;
|
||||||
|
rk_s32 i;
|
||||||
|
|
||||||
|
MPP_MEM_ASSERT(srv, srv->nodes_cnt <= srv->nodes_max);
|
||||||
|
|
||||||
|
for (i = 0; i < srv->nodes_max; i++, node++) {
|
||||||
|
if (node->index >= 0 && node->ptr == ptr) {
|
||||||
|
*size = node->size;
|
||||||
|
node->index = ~node->index;
|
||||||
|
srv->nodes_cnt--;
|
||||||
|
srv->total_size -= node->size;
|
||||||
|
|
||||||
|
if (srv->debug & MEM_NODE_LOG)
|
||||||
|
mpp_log("mem cnt: %5d total %8d dec size %8d at %s\n",
|
||||||
|
srv->nodes_cnt, srv->total_size, node->size, caller);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mpp_err("%s fail to find node with ptr %p\n", caller, ptr);
|
||||||
|
mpp_abort();
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *delay_del_node(MppMemSrv *srv, void *ptr, size_t *size, const char *caller)
|
||||||
|
{
|
||||||
|
MppMemNode *node = srv->nodes;
|
||||||
|
MppMemNode *free_node = NULL;
|
||||||
|
void *ret = NULL;
|
||||||
|
rk_s32 i = 0;
|
||||||
|
|
||||||
|
// clear output first
|
||||||
|
*size = 0;
|
||||||
|
|
||||||
|
// find the node to save
|
||||||
|
MPP_MEM_ASSERT(srv, srv->nodes_cnt <= srv->nodes_max);
|
||||||
|
for (i = 0; i < srv->nodes_max; i++, node++) {
|
||||||
|
if (node->index >= 0 && node->ptr == ptr) {
|
||||||
|
check_node(srv, node, caller);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MPP_MEM_ASSERT(srv, i < srv->nodes_max);
|
||||||
|
if (srv->debug & MEM_NODE_LOG)
|
||||||
|
mpp_log("mem cnt: %5d total %8d dec size %8d at %s\n",
|
||||||
|
srv->nodes_cnt, srv->total_size, node->size, caller);
|
||||||
|
|
||||||
|
MPP_MEM_ASSERT(srv, srv->frees_cnt <= srv->frees_max);
|
||||||
|
|
||||||
|
if (srv->frees_cnt) {
|
||||||
|
MppMemNode *tmp = srv->frees;
|
||||||
|
|
||||||
|
// NODE: check all data here
|
||||||
|
for (i = 0; i < srv->frees_max; i++, tmp++) {
|
||||||
|
if (tmp->index >= 0) {
|
||||||
|
check_node(srv, tmp, caller);
|
||||||
|
check_poison(srv, tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srv->frees_cnt >= srv->frees_max) {
|
||||||
|
// free list full start del
|
||||||
|
rk_s32 frees_last = srv->frees_idx - srv->frees_cnt;
|
||||||
|
|
||||||
|
if (frees_last < 0)
|
||||||
|
frees_last += srv->frees_max;
|
||||||
|
|
||||||
|
free_node = &srv->frees[frees_last];
|
||||||
|
|
||||||
|
if (free_node->index >= 0) {
|
||||||
|
check_node(srv, free_node, caller);
|
||||||
|
check_poison(srv, free_node);
|
||||||
|
ret = free_node->ptr;
|
||||||
|
*size = free_node->size;
|
||||||
|
free_node->index = ~free_node->index;
|
||||||
|
srv->frees_cnt--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MPP_MEM_ASSERT(srv, srv->frees_cnt <= srv->frees_max);
|
||||||
|
|
||||||
|
// free list is NOT full just store
|
||||||
|
free_node = &srv->frees[srv->frees_idx];
|
||||||
|
srv->frees_idx++;
|
||||||
|
if (srv->frees_idx >= srv->frees_max)
|
||||||
|
srv->frees_idx = 0;
|
||||||
|
if (srv->frees_cnt < srv->frees_max)
|
||||||
|
srv->frees_cnt++;
|
||||||
|
|
||||||
|
MPP_MEM_ASSERT(srv, srv->frees_cnt <= srv->frees_max);
|
||||||
|
|
||||||
|
memcpy(&srv->frees[srv->frees_idx], node, sizeof(*node));
|
||||||
|
|
||||||
|
if ((srv->debug & MEM_POISON) && (node->size < 1024))
|
||||||
|
memset(node->ptr, MEM_CHECK_MARK, node->size);
|
||||||
|
|
||||||
|
node->index = ~node->index;
|
||||||
|
srv->total_size -= node->size;
|
||||||
|
srv->nodes_cnt--;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mpp_mem_srv_init()
|
||||||
|
{
|
||||||
|
MppMemSrv *srv = srv_mem;
|
||||||
|
|
||||||
|
if (srv)
|
||||||
|
return;
|
||||||
|
|
||||||
|
os_malloc((void **)&srv, MEM_ALIGN, sizeof(*srv));
|
||||||
|
mpp_assert(srv);
|
||||||
|
srv_mem = srv;
|
||||||
|
|
||||||
|
memset(srv, 0, sizeof(*srv));
|
||||||
|
|
||||||
|
mpp_env_get_u32("mpp_mem_debug", &srv->debug, 0);
|
||||||
|
|
||||||
|
srv->nodes_max = MEM_NODE_MAX;
|
||||||
|
srv->frees_max = MEM_FREE_MAX;
|
||||||
|
srv->log_max = MEM_LOG_MAX;
|
||||||
|
|
||||||
|
{
|
||||||
|
// init mutex lock
|
||||||
|
pthread_mutexattr_t attr;
|
||||||
|
|
||||||
|
pthread_mutexattr_init(&attr);
|
||||||
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||||
|
pthread_mutex_init(&srv->lock, &attr);
|
||||||
|
pthread_mutexattr_destroy(&attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&srv->lock);
|
||||||
|
|
||||||
|
// add more flag if debug enabled
|
||||||
|
if (srv->debug)
|
||||||
|
srv->debug |= MEM_DEBUG_EN;
|
||||||
|
|
||||||
|
if (srv->debug & MEM_DEBUG_EN) {
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
mpp_env_get_u32("mpp_mem_node_max", (rk_u32 *)&srv->nodes_max, MEM_NODE_MAX);
|
||||||
|
|
||||||
|
mpp_log_f("mpp_mem_debug enabled %x max node %d\n",
|
||||||
|
srv->debug, srv->nodes_max);
|
||||||
|
|
||||||
|
size = srv->nodes_max * sizeof(MppMemNode);
|
||||||
|
os_malloc((void **)&srv->nodes, MEM_ALIGN, size);
|
||||||
|
mpp_assert(srv->nodes);
|
||||||
|
memset(srv->nodes, 0xff, size);
|
||||||
|
add_node(srv, srv->nodes, size, __FUNCTION__);
|
||||||
|
|
||||||
|
size = srv->frees_max * sizeof(MppMemNode);
|
||||||
|
os_malloc((void **)&srv->frees, MEM_ALIGN, size);
|
||||||
|
mpp_assert(srv->frees);
|
||||||
|
memset(srv->frees, 0xff, size);
|
||||||
|
add_node(srv, srv->frees, size, __FUNCTION__);
|
||||||
|
|
||||||
|
size = srv->log_max * sizeof(MppMemLog);
|
||||||
|
os_malloc((void **)&srv->logs, MEM_ALIGN, size);
|
||||||
|
mpp_assert(srv->logs);
|
||||||
|
add_node(srv, srv->logs, size, __FUNCTION__);
|
||||||
|
|
||||||
|
add_node(srv, srv, sizeof(MppMemSrv), __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&srv->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mpp_mem_srv_deinit()
|
||||||
|
{
|
||||||
|
MppMemSrv *srv = get_srv_mem_f();
|
||||||
|
|
||||||
|
if (!srv)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (srv->debug & MEM_DEBUG_EN) {
|
||||||
|
MppMemNode *node = srv->nodes;
|
||||||
|
size_t size = 0;
|
||||||
|
rk_s32 i = 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&srv->lock);
|
||||||
|
|
||||||
|
// delete self node first
|
||||||
|
del_node(srv, srv, &size, __FUNCTION__);
|
||||||
|
del_node(srv, srv->nodes, &size, __FUNCTION__);
|
||||||
|
del_node(srv, srv->frees, &size, __FUNCTION__);
|
||||||
|
del_node(srv, srv->logs, &size, __FUNCTION__);
|
||||||
|
|
||||||
|
// then check leak memory
|
||||||
|
if (srv->nodes_cnt) {
|
||||||
|
for (i = 0; i < srv->nodes_max; i++, node++) {
|
||||||
|
if (node->index >= 0) {
|
||||||
|
mpp_log("found idx %8d mem %10p size %d leaked from %s\n",
|
||||||
|
node->index, node->ptr, node->size, node->caller);
|
||||||
|
srv->nodes_cnt--;
|
||||||
|
add_log(srv, MEM_FREE, __FUNCTION__, node->ptr, NULL,
|
||||||
|
node->size, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mpp_assert(srv->nodes_cnt == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally release all delay free memory
|
||||||
|
if (srv->frees_cnt) {
|
||||||
|
node = srv->frees;
|
||||||
|
|
||||||
|
for (i = 0; i < srv->frees_max; i++, node++) {
|
||||||
|
if (node->index >= 0) {
|
||||||
|
os_free((rk_u8 *)node->ptr - MEM_HEAD_ROOM(srv->debug));
|
||||||
|
node->index = ~node->index;
|
||||||
|
srv->frees_cnt--;
|
||||||
|
add_log(srv, MEM_FREE_DELAY, __FUNCTION__, node->ptr, NULL,
|
||||||
|
node->size, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mpp_assert(srv->frees_cnt == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
os_free(srv->nodes);
|
||||||
|
os_free(srv->frees);
|
||||||
|
os_free(srv->logs);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&srv->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&srv->lock);
|
||||||
|
|
||||||
|
os_free(srv);
|
||||||
|
srv_mem = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MPP_SINGLETON(MPP_SGLN_OS_MEM, mpp_mem, mpp_mem_srv_init, mpp_mem_srv_deinit)
|
||||||
|
|
||||||
|
void *mpp_osal_malloc(const char *caller, size_t size)
|
||||||
|
{
|
||||||
|
MppMemSrv *srv = get_srv_mem(caller);
|
||||||
|
rk_u32 debug = srv->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;
|
||||||
|
|
||||||
|
os_malloc(&ptr, MEM_ALIGN, size_real);
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
pthread_mutex_lock(&srv->lock);
|
||||||
|
|
||||||
|
add_log(srv, MEM_MALLOC, caller, NULL, ptr, size, size_real);
|
||||||
|
|
||||||
|
if (ptr) {
|
||||||
|
if (debug & MEM_EXT_ROOM) {
|
||||||
|
ptr = (rk_u8 *)ptr + MEM_ALIGN;
|
||||||
|
set_mem_ext_room(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_node(srv, ptr, size, caller);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&srv->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *mpp_osal_calloc(const char *caller, size_t size)
|
||||||
|
{
|
||||||
|
void *ptr = mpp_osal_malloc(caller, size);
|
||||||
|
|
||||||
|
if (ptr)
|
||||||
|
memset(ptr, 0, size);
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *mpp_osal_realloc(const char *caller, void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
MppMemSrv *srv = get_srv_mem(caller);
|
||||||
|
rk_u32 debug = srv->debug;
|
||||||
|
size_t size_align;
|
||||||
|
size_t size_real;
|
||||||
|
void *ptr_real;
|
||||||
|
void *ret;
|
||||||
|
|
||||||
|
if (!ptr)
|
||||||
|
return mpp_osal_malloc(caller, size);
|
||||||
|
|
||||||
|
if (0 == size) {
|
||||||
|
mpp_err("warning: realloc %p to zero size\n", ptr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_align = MEM_ALIGNED(size);
|
||||||
|
size_real = (debug & MEM_EXT_ROOM) ? (size_align + 2 * MEM_ALIGN) : (size_align);
|
||||||
|
ptr_real = (rk_u8 *)ptr - MEM_HEAD_ROOM(debug);
|
||||||
|
|
||||||
|
os_realloc(ptr_real, &ret, MEM_ALIGN, size_align);
|
||||||
|
|
||||||
|
if (!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 {
|
||||||
|
pthread_mutex_lock(&srv->lock);
|
||||||
|
|
||||||
|
// if realloc success reset the node and record
|
||||||
|
if (debug) {
|
||||||
|
void *ret_ptr = (debug & MEM_EXT_ROOM) ?
|
||||||
|
((rk_u8 *)ret + MEM_ALIGN) : (ret);
|
||||||
|
|
||||||
|
reset_node(srv, ptr, ret_ptr, size, caller);
|
||||||
|
add_log(srv, MEM_REALLOC, caller, ptr, ret_ptr, size, size_real);
|
||||||
|
ret = ret_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&srv->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mpp_osal_free(const char *caller, void *ptr)
|
||||||
|
{
|
||||||
|
MppMemSrv *srv = get_srv_mem(caller);
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
if (!ptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!srv || !srv->debug) {
|
||||||
|
os_free(ptr);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&srv->lock);
|
||||||
|
|
||||||
|
if (srv->debug & MEM_POISON) {
|
||||||
|
// NODE: keep this node and delete delay node
|
||||||
|
void *ret = delay_del_node(srv, ptr, &size, caller);
|
||||||
|
if (ret)
|
||||||
|
os_free((rk_u8 *)ret - MEM_ALIGN);
|
||||||
|
|
||||||
|
add_log(srv, MEM_FREE_DELAY, caller, ptr, ret, size, 0);
|
||||||
|
} else {
|
||||||
|
void *ptr_real = (rk_u8 *)ptr - MEM_HEAD_ROOM(srv->debug);
|
||||||
|
|
||||||
|
// NODE: delete node and return size here
|
||||||
|
del_node(srv, ptr, &size, caller);
|
||||||
|
check_mem(srv, ptr, size, caller);
|
||||||
|
os_free(ptr_real);
|
||||||
|
add_log(srv, MEM_FREE, caller, ptr, ptr_real, size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&srv->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dump memory status */
|
||||||
|
void mpp_show_mem_status()
|
||||||
|
{
|
||||||
|
MppMemSrv *srv = get_srv_mem_f();
|
||||||
|
|
||||||
|
if (srv) {
|
||||||
|
pthread_mutex_lock(&srv->lock);
|
||||||
|
if (srv->debug & MEM_DEBUG_EN)
|
||||||
|
mpp_mem_srv_dump(srv, __FUNCTION__);
|
||||||
|
pthread_mutex_unlock(&srv->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rk_u32 mpp_mem_total_now()
|
||||||
|
{
|
||||||
|
MppMemSrv *srv = get_srv_mem_f();
|
||||||
|
rk_u32 total_now = 0;
|
||||||
|
|
||||||
|
if (srv) {
|
||||||
|
pthread_mutex_lock(&srv->lock);
|
||||||
|
total_now = srv->total_size;
|
||||||
|
pthread_mutex_unlock(&srv->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return total_now;
|
||||||
|
}
|
||||||
|
|
||||||
|
rk_u32 mpp_mem_total_max()
|
||||||
|
{
|
||||||
|
MppMemSrv *srv = get_srv_mem_f();
|
||||||
|
rk_u32 total_max = 0;
|
||||||
|
|
||||||
|
if (srv) {
|
||||||
|
pthread_mutex_lock(&srv->lock);
|
||||||
|
total_max = srv->total_max;
|
||||||
|
pthread_mutex_unlock(&srv->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return total_max;
|
||||||
|
}
|
784
osal/mpp_mem.cpp
784
osal/mpp_mem.cpp
@@ -1,784 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 Rockchip Electronics Co. LTD
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MODULE_TAG "mpp_mem"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "mpp_env.h"
|
|
||||||
#include "mpp_mem.h"
|
|
||||||
#include "mpp_list.h"
|
|
||||||
#include "mpp_debug.h"
|
|
||||||
#include "mpp_common.h"
|
|
||||||
|
|
||||||
#include "os_mem.h"
|
|
||||||
|
|
||||||
// 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 MEM_MAX_INDEX (0x7fffffff)
|
|
||||||
#define MEM_ALIGN 32
|
|
||||||
#define MEM_ALIGN_MASK (MEM_ALIGN - 1)
|
|
||||||
#define MEM_ALIGNED(x) (((x) + MEM_ALIGN_MASK) & (~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)
|
|
||||||
|
|
||||||
#define MPP_MEM_ASSERT(cond) \
|
|
||||||
do { \
|
|
||||||
if (!(cond)) { \
|
|
||||||
mpp_err("found mpp_mem assert failed, start dumping:\n"); \
|
|
||||||
MppMemService::get_inst()->dump(__FUNCTION__); \
|
|
||||||
mpp_assert(cond); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
typedef enum MppMemOps_e {
|
|
||||||
MEM_MALLOC,
|
|
||||||
MEM_REALLOC,
|
|
||||||
MEM_FREE,
|
|
||||||
MEM_FREE_DELAY,
|
|
||||||
|
|
||||||
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:
|
|
||||||
static MppMemService *get_inst() {
|
|
||||||
static MppMemService instance;
|
|
||||||
return &instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
RK_U32 total_now(void) { return m_total_size; }
|
|
||||||
RK_U32 total_max(void) { return m_total_max; }
|
|
||||||
|
|
||||||
Mutex *m_lock;
|
|
||||||
RK_U32 debug;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// avoid any unwanted function
|
|
||||||
MppMemService();
|
|
||||||
~MppMemService();
|
|
||||||
MppMemService(const MppMemService &);
|
|
||||||
MppMemService &operator=(const MppMemService &);
|
|
||||||
|
|
||||||
// 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 m_total_size;
|
|
||||||
RK_U32 m_total_max;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *ops2str[MEM_OPS_BUTT] = {
|
|
||||||
"malloc",
|
|
||||||
"realloc",
|
|
||||||
"free",
|
|
||||||
"delayed",
|
|
||||||
};
|
|
||||||
|
|
||||||
static void show_mem(RK_U32 *buf, RK_S32 size)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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),
|
|
||||||
m_total_size(0),
|
|
||||||
m_total_max(0)
|
|
||||||
{
|
|
||||||
mpp_env_get_u32("mpp_mem_debug", &debug, 0);
|
|
||||||
|
|
||||||
m_lock = new Mutex();
|
|
||||||
|
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MppMemService::~MppMemService()
|
|
||||||
{
|
|
||||||
if (debug & MEM_DEBUG_EN) {
|
|
||||||
AutoMutex auto_lock(m_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->index, 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_lock) {
|
|
||||||
delete m_lock;
|
|
||||||
m_lock = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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, m_total_size, size, caller);
|
|
||||||
|
|
||||||
if (nodes_cnt >= nodes_max) {
|
|
||||||
mpp_err("******************************************************\n");
|
|
||||||
mpp_err("* Reach max limit of mpp_mem counter %5d *\n", nodes_max);
|
|
||||||
mpp_err("* Increase limit by setup env mpp_mem_node_max or *\n");
|
|
||||||
mpp_err("* recompile mpp with larger macro MEM_NODE_MAX value *\n");
|
|
||||||
mpp_err("******************************************************\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++;
|
|
||||||
m_total_size += size;
|
|
||||||
if (m_total_size > m_total_max)
|
|
||||||
m_total_max = m_total_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--;
|
|
||||||
m_total_size -= node->size;
|
|
||||||
|
|
||||||
if (debug & MEM_NODE_LOG)
|
|
||||||
mpp_log("mem cnt: %5d total %8d dec size %8d at %s\n",
|
|
||||||
nodes_cnt, m_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, m_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;
|
|
||||||
m_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, m_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) {
|
|
||||||
m_total_size += size;
|
|
||||||
m_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)
|
|
||||||
{
|
|
||||||
MppMemService *srv = MppMemService::get_inst();
|
|
||||||
MppMemLog *log = &logs[log_idx];
|
|
||||||
|
|
||||||
if (srv->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)
|
|
||||||
{
|
|
||||||
MppMemService *srv = MppMemService::get_inst();
|
|
||||||
RK_U32 debug = srv->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;
|
|
||||||
|
|
||||||
os_malloc(&ptr, MEM_ALIGN, size_real);
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
AutoMutex auto_lock(srv->m_lock);
|
|
||||||
srv->add_log(MEM_MALLOC, caller, NULL, ptr, size, size_real);
|
|
||||||
|
|
||||||
if (ptr) {
|
|
||||||
if (debug & MEM_EXT_ROOM) {
|
|
||||||
ptr = (RK_U8 *)ptr + MEM_ALIGN;
|
|
||||||
set_mem_ext_room(ptr, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
srv->add_node(caller, ptr, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *mpp_osal_calloc(const char *caller, size_t size)
|
|
||||||
{
|
|
||||||
void *ptr = mpp_osal_malloc(caller, size);
|
|
||||||
if (ptr)
|
|
||||||
memset(ptr, 0, size);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *mpp_osal_realloc(const char *caller, void *ptr, size_t size)
|
|
||||||
{
|
|
||||||
MppMemService *srv = MppMemService::get_inst();
|
|
||||||
RK_U32 debug = srv->debug;
|
|
||||||
void *ret;
|
|
||||||
|
|
||||||
if (NULL == ptr)
|
|
||||||
return mpp_osal_malloc(caller, size);
|
|
||||||
|
|
||||||
if (0 == size) {
|
|
||||||
mpp_err("warning: realloc %p to zero size\n", ptr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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 {
|
|
||||||
AutoMutex auto_lock(srv->m_lock);
|
|
||||||
|
|
||||||
// if realloc success reset the node and record
|
|
||||||
if (debug) {
|
|
||||||
void *ret_ptr = (debug & MEM_EXT_ROOM) ?
|
|
||||||
((RK_U8 *)ret + MEM_ALIGN) : (ret);
|
|
||||||
|
|
||||||
srv->reset_node(caller, ptr, ret_ptr, size);
|
|
||||||
srv->add_log(MEM_REALLOC, caller, ptr, ret_ptr, size, size_real);
|
|
||||||
ret = ret_ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mpp_osal_free(const char *caller, void *ptr)
|
|
||||||
{
|
|
||||||
MppMemService *srv = MppMemService::get_inst();
|
|
||||||
RK_U32 debug = srv->debug;
|
|
||||||
|
|
||||||
if (NULL == ptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!debug) {
|
|
||||||
os_free(ptr);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size = 0;
|
|
||||||
|
|
||||||
AutoMutex auto_lock(srv->m_lock);
|
|
||||||
if (debug & MEM_POISON) {
|
|
||||||
// NODE: keep this node and delete delay node
|
|
||||||
void *ret = srv->delay_del_node(caller, ptr, &size);
|
|
||||||
if (ret)
|
|
||||||
os_free((RK_U8 *)ret - MEM_ALIGN);
|
|
||||||
|
|
||||||
srv->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
|
|
||||||
srv->del_node(caller, ptr, &size);
|
|
||||||
srv->chk_mem(caller, ptr, size);
|
|
||||||
os_free(ptr_real);
|
|
||||||
srv->add_log(MEM_FREE, caller, ptr, ptr_real, size, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dump memory status */
|
|
||||||
void mpp_show_mem_status()
|
|
||||||
{
|
|
||||||
MppMemService *srv = MppMemService::get_inst();
|
|
||||||
AutoMutex auto_lock(srv->m_lock);
|
|
||||||
|
|
||||||
if (srv->debug & MEM_DEBUG_EN)
|
|
||||||
srv->dump(__FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
RK_U32 mpp_mem_total_now()
|
|
||||||
{
|
|
||||||
MppMemService *srv = MppMemService::get_inst();
|
|
||||||
AutoMutex auto_lock(srv->m_lock);
|
|
||||||
|
|
||||||
return srv->total_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
RK_U32 mpp_mem_total_max()
|
|
||||||
{
|
|
||||||
MppMemService *srv = MppMemService::get_inst();
|
|
||||||
AutoMutex auto_lock(srv->m_lock);
|
|
||||||
|
|
||||||
return srv->total_max();
|
|
||||||
}
|
|
@@ -1,17 +1,6 @@
|
|||||||
|
/* SPDX-License-Identifier: Apache-2.0 OR MIT */
|
||||||
/*
|
/*
|
||||||
* Copyright 2015 Rockchip Electronics Co. LTD
|
* Copyright (c) 2015 Rockchip Electronics Co., Ltd.
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MODULE_TAG "mpp_mem_test"
|
#define MODULE_TAG "mpp_mem_test"
|
||||||
|
Reference in New Issue
Block a user