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 /* Must check the end pointer first */
71 if (mem_blk_end_ptr == NULL)
72 {
73 memory_heap_init();
74 }
75
76 /* Then check the size */
77 size = MEM_ALIGN(size);
78 if ((size == 0) || (size > byte_available))
79 {
80 core_assert(0, "OS_ERR_MEM_INVALID_SIZE");
81 return (void *)p_return;
82 }
83
84 p_block = p_block->next_ptr;
85 while (p_block != mem_blk_end_ptr)
86 {
87 if ((p_block->size < size) || (p_block->state == MEM_STATE_BUSY))
88 {
89 p_block = p_block->next_ptr;
90 }
91 else
92 {
93 /* Exit loop */
94 break;
95 }
96 }
97
98
99 /* Ensure selected block is actually usable (FREE and large enough). */
100 if ((p_block->state == MEM_STATE_BUSY) || (p_block->size < size))
101 {
102 core_assert(0, "OS_ERR_MEM_NO_BLOCK");
103 return (void *)p_return;
104 }
105
106 if ((p_block->size - size) > (MIN_SIZE_TO_SPLIT + SIZE_OF_BLOCK_HEADER))
107 {
108 mem_blk_header_t *p_new_block = (mem_blk_header_t *)(((uint8_t *)p_block) + SIZE_OF_BLOCK_HEADER + size);
109 p_return = (uint8_t *)p_block + SIZE_OF_BLOCK_HEADER;
110 p_new_block->size = p_block->size - size - SIZE_OF_BLOCK_HEADER;
111 p_new_block->state = MEM_STATE_FREE;
112 p_new_block->next_ptr = p_block->next_ptr;
113
114 if (p_new_block->next_ptr == NULL)
115 {
116 mem_blk_end_ptr = p_new_block;
117 }
118
119 p_block->size = size;
120 p_block->state = MEM_STATE_BUSY;
121 p_block->next_ptr = p_new_block;
122 byte_available -= (size + SIZE_OF_BLOCK_HEADER);
123 }
124 else
125 {
126 p_return = ((uint8_t *)p_block + SIZE_OF_BLOCK_HEADER);
127 p_block->state = MEM_STATE_BUSY;
128 byte_available -= p_block->size;
129 }
130
131
132 return (void *)p_return;
133}
134
139void akos_memory_free(void *p_addr)
140{
141 if ((mem_blk_end_ptr == NULL))
142 {
143 core_assert(0, "OS_ERR_MEM_LIST_IS_EMPTY");
144 return;
145 }
146
147 if (p_addr == NULL)
148 {
149 core_assert(0, "OS_ERR_MEM_INVALID_ADDRESS");
150 return;
151 }
152
153 uint8_t is_above_heap_end =
154 ((uint8_t *)p_addr >= ((uint8_t *)mem_blk_end_ptr + SIZE_OF_BLOCK_HEADER + mem_blk_end_ptr->size));
155
156 uint8_t is_below_heap_start =
157 ((uint8_t *)p_addr < ((uint8_t *)mem_blk_start.next_ptr + SIZE_OF_BLOCK_HEADER));
158
159 if (is_above_heap_end || is_below_heap_start)
160 {
161 core_assert(0, "OS_ERR_MEM_INVALID_ADDRESS");
162 return;
163 }
164
165 mem_blk_header_t *p_block = (mem_blk_header_t *)((uint8_t *)p_addr - SIZE_OF_BLOCK_HEADER);
166 mem_blk_header_t *p_block_temp = &mem_blk_start;
167 mem_blk_header_t *p_prev_block = p_block_temp;
168
169 while ((p_block_temp != mem_blk_end_ptr) && (p_block_temp != p_block))
170 {
171 p_prev_block = p_block_temp;
172 p_block_temp = p_block_temp->next_ptr;
173 }
174
175 if (p_block_temp != p_block)
176 {
177 core_assert(0, "OS_ERR_MEM_INVALID_ADDRESS");
178 return;
179 }
180
181 if (p_block_temp->state == MEM_STATE_FREE)
182 {
183 core_assert(0, "OS_ERR_MEM_DOUBLE_FREE");
184 return;
185 }
186
187 byte_available += p_block_temp->size;
188 p_block_temp->state = MEM_STATE_FREE;
189
190 /* Merge next block */
191 if ((p_block_temp->next_ptr != NULL) && (p_block_temp->next_ptr->state == MEM_STATE_FREE))
192 {
193 byte_available += SIZE_OF_BLOCK_HEADER;
194 p_block_temp->size += p_block_temp->next_ptr->size + SIZE_OF_BLOCK_HEADER;
195 p_block_temp->next_ptr = p_block_temp->next_ptr->next_ptr;
196 if (p_block_temp->next_ptr == NULL)
197 {
198 mem_blk_end_ptr = p_block_temp;
199 }
200 }
201
202 /* Merge previous block */
203 if ((p_prev_block->state == MEM_STATE_FREE) && (p_prev_block != &mem_blk_start))
204 {
205 if (mem_blk_end_ptr == p_block_temp)
206 {
207 mem_blk_end_ptr = p_prev_block;
208 }
209
210 byte_available += SIZE_OF_BLOCK_HEADER;
211 p_prev_block->size += p_block_temp->size + SIZE_OF_BLOCK_HEADER;
212 p_prev_block->next_ptr = p_block_temp->next_ptr;
213 }
214}
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:139
void * akos_memory_malloc(size_t size)
Allocate block from heap.
Definition memory.c:65
Static-heap allocator APIs.