• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  * Description: Malloc function. \n
16  *
17  * History: \n
18  * 2023-2-14, Create file. \n
19  */
20 
21 #include <stddef.h>
22 #include "securec.h"
23 #include "debug_print.h"
24 #include "errcode.h"
25 #include "malloc.h"
26 
27 #ifdef _DEBUG_HEAP_MEM_MGR
28 #include "dbg_heap_memory.h"
29 #endif
30 
31 malloc_dfx_t g_st_dfx = { 0 };
32 malloc_funcs g_malloc_func = { 0 };
33 
34 /* malloc重新实现 */
35 
36 typedef enum malloc_type  {
37     EXT_NOTMALLOC = 0x7074,   /* empt */
38     EXT_HAVEMALLOC = 0x6C6C,  /* full */
39 } malloc_type_t;
40 
41 typedef uint16_t malloc_type_t_uint16;
42 
43 /* 可用空间总大小 */
44 #define ALIGN4 0x4
45 #define DOUBLE 2
46 
47 /* 数据格式: 大小、状态(是否已用)、可用空间 */
48 typedef struct malloc_state {
49     uintptr_t caller;
50     uint16_t size;
51     malloc_type_t_uint16 is_used;
52 } malloc_state_t;
53 
malloc_register_funcs(const malloc_funcs * funcs)54 uint32_t malloc_register_funcs(const malloc_funcs *funcs)
55 {
56     (void)memcpy_s((void*)(&g_malloc_func), sizeof(malloc_funcs), funcs, sizeof(malloc_funcs));
57     return ERRCODE_SUCC;
58 }
59 
malloc_get_funcs(void)60 malloc_funcs *malloc_get_funcs(void)
61 {
62     return &g_malloc_func;
63 }
64 
malloc_init(uintptr_t heap_start_addr,uintptr_t heap_end_addr)65 void malloc_init(uintptr_t heap_start_addr, uintptr_t heap_end_addr)
66 {
67     rom_malloc_init(heap_start_addr, heap_end_addr);
68 }
69 
malloc(size_t size)70 void *malloc(size_t size)
71 {
72     uint32_t caller = 0;
73 #ifdef __GNUC__
74     caller = (uint32_t)(uintptr_t)__builtin_return_address(0);
75 #endif
76     return rom_malloc(size, caller);
77 }
78 
free(void * addr)79 void free(void *addr)
80 {
81     rom_free(addr);
82 }
83 
84 /*
85 * malloc初始化,可用空间以4 字节对齐
86 * 注意:  本函数内不能增加打印,因其调用位置未进行串口初始化
87 */
rom_malloc_init(uint32_t heap_start_addr,uint32_t heap_end_addr)88 void rom_malloc_init(uint32_t heap_start_addr, uint32_t heap_end_addr)
89 {
90     uint32_t real_start_addr = 0;
91     malloc_dfx_t *st_dfx = NULL;
92 
93     malloc_state_t *mem_pos = NULL;
94 
95     memset_s((void*)(uintptr_t)heap_start_addr, sizeof(malloc_dfx_t), 0x0, sizeof(malloc_dfx_t));
96     st_dfx = &g_st_dfx;
97     real_start_addr = (uint32_t)(heap_start_addr + sizeof(malloc_dfx_t));
98 
99     /* 创建第一个内存池 */
100     st_dfx->heap_start_addr = ((unsigned int)(real_start_addr + (ALIGN4 - 1)) & (~(ALIGN4 - 1)));
101     st_dfx->heap_end_addr = (unsigned int)(heap_end_addr - DOUBLE * ALIGN4) & (~(ALIGN4 - 1));
102     mem_pos = (malloc_state_t *)st_dfx->heap_start_addr;
103     mem_pos->size = (uint16_t)(st_dfx->heap_end_addr - st_dfx->heap_start_addr - sizeof(malloc_state_t));
104     st_dfx->heap_size = mem_pos->size;
105     mem_pos->is_used = EXT_NOTMALLOC;
106     mem_pos->caller = 0x0;
107 }
108 
109 /*
110 * 刷新malloc 可分配空间,合并相邻已free 链表
111 */
mem_fresh(void)112 static void mem_fresh(void)
113 {
114     malloc_state_t *mem_pos = NULL;
115     malloc_state_t *next_pos = NULL;
116     malloc_dfx_t *st_dfx = &g_st_dfx;
117 
118     /* 头结点 */
119     mem_pos = (malloc_state_t *)st_dfx->heap_start_addr;
120     while ((uintptr_t)((char *)mem_pos + sizeof(malloc_state_t) + mem_pos->size) < st_dfx->heap_end_addr) {
121         /* 指向下一个区域 */
122         next_pos = (malloc_state_t *)((char *)mem_pos + sizeof(malloc_state_t) +
123                                               mem_pos->size);
124 
125         if ((mem_pos->is_used == EXT_NOTMALLOC) && (next_pos->is_used == EXT_NOTMALLOC)) {
126             mem_pos->size += (uint16_t)(sizeof(malloc_state_t) + next_pos->size);
127         } else {
128             mem_pos = next_pos;
129         }
130     }
131 }
132 
133 /*
134 * malloc 接口
135 */
rom_malloc(uint32_t size,uint32_t caller)136 void *rom_malloc(uint32_t size, uint32_t caller)
137 {
138     /* 首地址查询大于等于size且未用空间 */
139     malloc_state_t *mem_pos = NULL;
140     malloc_state_t *next_pos = NULL;
141     malloc_dfx_t *st_dfx = &g_st_dfx;
142     uint16_t align_size;
143     uint32_t count = 0;
144 
145     if ((st_dfx->heap_start_addr == 0) || (size == 0)) {
146         return NULL;
147     }
148     /* 头结点 */
149     mem_pos = (malloc_state_t *)st_dfx->heap_start_addr;
150     if ((mem_pos->is_used != EXT_NOTMALLOC) && (mem_pos->is_used != EXT_HAVEMALLOC)) {
151         return NULL;
152     }
153     /* 分配空间4 字节对齐 */
154     align_size = (size + (ALIGN4 - 1)) & (~(ALIGN4 - 1));
155 
156     for (;;) {
157         if (mem_pos->is_used == EXT_NOTMALLOC) {
158             /* 分配可用块的部分可用空间 */
159             if ((sizeof(malloc_state_t) + align_size) < (mem_pos->size)) {
160                 /* 剩余空间自动成为未用块,须大于sizeof(malloc_state_t) */
161                 next_pos = (malloc_state_t *)((char *)mem_pos + align_size +
162                                                       sizeof(malloc_state_t));
163 
164                 next_pos->size = (uint16_t)(mem_pos->size - align_size - sizeof(malloc_state_t));
165                 next_pos->is_used = EXT_NOTMALLOC;
166 
167                 mem_pos->size = align_size;
168                 mem_pos->is_used = EXT_HAVEMALLOC;
169                 mem_pos->caller = caller;
170 
171                 st_dfx->heap_malloc_size += mem_pos->size;
172                 return (void *)((char *) mem_pos + sizeof(malloc_state_t));
173             } else if ((align_size <= mem_pos->size) &&
174                      ((sizeof(malloc_state_t) + align_size) >= (mem_pos->size))) {
175                 /* 分配整块可用块 */
176                 mem_pos->is_used = EXT_HAVEMALLOC;
177                 mem_pos->caller = caller;
178                 st_dfx->heap_malloc_size += mem_pos->size;
179                 return (void *)((char *) mem_pos + sizeof(malloc_state_t));
180             }
181         }
182 
183         /* 当前块不可用,查找下一块 */
184         next_pos = (malloc_state_t *)((char *)mem_pos + sizeof(malloc_state_t) + mem_pos->size);
185         mem_pos = next_pos;
186 
187         /* 查询至总空间结尾,失败则合并已free空间再次查询 */
188         if ((uintptr_t)mem_pos >= st_dfx->heap_end_addr) {
189             if (count >= 1) {
190                 return NULL;
191             }
192 
193             mem_fresh();
194             mem_pos = (malloc_state_t *)st_dfx->heap_start_addr;
195             count++;
196         }
197         if ((mem_pos->is_used != EXT_HAVEMALLOC) && (mem_pos->is_used != EXT_NOTMALLOC)) {
198             return NULL;
199         }
200     }
201 }
202 
203 /*
204 * free 接口
205 */
rom_free(void * addr)206 uint32_t rom_free(void *addr)
207 {
208     /* 置链表状态为未用 */
209     malloc_state_t *mem_pos = NULL;
210     malloc_dfx_t *st_dfx = &g_st_dfx;
211 
212     if (addr == NULL) {
213         return ERRCODE_SUCC;
214     }
215 
216     mem_pos = (malloc_state_t *)((char *)addr - sizeof(malloc_state_t));
217     if (mem_pos->is_used != EXT_HAVEMALLOC) {
218         return ERRCODE_SUCC;
219     }
220     mem_pos->is_used = EXT_NOTMALLOC;
221     st_dfx->heap_free_size += mem_pos->size;
222 
223     return ERRCODE_SUCC;
224 }
225 
226 /*
227 * 测试代码
228 */
print_mem_info(void)229 void print_mem_info(void)
230 {
231     malloc_dfx_t *st_dfx = &g_st_dfx;
232     malloc_state_t *pos = (malloc_state_t *)st_dfx->heap_start_addr;
233 
234     PRINT("malloc start addr is 0x%x, end sddr is %d\r\n", st_dfx->heap_start_addr, st_dfx->heap_end_addr);
235     if ((void *)st_dfx->heap_start_addr == NULL) {
236         return;
237     }
238     PRINT("info:\r\n");
239     while ((void *)pos < (void *)st_dfx->heap_end_addr) {
240         /* 输出所有信息 */
241         PRINT("addr:0x%x    ", pos);
242 #if ATE_DEBUG
243         print_str("size:%d    ", pos->size);
244         print_str("is_used:%x    ", pos->is_used);
245         print_str("caller:0x%x\r\n", pos->caller);
246 #endif
247         pos = (malloc_state_t *)((char *)pos + pos->size + sizeof(malloc_state_t));
248     }
249     return;
250 }
251