1 #include "stdlib.h"
2 #include "stdint.h"
3 #include "string.h"
4 #include "aos_system.h"
5 #include "amp_memmgt.h"
6 
7 typedef struct amp_memmgt_rec_stru_tag {
8     void *ptr;
9     unsigned int size;
10     unsigned int lr;
11     unsigned int seq;
12     struct amp_memmgt_rec_stru_tag *next;
13     struct amp_memmgt_rec_stru_tag *prev;
14 } amp_memmgt_rec_stru;
15 
16 static amp_memmgt_rec_stru *g_mem_rec_head = NULL;
17 static amp_memmgt_rec_stru *g_mem_rec_tail = NULL;
18 static amp_memmgt_config_t g_mem_config;
19 
20 static unsigned int g_mem_rec_num = 0;
21 static unsigned int g_mem_max[MEMMGT_TOTAL_PT_NUM] = {0};
22 static unsigned int g_mem_total[MEMMGT_TOTAL_PT_NUM] = {0};
23 static aos_mutex_t g_mem_rec_lock = NULL;
24 
25 #ifdef MEMMGT_MEM_DBG_STATIC
add_node(void * ptr,unsigned int size,unsigned int lr,int ptno)26 static void add_node(void *ptr, unsigned int size, unsigned int lr, int ptno)
27 {
28     amp_memmgt_rec_stru * node = NULL;
29 
30     node = g_mem_config.malloc_fn(sizeof(amp_memmgt_rec_stru));
31     if(NULL == node) {
32         return;
33     }
34     memset(node, 0, sizeof(amp_memmgt_rec_stru));
35 
36     aos_mutex_lock(&g_mem_rec_lock, AOS_WAIT_FOREVER);
37     g_mem_rec_tail->next = node;
38     node->prev           = g_mem_rec_tail;
39     g_mem_rec_tail       = node;
40 
41     node->ptr  = ptr;
42     node->size = size;
43     node->seq  = g_mem_rec_num;
44     node->lr   = lr;
45 
46     *(unsigned int *)ptr = (unsigned int)node;
47 
48     g_mem_rec_num ++;
49     aos_mutex_unlock(&g_mem_rec_lock);
50 }
51 
delete_node(amp_memmgt_rec_stru * node)52 static void delete_node(amp_memmgt_rec_stru *node)
53 {
54     if(node == NULL) {
55         return;
56     }
57     aos_mutex_lock(&g_mem_rec_lock, AOS_WAIT_FOREVER);
58     if(node == g_mem_rec_tail) {
59         g_mem_rec_tail = node->prev;
60     }
61     if(NULL != node->prev) {
62         node->prev->next = node->next;
63     }
64 
65     if(NULL != node->next) {
66         node->next->prev = node->prev;
67     }
68 
69     if (g_mem_config.free_fn) {
70         g_mem_config.free_fn(node);
71     }
72 
73     aos_mutex_unlock(&g_mem_rec_lock);
74 }
75 #endif
76 
77 
amp_memmgt_init(amp_memmgt_config_t * config)78 int amp_memmgt_init(amp_memmgt_config_t *config)
79 {
80     if ((config->malloc_fn == NULL) || (config->free_fn == NULL)) {
81         return -1;
82     }
83 
84     memcpy(&g_mem_config, config, sizeof(amp_memmgt_config_t));
85 
86 #ifdef MEMMGT_MEM_DBG_STATIC
87     if(NULL == g_mem_rec_head) {
88         g_mem_rec_head = config->malloc_fn(sizeof(amp_memmgt_rec_stru));
89         memset(g_mem_rec_head, 0, sizeof(amp_memmgt_rec_stru));
90         aos_mutex_new(&g_mem_rec_lock);
91         g_mem_rec_tail = g_mem_rec_head;
92     }
93 #endif
94 
95     return 0;
96 }
97 
amp_memmgt_mem_show_rec()98 void amp_memmgt_mem_show_rec()
99 {
100 #ifdef MEMMGT_MEM_DBG_STATIC
101     aos_mutex_lock(&g_mem_rec_lock, AOS_WAIT_FOREVER);
102     amp_memmgt_rec_stru *rec_node = g_mem_rec_head;
103     if(rec_node != NULL) {
104         aos_printf("seq   addr       size         LR\r\n");
105 
106         while(rec_node) {
107             if(rec_node->ptr) {
108                 aos_printf("%4u ", rec_node->seq);
109                 aos_printf("0x%x ", rec_node->ptr);
110                 aos_printf("0x%x   ", rec_node->size);
111                 aos_printf("0x%x \n", rec_node->lr);
112             }
113             rec_node = rec_node->next;
114         }
115     }
116     aos_mutex_unlock(&g_mem_rec_lock);
117 #endif
118 
119     for (int i = 0; i < g_mem_config.pt_num; i++) {
120         aos_printf("\r\nPT[%d]: max mem %u, now mem %u \n", i, g_mem_max[i], g_mem_total[i]);
121     }
122 }
123 
amp_memmgt_malloc(unsigned int size,unsigned int lr,int ptno)124 void *amp_memmgt_malloc(unsigned int size, unsigned int lr, int ptno)
125 {
126     void *ptr = NULL;
127 
128     unsigned int alloc_size = size + MEMMGT_OFFSET;
129     unsigned int once_size  = alloc_size;
130 
131     if(NULL == g_mem_config.malloc_fn) {
132         return NULL;
133     }
134 
135 #ifdef MEMMGT_MEM_SIZE_CHECK
136 #ifdef MEMMGT_MEM_DBG_STATIC
137     once_size += sizeof(amp_memmgt_rec_stru);
138 #endif
139     if((g_mem_config.mem_limit[ptno] != 0) && (g_mem_total[ptno] + once_size > g_mem_config.mem_limit[ptno])) {
140         aos_printf("[amp_memory] memory leak, pt %d, size %d, lr 0x%x, total size 0x%x, limit 0x%x\n", ptno, size, lr, g_mem_total[ptno], g_mem_config.mem_limit[ptno]);
141         return NULL;
142     }
143 #endif
144     ptr = g_mem_config.malloc_fn(alloc_size);
145     if(NULL == ptr) {
146         aos_printf("[amp_memory%s] lr 0x%x memory alloc failed, system will stop !!!\n", __TIME__, lr);
147         amp_memmgt_mem_show_rec();
148         while(1) {
149             aos_msleep(1000);
150         }
151         return NULL;
152     }
153 
154     g_mem_total[ptno] += alloc_size;
155 
156 #ifdef MEMMGT_MEM_DBG_STATIC
157     add_node(ptr, alloc_size, lr, ptno);
158     g_mem_total[ptno] += sizeof(amp_memmgt_rec_stru);
159 #else
160     *(unsigned int *)ptr = alloc_size;
161 #endif
162 
163     if(g_mem_total[ptno] > g_mem_max[ptno]) {
164         g_mem_max[ptno] = g_mem_total[ptno];
165     }
166 #ifdef MEMMGT_MEM_TRACE
167     if(((1<<ptno) & g_mem_config.trace_pt) != 0) {
168         aos_printf("[amp_memory:%s] lr 0x%x alloc %p, size %d\n", __TIME__, lr, (void *)((unsigned int)ptr + MEMMGT_OFFSET), size);
169         aos_printf("                      now total malloc %u, max malloc %u\n", g_mem_total[ptno], g_mem_max[ptno]);
170     }
171 #endif
172     return (void *)((unsigned int)ptr + MEMMGT_OFFSET);
173 }
174 
amp_memmgt_realloc(void * ptr,unsigned int size,unsigned int lr,int ptno)175 void *amp_memmgt_realloc(void *ptr, unsigned int size, unsigned int lr, int ptno)
176 {
177     void *ptr_new    = NULL;
178     void *origin_ptr = NULL;
179 
180     unsigned int alloc_size = size + MEMMGT_OFFSET;
181     unsigned int old_size   = size;
182     unsigned int once_size  = alloc_size;
183 
184     if (size == 0) {
185         amp_memmgt_free(ptr, lr, ptno);
186         return NULL;
187     }
188 
189     if(NULL == g_mem_config.realloc_fn) {
190         return NULL;
191     }
192 
193 #ifdef MEMMGT_MEM_TRACE
194     if(((1<<ptno) & g_mem_config.trace_pt) != 0) {
195         aos_printf("[amp_memory:%s] lr 0x%x realloc %p, size %d\n", __TIME__, lr, ptr, size);
196     }
197 #endif
198 
199 #ifdef MEMMGT_MEM_DBG_STATIC
200     amp_memmgt_rec_stru *node = *(unsigned int *)((uint32_t)ptr - MEMMGT_OFFSET);
201     amp_memmgt_rec_stru tmp_node;
202     memcpy(&tmp_node, node, sizeof(amp_memmgt_rec_stru));
203 
204     old_size = node->size;
205 #else
206     old_size = *(unsigned int *)((unsigned int)ptr - 4);
207 #endif
208     origin_ptr = (void *)((unsigned int)ptr - 4);
209 
210 #ifdef MEMMGT_MEM_SIZE_CHECK
211 #ifdef MEMMGT_MEM_DBG_STATIC
212     once_size += sizeof(amp_memmgt_rec_stru);
213 #endif
214     once_size -= old_size;
215     if((g_mem_config.mem_limit[ptno] != 0) && (g_mem_total[ptno] + once_size > g_mem_config.mem_limit[ptno])) {
216         aos_printf("[amp_memory:%s] memory leak, pt %d, size %d, lr 0x%x, total size 0x%x, limit 0x%x\n", __TIME__,
217                 ptno, size, lr, g_mem_total[ptno], g_mem_config.mem_limit[ptno]);
218         return NULL;
219     }
220 #endif
221 
222     ptr_new = g_mem_config.realloc_fn(origin_ptr, alloc_size);
223     if(NULL == ptr_new) {
224         aos_printf("[amp_memory:%s] lr 0x%x memory realloc failed, system will stop !!!\n", __TIME__, lr);
225         amp_memmgt_mem_show_rec();
226         while(1) {
227             aos_msleep(1000);
228         }
229         return NULL;
230     }
231 
232     g_mem_total[ptno] += alloc_size - old_size;
233     if(g_mem_total[ptno] > g_mem_max[ptno]) {
234         g_mem_max[ptno] = g_mem_total[ptno];
235     }
236 
237 #ifdef MEMMGT_MEM_DBG_STATIC
238     if(origin_ptr != ptr_new) {
239         delete_node(node);
240         add_node(ptr_new, alloc_size, lr, ptno);
241     } else {
242         node->size = size;
243     }
244 #else
245     *(unsigned int *)ptr_new = alloc_size;
246 #endif
247 
248 #ifdef MEMMGT_MEM_TRACE
249     if(((1<<ptno) & g_mem_config.trace_pt) != 0) {
250         aos_printf("[amp_memory:%s] lr 0x%x realloc result %p\n", __TIME__, lr, (void *)((unsigned int)ptr_new + MEMMGT_OFFSET));
251         aos_printf("                      now total malloc %u, max malloc %u\n", g_mem_total[ptno], g_mem_max[ptno]);
252     }
253 #endif
254 
255     return (void *)((unsigned int)ptr_new + MEMMGT_OFFSET);
256 }
257 
amp_memmgt_free(void * ptr,unsigned int lr,int ptno)258 void amp_memmgt_free(void *ptr, unsigned int lr, int ptno)
259 {
260     void       *origin_ptr = (void *)((uint32_t)ptr - MEMMGT_OFFSET);
261     unsigned int free_size = 0;
262 
263     if (ptr == NULL) {
264         return;
265     }
266 
267 #ifdef MEMMGT_MEM_DBG_STATIC
268     amp_memmgt_rec_stru *node = NULL;
269     node = (amp_memmgt_rec_stru *)(*(unsigned int *)origin_ptr);
270     free_size = node->size;
271 #else
272     free_size  = *(unsigned int *)((unsigned int)origin_ptr);
273 #endif
274     g_mem_total[ptno] -= free_size;
275 
276 #ifdef MEMMGT_MEM_DBG_STATIC
277     delete_node(node);
278 #endif
279     g_mem_config.free_fn(origin_ptr);
280 
281 #ifdef MEMMGT_MEM_TRACE
282     if(((1<<ptno) & g_mem_config.trace_pt) != 0) {
283         aos_printf("[amp_memory:%s] lr 0x%x free %p\n", __TIME__, lr, ptr);
284         aos_printf("                      now total malloc %u, max malloc %u\n", g_mem_total[ptno], g_mem_max[ptno]);
285     }
286 #endif
287 }
288 
amp_malloc_usable_size(void * ptr)289 unsigned int amp_malloc_usable_size(void *ptr)
290 {
291     void *origin_ptr = (void *)((uint32_t)ptr - MEMMGT_OFFSET);
292     uint32_t size = 0;
293 
294     if (ptr == NULL) {
295         return 0;
296     }
297 
298 #ifdef MEMMGT_MEM_DBG_STATIC
299     amp_memmgt_rec_stru *node = NULL;
300     node = (amp_memmgt_rec_stru *)(*(unsigned int *)origin_ptr);
301     if (node != NULL) {
302         size = node->size;
303     }
304 #else
305     size  = *(unsigned int *)((unsigned int)origin_ptr);
306 #endif
307     return size - MEMMGT_OFFSET;
308 }
309