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