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