xref: /rockchip-linux_mpp/osal/mpp_mem.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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