1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "mpp_mem"
7
8 #include <string.h>
9
10 #include "mpp_env.h"
11 #include "mpp_mem.h"
12 #include "mpp_list.h"
13 #include "mpp_debug.h"
14 #include "mpp_common.h"
15 #include "mpp_singleton.h"
16
17 #include "os_mem.h"
18
19 // mpp_mem_debug bit mask
20 #define MEM_DEBUG_EN (0x00000001)
21 // NOTE: runtime log need debug enable
22 #define MEM_RUNTIME_LOG (0x00000002)
23 #define MEM_NODE_LOG (0x00000004)
24 #define MEM_EXT_ROOM (0x00000010)
25 #define MEM_POISON (0x00000020)
26
27 // default memory align size is set to 32
28 #define MEM_MAX_INDEX (0x7fffffff)
29 #define MEM_ALIGN 32
30 #define MEM_ALIGN_MASK (MEM_ALIGN - 1)
31 #define MEM_ALIGNED(x) (((x) + MEM_ALIGN_MASK) & (~MEM_ALIGN_MASK))
32 #define MEM_HEAD_ROOM(debug) ((debug & MEM_EXT_ROOM) ? (MEM_ALIGN) : (0))
33 #define MEM_NODE_MAX (1024)
34 #define MEM_FREE_MAX (512)
35 #define MEM_LOG_MAX (1024)
36 #define MEM_CHECK_MARK (0xdd)
37 #define MEM_HEAD_MASK (0xab)
38 #define MEM_TAIL_MASK (0xcd)
39
40 #define MPP_MEM_ASSERT(srv, cond) \
41 do { \
42 if (!(cond)) { \
43 mpp_err("found mpp_mem assert failed, start dumping:\n"); \
44 mpp_mem_srv_dump(srv, __FUNCTION__); \
45 mpp_assert(cond); \
46 } \
47 } while (0)
48
49 #define get_srv_mem(caller) \
50 ({ \
51 MppMemSrv *__tmp; \
52 if (!srv_mem) { \
53 mpp_mem_srv_init(); \
54 } \
55 if (srv_mem) { \
56 __tmp = srv_mem; \
57 } else { \
58 mpp_err("mpp mem srv not init at %s : %s\n", __FUNCTION__, caller); \
59 __tmp = NULL; \
60 } \
61 __tmp; \
62 })
63
64 #define get_srv_mem_f() \
65 ({ \
66 MppMemSrv *__tmp; \
67 if (!srv_mem) { \
68 mpp_mem_srv_init(); \
69 } \
70 if (srv_mem) { \
71 __tmp = srv_mem; \
72 } else { \
73 mpp_err("mpp mem srv not init at %s\n", __FUNCTION__); \
74 __tmp = NULL; \
75 } \
76 __tmp; \
77 })
78
79 typedef enum MppMemOps_e {
80 MEM_MALLOC,
81 MEM_REALLOC,
82 MEM_FREE,
83 MEM_FREE_DELAY,
84
85 MEM_OPS_BUTT,
86 } MppMemOps;
87
88 /*
89 * Here we combined valid flag with index value to keep node structure small
90 * If index >= 0 this node is valid otherwise it is invalid
91 * When we need to invalid one index use ~ to revert all bit
92 * Then max valid index is 0x7fffffff. When index goes beyond it and becomes
93 * negative value index will be reset to zero.
94 */
95 typedef struct MppMemNode_t {
96 rk_s32 index;
97 size_t size;
98 void *ptr;
99 const char *caller;
100 } MppMemNode;
101
102 typedef struct MppMemLog_t {
103 rk_u32 index;
104 MppMemOps ops;
105 size_t size_0; // size at input
106 size_t size_1; // size at output
107 void *ptr; // ptr at input
108 void *ret; // ptr at output
109 MppMemNode *node; // node for operation
110 const char *caller;
111 } MppMemLog;
112
113 typedef struct MppMemSrv_t {
114 // data for node record and delay free check
115 rk_s32 nodes_max;
116 rk_s32 nodes_idx;
117 rk_s32 nodes_cnt;
118 rk_s32 frees_max;
119 rk_s32 frees_idx;
120 rk_s32 frees_cnt;
121
122 MppMemNode *nodes;
123 MppMemNode *frees;
124
125 // data for log record
126 rk_u32 log_index;
127 rk_s32 log_max;
128 rk_s32 log_idx;
129 rk_s32 log_cnt;
130
131 MppMemLog *logs;
132 rk_u32 total_size;
133 rk_u32 total_max;
134 pthread_mutex_t lock;
135 rk_u32 debug;
136 } MppMemSrv;
137
138 static MppMemSrv *srv_mem = NULL;
139
140 static const char *ops2str[MEM_OPS_BUTT] = {
141 "malloc",
142 "realloc",
143 "free",
144 "delayed",
145 };
146
show_mem(rk_u32 * buf,rk_s32 size)147 static void show_mem(rk_u32 *buf, rk_s32 size)
148 {
149 mpp_err("dumping buf %p size %d start\n", buf, size);
150
151 while (size > 0) {
152 if (size >= 16) {
153 mpp_err("%08x %08x %08x %08x\n", buf[0], buf[1], buf[2], buf[3]);
154 buf += 4;
155 size -= 16;
156 } else if (size >= 12) {
157 mpp_err("%08x %08x %08x\n", buf[0], buf[1], buf[2]);
158 buf += 3;
159 size -= 12;
160 } else if (size >= 8) {
161 mpp_err("%08x %08x\n", buf[0], buf[1]);
162 buf += 2;
163 size -= 8;
164 } else if (size >= 4) {
165 mpp_err("%08x\n", buf[0]);
166 buf += 1;
167 size -= 4;
168 } else {
169 mpp_log("end with size %d\n", size);
170 break;
171 }
172 }
173 mpp_err("dumping buf %p size %d end\n", buf, size);
174 }
175
set_mem_ext_room(void * p,size_t size)176 static void set_mem_ext_room(void *p, size_t size)
177 {
178 memset((rk_u8 *)p - MEM_ALIGN, MEM_HEAD_MASK, MEM_ALIGN);
179 memset((rk_u8 *)p + size, MEM_TAIL_MASK, MEM_ALIGN);
180 }
181
mpp_mem_srv_dump(MppMemSrv * srv,const char * caller)182 void mpp_mem_srv_dump(MppMemSrv *srv, const char *caller)
183 {
184 MppMemNode *node = srv->nodes;
185 rk_s32 start;
186 rk_s32 tmp_cnt;
187 rk_s32 i;
188
189 mpp_log("mpp_mem enter status dumping from %s:\n", caller);
190
191 mpp_log("mpp_mem node count %d:\n", srv->nodes_cnt);
192 if (srv->nodes_cnt) {
193 for (i = 0; i < srv->nodes_max; i++, node++) {
194 if (node->index < 0)
195 continue;
196
197 mpp_log("mpp_memory index %d caller %-32s size %-8u ptr %p\n",
198 node->index, node->caller, node->size, node->ptr);
199 }
200 }
201
202 node = srv->frees;
203 mpp_log("mpp_mem free count %d:\n", srv->frees_cnt);
204 if (srv->frees_cnt) {
205 for (i = 0; i < srv->frees_max; i++, node++) {
206 if (node->index < 0)
207 continue;
208
209 mpp_log("mpp_freed index %d caller %-32s size %-8u ptr %p\n",
210 node->index, node->caller, node->size, node->ptr);
211 }
212 }
213
214 start = srv->log_idx - srv->log_cnt;
215 tmp_cnt = srv->log_cnt;
216
217 if (start < 0)
218 start += srv->log_max;
219
220 mpp_log("mpp_mem enter log dumping:\n");
221
222 while (tmp_cnt) {
223 MppMemLog *log = &srv->logs[start];
224
225 mpp_log("idx %-8d op: %-7s from %-32s ptr %10p %10p size %7d %7d\n",
226 log->index, ops2str[log->ops], log->caller,
227 log->ptr, log->ret, log->size_0, log->size_1);
228
229 start++;
230 if (start >= srv->log_max)
231 start = 0;
232
233 tmp_cnt--;
234 }
235 }
236
check_mem(MppMemSrv * srv,void * ptr,size_t size,const char * caller)237 static void check_mem(MppMemSrv *srv, void *ptr, size_t size, const char *caller)
238 {
239 rk_u8 *p;
240 rk_s32 i;
241
242 if ((srv->debug & MEM_EXT_ROOM) == 0)
243 return ;
244
245 p = (rk_u8 *)ptr - MEM_ALIGN;
246
247 for (i = 0; i < MEM_ALIGN; i++) {
248 if (p[i] != MEM_HEAD_MASK) {
249 mpp_err("%s checking ptr %p head room found error!\n", caller, ptr);
250 mpp_mem_srv_dump(srv, caller);
251 show_mem((rk_u32 *)p, MEM_ALIGN);
252 mpp_abort();
253 }
254 }
255
256 p = (rk_u8 *)ptr + size;
257 for (i = 0; i < MEM_ALIGN; i++) {
258 if (p[i] != MEM_TAIL_MASK) {
259 mpp_err("%s checking ptr %p tail room found error!\n", caller, ptr);
260 mpp_mem_srv_dump(srv, caller);
261 show_mem((rk_u32 *)p, MEM_ALIGN);
262 mpp_abort();
263 }
264 }
265 }
266
check_node(MppMemSrv * srv,MppMemNode * node,const char * caller)267 static void check_node(MppMemSrv *srv, MppMemNode *node, const char *caller)
268 {
269 if ((srv->debug & MEM_EXT_ROOM) == 0)
270 return ;
271
272 check_mem(srv, node->ptr, node->size, caller);
273 }
274
check_poison(MppMemSrv * srv,MppMemNode * node)275 static rk_s32 check_poison(MppMemSrv *srv, MppMemNode *node)
276 {
277 if ((srv->debug & MEM_POISON) == 0)
278 return 0;
279
280 // check oldest memory and free it
281 rk_u8 *node_ptr = (rk_u8 *)node->ptr;
282 rk_s32 size = node->size;
283 rk_s32 i = 0;
284 rk_s32 start = -1;
285 rk_s32 end = -1;
286
287 if (size >= 1024)
288 return 0;
289
290 for (; i < size; i++) {
291 if (node_ptr[i] != MEM_CHECK_MARK) {
292 if (start < 0) {
293 start = i;
294 }
295 end = i + 1;
296 }
297 }
298
299 if (start >= 0 || end >= 0) {
300 mpp_err_f("found memory %p size %d caller %s overwrite from %d to %d\n",
301 node_ptr, size, node->caller, start, end);
302 mpp_mem_srv_dump(srv, node->caller);
303 }
304
305 return end - start;
306 }
307
reset_node(MppMemSrv * srv,void * ptr,void * ret,size_t size,const char * caller)308 static void reset_node(MppMemSrv *srv, void *ptr, void *ret, size_t size, const char *caller)
309 {
310 MppMemNode *node = srv->nodes;
311 rk_s32 i = 0;
312
313 if (srv->debug & MEM_NODE_LOG)
314 mpp_log("mem cnt: %5d total %8d equ size %8d at %s\n",
315 srv->nodes_cnt, srv->total_size, size, __FUNCTION__);
316
317 MPP_MEM_ASSERT(srv, srv->nodes_cnt <= srv->nodes_max);
318
319 for (i = 0; i < srv->nodes_max; i++, node++) {
320 if (node->index >= 0 && node->ptr == ptr) {
321 srv->total_size += size;
322 srv->total_size -= node->size;
323
324 node->ptr = ret;
325 node->size = size;
326 node->caller = caller;
327
328 if (srv->debug & MEM_EXT_ROOM)
329 set_mem_ext_room(ret, size);
330 break;
331 }
332 }
333 }
334
add_log(MppMemSrv * srv,MppMemOps ops,const char * caller,void * ptr,void * ret,size_t size_0,size_t size_1)335 static void add_log(MppMemSrv *srv, MppMemOps ops, const char *caller, void *ptr,
336 void *ret, size_t size_0, size_t size_1)
337 {
338 MppMemLog *log = &srv->logs[srv->log_idx];
339
340 if (srv->debug & MEM_RUNTIME_LOG)
341 mpp_log("%-7s ptr %010p %010p size %8u %8u at %s\n",
342 ops2str[ops], ptr, ret, size_0, size_1, caller);
343
344 log->index = srv->log_index++;
345 log->ops = ops;
346 log->size_0 = size_0;
347 log->size_1 = size_1;
348 log->ptr = ptr;
349 log->ret = ret;
350 log->node = NULL;
351 log->caller = caller;
352
353 srv->log_idx++;
354 if (srv->log_idx >= srv->log_max)
355 srv->log_idx = 0;
356
357 if (srv->log_cnt < srv->log_max)
358 srv->log_cnt++;
359 }
360
add_node(MppMemSrv * srv,void * ptr,size_t size,const char * caller)361 static void add_node(MppMemSrv *srv, void *ptr, size_t size, const char *caller)
362 {
363 MppMemNode *node;
364 rk_s32 i;
365
366 if (srv->debug & MEM_NODE_LOG)
367 mpp_log("mem cnt: %5d total %8d inc size %8d at %s\n",
368 srv->nodes_cnt, srv->total_size, size, caller);
369
370 if (srv->nodes_cnt >= srv->nodes_max) {
371 mpp_err("******************************************************\n");
372 mpp_err("* Reach max limit of mpp_mem counter %5d *\n", srv->nodes_max);
373 mpp_err("* Increase limit by setup env mpp_mem_node_max or *\n");
374 mpp_err("* recompile mpp with larger macro MEM_NODE_MAX value *\n");
375 mpp_err("******************************************************\n");
376 mpp_abort();
377 }
378
379 node = srv->nodes;
380 for (i = 0; i < srv->nodes_max; i++, node++) {
381 if (node->index < 0) {
382 node->index = srv->nodes_idx++;
383 node->size = size;
384 node->ptr = ptr;
385 node->caller = caller;
386
387 // NOTE: reset node index on revert
388 if (srv->nodes_idx < 0)
389 srv->nodes_idx = 0;
390
391 srv->nodes_cnt++;
392 srv->total_size += size;
393 if (srv->total_size > srv->total_max)
394 srv->total_max = srv->total_size;
395 break;
396 }
397 }
398 }
399
del_node(MppMemSrv * srv,void * ptr,size_t * size,const char * caller)400 static void del_node(MppMemSrv *srv, void *ptr, size_t *size, const char *caller)
401 {
402 MppMemNode *node = srv->nodes;
403 rk_s32 i;
404
405 MPP_MEM_ASSERT(srv, srv->nodes_cnt <= srv->nodes_max);
406
407 for (i = 0; i < srv->nodes_max; i++, node++) {
408 if (node->index >= 0 && node->ptr == ptr) {
409 *size = node->size;
410 node->index = ~node->index;
411 srv->nodes_cnt--;
412 srv->total_size -= node->size;
413
414 if (srv->debug & MEM_NODE_LOG)
415 mpp_log("mem cnt: %5d total %8d dec size %8d at %s\n",
416 srv->nodes_cnt, srv->total_size, node->size, caller);
417 return ;
418 }
419 }
420
421 mpp_err("%s fail to find node with ptr %p\n", caller, ptr);
422 mpp_abort();
423 return ;
424 }
425
delay_del_node(MppMemSrv * srv,void * ptr,size_t * size,const char * caller)426 static void *delay_del_node(MppMemSrv *srv, void *ptr, size_t *size, const char *caller)
427 {
428 MppMemNode *node = srv->nodes;
429 MppMemNode *free_node = NULL;
430 void *ret = NULL;
431 rk_s32 i = 0;
432
433 // clear output first
434 *size = 0;
435
436 // find the node to save
437 MPP_MEM_ASSERT(srv, srv->nodes_cnt <= srv->nodes_max);
438 for (i = 0; i < srv->nodes_max; i++, node++) {
439 if (node->index >= 0 && node->ptr == ptr) {
440 check_node(srv, node, caller);
441 break;
442 }
443 }
444
445 MPP_MEM_ASSERT(srv, i < srv->nodes_max);
446 if (srv->debug & MEM_NODE_LOG)
447 mpp_log("mem cnt: %5d total %8d dec size %8d at %s\n",
448 srv->nodes_cnt, srv->total_size, node->size, caller);
449
450 MPP_MEM_ASSERT(srv, srv->frees_cnt <= srv->frees_max);
451
452 if (srv->frees_cnt) {
453 MppMemNode *tmp = srv->frees;
454
455 // NODE: check all data here
456 for (i = 0; i < srv->frees_max; i++, tmp++) {
457 if (tmp->index >= 0) {
458 check_node(srv, tmp, caller);
459 check_poison(srv, tmp);
460 }
461 }
462 }
463
464 if (srv->frees_cnt >= srv->frees_max) {
465 // free list full start del
466 rk_s32 frees_last = srv->frees_idx - srv->frees_cnt;
467
468 if (frees_last < 0)
469 frees_last += srv->frees_max;
470
471 free_node = &srv->frees[frees_last];
472
473 if (free_node->index >= 0) {
474 check_node(srv, free_node, caller);
475 check_poison(srv, free_node);
476 ret = free_node->ptr;
477 *size = free_node->size;
478 free_node->index = ~free_node->index;
479 srv->frees_cnt--;
480 }
481 }
482
483 MPP_MEM_ASSERT(srv, srv->frees_cnt <= srv->frees_max);
484
485 // free list is NOT full just store
486 free_node = &srv->frees[srv->frees_idx];
487 srv->frees_idx++;
488 if (srv->frees_idx >= srv->frees_max)
489 srv->frees_idx = 0;
490 if (srv->frees_cnt < srv->frees_max)
491 srv->frees_cnt++;
492
493 MPP_MEM_ASSERT(srv, srv->frees_cnt <= srv->frees_max);
494
495 memcpy(&srv->frees[srv->frees_idx], node, sizeof(*node));
496
497 if ((srv->debug & MEM_POISON) && (node->size < 1024))
498 memset(node->ptr, MEM_CHECK_MARK, node->size);
499
500 node->index = ~node->index;
501 srv->total_size -= node->size;
502 srv->nodes_cnt--;
503
504 return ret;
505 }
506
mpp_mem_srv_init()507 static void mpp_mem_srv_init()
508 {
509 MppMemSrv *srv = srv_mem;
510
511 if (srv)
512 return;
513
514 os_malloc((void **)&srv, MEM_ALIGN, sizeof(*srv));
515 mpp_assert(srv);
516 srv_mem = srv;
517
518 memset(srv, 0, sizeof(*srv));
519
520 mpp_env_get_u32("mpp_mem_debug", &srv->debug, 0);
521
522 srv->nodes_max = MEM_NODE_MAX;
523 srv->frees_max = MEM_FREE_MAX;
524 srv->log_max = MEM_LOG_MAX;
525
526 {
527 // init mutex lock
528 pthread_mutexattr_t attr;
529
530 pthread_mutexattr_init(&attr);
531 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
532 pthread_mutex_init(&srv->lock, &attr);
533 pthread_mutexattr_destroy(&attr);
534 }
535
536 pthread_mutex_lock(&srv->lock);
537
538 // add more flag if debug enabled
539 if (srv->debug)
540 srv->debug |= MEM_DEBUG_EN;
541
542 if (srv->debug & MEM_DEBUG_EN) {
543 size_t size;
544
545 mpp_env_get_u32("mpp_mem_node_max", (rk_u32 *)&srv->nodes_max, MEM_NODE_MAX);
546
547 mpp_log_f("mpp_mem_debug enabled %x max node %d\n",
548 srv->debug, srv->nodes_max);
549
550 size = srv->nodes_max * sizeof(MppMemNode);
551 os_malloc((void **)&srv->nodes, MEM_ALIGN, size);
552 mpp_assert(srv->nodes);
553 memset(srv->nodes, 0xff, size);
554 add_node(srv, srv->nodes, size, __FUNCTION__);
555
556 size = srv->frees_max * sizeof(MppMemNode);
557 os_malloc((void **)&srv->frees, MEM_ALIGN, size);
558 mpp_assert(srv->frees);
559 memset(srv->frees, 0xff, size);
560 add_node(srv, srv->frees, size, __FUNCTION__);
561
562 size = srv->log_max * sizeof(MppMemLog);
563 os_malloc((void **)&srv->logs, MEM_ALIGN, size);
564 mpp_assert(srv->logs);
565 add_node(srv, srv->logs, size, __FUNCTION__);
566
567 add_node(srv, srv, sizeof(MppMemSrv), __FUNCTION__);
568 }
569
570 pthread_mutex_unlock(&srv->lock);
571 }
572
mpp_mem_srv_deinit()573 static void mpp_mem_srv_deinit()
574 {
575 MppMemSrv *srv = get_srv_mem_f();
576
577 if (!srv)
578 return;
579
580 if (srv->debug & MEM_DEBUG_EN) {
581 MppMemNode *node = srv->nodes;
582 size_t size = 0;
583 rk_s32 i = 0;
584
585 pthread_mutex_lock(&srv->lock);
586
587 // delete self node first
588 del_node(srv, srv, &size, __FUNCTION__);
589 del_node(srv, srv->nodes, &size, __FUNCTION__);
590 del_node(srv, srv->frees, &size, __FUNCTION__);
591 del_node(srv, srv->logs, &size, __FUNCTION__);
592
593 // then check leak memory
594 if (srv->nodes_cnt) {
595 for (i = 0; i < srv->nodes_max; i++, node++) {
596 if (node->index >= 0) {
597 mpp_log("found idx %8d mem %10p size %d leaked from %s\n",
598 node->index, node->ptr, node->size, node->caller);
599 srv->nodes_cnt--;
600 add_log(srv, MEM_FREE, __FUNCTION__, node->ptr, NULL,
601 node->size, 0);
602 }
603 }
604
605 mpp_assert(srv->nodes_cnt == 0);
606 }
607
608 // finally release all delay free memory
609 if (srv->frees_cnt) {
610 node = srv->frees;
611
612 for (i = 0; i < srv->frees_max; i++, node++) {
613 if (node->index >= 0) {
614 os_free((rk_u8 *)node->ptr - MEM_HEAD_ROOM(srv->debug));
615 node->index = ~node->index;
616 srv->frees_cnt--;
617 add_log(srv, MEM_FREE_DELAY, __FUNCTION__, node->ptr, NULL,
618 node->size, 0);
619 }
620 }
621
622 mpp_assert(srv->frees_cnt == 0);
623 }
624
625 os_free(srv->nodes);
626 os_free(srv->frees);
627 os_free(srv->logs);
628
629 pthread_mutex_unlock(&srv->lock);
630 }
631
632 pthread_mutex_destroy(&srv->lock);
633
634 os_free(srv);
635 srv_mem = NULL;
636 }
637
MPP_SINGLETON(MPP_SGLN_OS_MEM,mpp_mem,mpp_mem_srv_init,mpp_mem_srv_deinit)638 MPP_SINGLETON(MPP_SGLN_OS_MEM, mpp_mem, mpp_mem_srv_init, mpp_mem_srv_deinit)
639
640 void *mpp_osal_malloc(const char *caller, size_t size)
641 {
642 MppMemSrv *srv = get_srv_mem(caller);
643 rk_u32 debug = srv->debug;
644 size_t size_align = MEM_ALIGNED(size);
645 size_t size_real = (debug & MEM_EXT_ROOM) ? (size_align + 2 * MEM_ALIGN) : (size_align);
646 void *ptr;
647
648 os_malloc(&ptr, MEM_ALIGN, size_real);
649
650 if (debug) {
651 pthread_mutex_lock(&srv->lock);
652
653 add_log(srv, MEM_MALLOC, caller, NULL, ptr, size, size_real);
654
655 if (ptr) {
656 if (debug & MEM_EXT_ROOM) {
657 ptr = (rk_u8 *)ptr + MEM_ALIGN;
658 set_mem_ext_room(ptr, size);
659 }
660
661 add_node(srv, ptr, size, caller);
662 }
663
664 pthread_mutex_unlock(&srv->lock);
665 }
666
667 return ptr;
668 }
669
mpp_osal_calloc(const char * caller,size_t size)670 void *mpp_osal_calloc(const char *caller, size_t size)
671 {
672 void *ptr = mpp_osal_malloc(caller, size);
673
674 if (ptr)
675 memset(ptr, 0, size);
676
677 return ptr;
678 }
679
mpp_osal_realloc(const char * caller,void * ptr,size_t size)680 void *mpp_osal_realloc(const char *caller, void *ptr, size_t size)
681 {
682 MppMemSrv *srv = get_srv_mem(caller);
683 rk_u32 debug = srv->debug;
684 size_t size_align;
685 size_t size_real;
686 void *ptr_real;
687 void *ret;
688
689 if (!ptr)
690 return mpp_osal_malloc(caller, size);
691
692 if (0 == size) {
693 mpp_err("warning: realloc %p to zero size\n", ptr);
694 return NULL;
695 }
696
697 size_align = MEM_ALIGNED(size);
698 size_real = (debug & MEM_EXT_ROOM) ? (size_align + 2 * MEM_ALIGN) : (size_align);
699 ptr_real = (rk_u8 *)ptr - MEM_HEAD_ROOM(debug);
700
701 os_realloc(ptr_real, &ret, MEM_ALIGN, size_align);
702
703 if (!ret) {
704 // if realloc fail the original buffer will be kept the same.
705 mpp_err("mpp_realloc ptr %p to size %d failed\n", ptr, size);
706 } else {
707 pthread_mutex_lock(&srv->lock);
708
709 // if realloc success reset the node and record
710 if (debug) {
711 void *ret_ptr = (debug & MEM_EXT_ROOM) ?
712 ((rk_u8 *)ret + MEM_ALIGN) : (ret);
713
714 reset_node(srv, ptr, ret_ptr, size, caller);
715 add_log(srv, MEM_REALLOC, caller, ptr, ret_ptr, size, size_real);
716 ret = ret_ptr;
717 }
718
719 pthread_mutex_unlock(&srv->lock);
720 }
721
722 return ret;
723 }
724
mpp_osal_free(const char * caller,void * ptr)725 void mpp_osal_free(const char *caller, void *ptr)
726 {
727 MppMemSrv *srv = get_srv_mem(caller);
728 size_t size = 0;
729
730 if (!ptr)
731 return;
732
733 if (!srv || !srv->debug) {
734 os_free(ptr);
735 return ;
736 }
737
738 pthread_mutex_lock(&srv->lock);
739
740 if (srv->debug & MEM_POISON) {
741 // NODE: keep this node and delete delay node
742 void *ret = delay_del_node(srv, ptr, &size, caller);
743 if (ret)
744 os_free((rk_u8 *)ret - MEM_ALIGN);
745
746 add_log(srv, MEM_FREE_DELAY, caller, ptr, ret, size, 0);
747 } else {
748 void *ptr_real = (rk_u8 *)ptr - MEM_HEAD_ROOM(srv->debug);
749
750 // NODE: delete node and return size here
751 del_node(srv, ptr, &size, caller);
752 check_mem(srv, ptr, size, caller);
753 os_free(ptr_real);
754 add_log(srv, MEM_FREE, caller, ptr, ptr_real, size, 0);
755 }
756
757 pthread_mutex_unlock(&srv->lock);
758 }
759
760 /* dump memory status */
mpp_show_mem_status()761 void mpp_show_mem_status()
762 {
763 MppMemSrv *srv = get_srv_mem_f();
764
765 if (srv) {
766 pthread_mutex_lock(&srv->lock);
767 if (srv->debug & MEM_DEBUG_EN)
768 mpp_mem_srv_dump(srv, __FUNCTION__);
769 pthread_mutex_unlock(&srv->lock);
770 }
771 }
772
mpp_mem_total_now()773 rk_u32 mpp_mem_total_now()
774 {
775 MppMemSrv *srv = get_srv_mem_f();
776 rk_u32 total_now = 0;
777
778 if (srv) {
779 pthread_mutex_lock(&srv->lock);
780 total_now = srv->total_size;
781 pthread_mutex_unlock(&srv->lock);
782 }
783
784 return total_now;
785 }
786
mpp_mem_total_max()787 rk_u32 mpp_mem_total_max()
788 {
789 MppMemSrv *srv = get_srv_mem_f();
790 rk_u32 total_max = 0;
791
792 if (srv) {
793 pthread_mutex_lock(&srv->lock);
794 total_max = srv->total_max;
795 pthread_mutex_unlock(&srv->lock);
796 }
797
798 return total_max;
799 }
800