AKOS  v1.0.0
Documentation
Loading...
Searching...
No Matches
memory.c
Go to the documentation of this file.
1/*
2*********************************************************************************************************
3 * MEMORY
4*
5 * File : memory.c
6* Version : none
7* Author : JiaHui
8*********************************************************************************************************
9*/
10
11// clang-format off
12
13/****************************************************************************/
24
25#include "config.h"
26#include "memory.h"
27#include "core.h"
28
29#define ALIGNMENT ((size_t)4U)
30#define MEM_ALIGN(size) (size_t)(((size) + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1))
31#define MIN_SIZE_TO_SPLIT ((size_t)8U)
32#define SIZE_OF_BLOCK_HEADER ((size_t)MEM_ALIGN(sizeof(mem_blk_header_t)))
33
34static uint8_t mem_heap[OS_CFG_HEAP_SIZE] __attribute__((aligned(ALIGNMENT)));
35static mem_blk_header_t mem_blk_start;
36static mem_blk_header_t *mem_blk_end_ptr = NULL;
37static uint32_t byte_available = 0;
38
42static void memory_heap_init(void)
43{
44 uint32_t total_heap_size = OS_CFG_HEAP_SIZE;
45 uint32_t heap_addr = (uint32_t)mem_heap;
46
47 /* Initialize first block */
48 mem_blk_end_ptr = (mem_blk_header_t *)(heap_addr);
49 mem_blk_end_ptr->size = total_heap_size - SIZE_OF_BLOCK_HEADER;
50 mem_blk_end_ptr->state = MEM_STATE_FREE;
51 mem_blk_end_ptr->next_ptr = NULL;
52
53 mem_blk_start.size = 0;
54 mem_blk_start.state = MEM_STATE_BUSY;
55 mem_blk_start.next_ptr = mem_blk_end_ptr;
56
57 byte_available = total_heap_size - SIZE_OF_BLOCK_HEADER;
58}
59
65void *akos_memory_malloc(size_t size)
66{
67 uint8_t *p_return = NULL;
68 mem_blk_header_t *p_block = &mem_blk_start;
69
70 AKOS_CORE_ENTER_CRITICAL();
71
72 /* Must check the end pointer first */
73 if (mem_blk_end_ptr == NULL)
74 {
75 memory_heap_init();
76 }
77
78 /* Then check the size */
79 size = MEM_ALIGN(size);
80 if ((size == 0) || (size > byte_available))
81 {
82 core_assert(0, "OS_ERR_MEM_INVALID_SIZE");
83 AKOS_CORE_EXIT_CRITICAL();
84 return (void *)p_return;
85 }
86
87 p_block = p_block->next_ptr;
88 while (p_block != mem_blk_end_ptr)
89 {
90 if ((p_block->size < size) || (p_block->state == MEM_STATE_BUSY))
91 {
92 p_block = p_block->next_ptr;
93 }
94 else
95 {
96 /* Exit loop */
97 break;
98 }
99 }
100
101
102 /* Ensure selected block is actually usable (FREE and large enough). */
103 if ((p_block->state == MEM_STATE_BUSY) || (p_block->size < size))
104 {
105 core_assert(0, "OS_ERR_MEM_NO_BLOCK");
106 AKOS_CORE_EXIT_CRITICAL();
107 return (void *)p_return;
108 }
109
110 if ((p_block->size - size) > (MIN_SIZE_TO_SPLIT + SIZE_OF_BLOCK_HEADER))
111 {
112 mem_blk_header_t *p_new_block = (mem_blk_header_t *)(((uint8_t *)p_block) + SIZE_OF_BLOCK_HEADER + size);
113 p_return = (uint8_t *)p_block + SIZE_OF_BLOCK_HEADER;
114 p_new_block->size = p_block->size - size - SIZE_OF_BLOCK_HEADER;
115 p_new_block->state = MEM_STATE_FREE;
116 p_new_block->next_ptr = p_block->next_ptr;
117
118 if (p_new_block->next_ptr == NULL)
119 {
120 mem_blk_end_ptr = p_new_block;
121 }
122
123 p_block->size = size;
124 p_block->state = MEM_STATE_BUSY;
125 p_block->next_ptr = p_new_block;
126 byte_available -= (size + SIZE_OF_BLOCK_HEADER);
127 }
128 else
129 {
130 p_return = ((uint8_t *)p_block + SIZE_OF_BLOCK_HEADER);
131 p_block->state = MEM_STATE_BUSY;
132 byte_available -= p_block->size;
133 }
134
135
136 AKOS_CORE_EXIT_CRITICAL();
137 return (void *)p_return;
138}
139
144void akos_memory_free(void *p_addr)
145{
146 AKOS_CORE_ENTER_CRITICAL();
147
148 if ((mem_blk_end_ptr == NULL))
149 {
150 core_assert(0, "OS_ERR_MEM_LIST_IS_EMPTY");
151 AKOS_CORE_EXIT_CRITICAL();
152 return;
153 }
154
155 if (p_addr == NULL)
156 {
157 core_assert(0, "OS_ERR_MEM_INVALID_ADDRESS");
158 AKOS_CORE_EXIT_CRITICAL();
159 return;
160 }
161
162 uint8_t is_above_heap_end =
163 ((uint8_t *)p_addr >= ((uint8_t *)mem_blk_end_ptr + SIZE_OF_BLOCK_HEADER + mem_blk_end_ptr->size));
164
165 uint8_t is_below_heap_start =
166 ((uint8_t *)p_addr < ((uint8_t *)mem_blk_start.next_ptr + SIZE_OF_BLOCK_HEADER));
167
168 if (is_above_heap_end || is_below_heap_start)
169 {
170 core_assert(0, "OS_ERR_MEM_INVALID_ADDRESS");
171 AKOS_CORE_EXIT_CRITICAL();
172 return;
173 }
174
175 mem_blk_header_t *p_block = (mem_blk_header_t *)((uint8_t *)p_addr - SIZE_OF_BLOCK_HEADER);
176 mem_blk_header_t *p_block_temp = &mem_blk_start;
177 mem_blk_header_t *p_prev_block = p_block_temp;
178
179 while ((p_block_temp != mem_blk_end_ptr) && (p_block_temp != p_block))
180 {
181 p_prev_block = p_block_temp;
182 p_block_temp = p_block_temp->next_ptr;
183 }
184
185 if (p_block_temp != p_block)
186 {
187 core_assert(0, "OS_ERR_MEM_INVALID_ADDRESS");
188 AKOS_CORE_EXIT_CRITICAL();
189 return;
190 }
191
192 if (p_block_temp->state == MEM_STATE_FREE)
193 {
194 core_assert(0, "OS_ERR_MEM_DOUBLE_FREE");
195 AKOS_CORE_EXIT_CRITICAL();
196 return;
197 }
198
199 byte_available += p_block_temp->size;
200 p_block_temp->state = MEM_STATE_FREE;
201
202 /* Merge next block */
203 if ((p_block_temp->next_ptr != NULL) && (p_block_temp->next_ptr->state == MEM_STATE_FREE))
204 {
205 byte_available += SIZE_OF_BLOCK_HEADER;
206 p_block_temp->size += p_block_temp->next_ptr->size + SIZE_OF_BLOCK_HEADER;
207 p_block_temp->next_ptr = p_block_temp->next_ptr->next_ptr;
208 if (p_block_temp->next_ptr == NULL)
209 {
210 mem_blk_end_ptr = p_block_temp;
211 }
212 }
213
214 /* Merge previous block */
215 if ((p_prev_block->state == MEM_STATE_FREE) && (p_prev_block != &mem_blk_start))
216 {
217 if (mem_blk_end_ptr == p_block_temp)
218 {
219 mem_blk_end_ptr = p_prev_block;
220 }
221
222 byte_available += SIZE_OF_BLOCK_HEADER;
223 p_prev_block->size += p_block_temp->size + SIZE_OF_BLOCK_HEADER;
224 p_prev_block->next_ptr = p_block_temp->next_ptr;
225 }
226
227 AKOS_CORE_EXIT_CRITICAL();
228}
Build-time configuration macros for AK-mOS.
#define OS_CFG_HEAP_SIZE
Definition config.h:25
Kernel control and critical-section API.
void akos_memory_free(void *p_addr)
Free previously allocated heap block.
Definition memory.c:144
void * akos_memory_malloc(size_t size)
Allocate block from heap.
Definition memory.c:65
Static-heap allocator APIs.