Line | Branch | Exec | Source |
---|---|---|---|
1 | /* GATE PROJECT LICENSE: | ||
2 | +----------------------------------------------------------------------------+ | ||
3 | | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> | | ||
4 | | All rights reserved. | | ||
5 | | | | ||
6 | | Redistribution and use in source and binary forms, with or without | | ||
7 | | modification, are permitted provided that the following conditions are met:| | ||
8 | | | | ||
9 | | 1. Redistributions of source code must retain the above copyright notice, | | ||
10 | | this list of conditions and the following disclaimer. | | ||
11 | | 2. Redistributions in binary form must reproduce the above copyright | | ||
12 | | notice, this list of conditions and the following disclaimer in the | | ||
13 | | documentation and/or other materials provided with the distribution. | | ||
14 | | | | ||
15 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| | ||
16 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | ||
17 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | ||
18 | | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | | ||
19 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | ||
20 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | ||
21 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | ||
22 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | ||
23 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | ||
24 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | ||
25 | | THE POSSIBILITY OF SUCH DAMAGE. | | ||
26 | +----------------------------------------------------------------------------+ | ||
27 | */ | ||
28 | |||
29 | #include "gate/memalloc.h" | ||
30 | #include "gate/gatetypes.h" | ||
31 | #include "gate/debugging.h" | ||
32 | #include "gate/results.h" | ||
33 | |||
34 | #if defined(GATE_SYS_EFI) | ||
35 | # define GATE_MEMALLOC_ALLOC_STD_IMPL | ||
36 | # define GATE_MEMALLOC_ACCESS_INTERNAL_IMPL | ||
37 | #else | ||
38 | # define GATE_MEMALLOC_ALLOC_STD_IMPL | ||
39 | # define GATE_MEMALLOC_ACCESS_STD_IMPL | ||
40 | #endif | ||
41 | |||
42 | |||
43 | #if defined(GATE_MEMALLOC_ALLOC_STD_IMPL) | ||
44 | |||
45 | /* memory allocation C standard implementation */ | ||
46 | |||
47 | #include <stdlib.h> | ||
48 | #include <string.h> | ||
49 | |||
50 | 67919 | void* gate_mem_alloc(gate_size_t sz) | |
51 | { | ||
52 | 67919 | GATE_DEBUG_ASSERT(sz != 0); | |
53 | 67919 | return malloc(sz); | |
54 | } | ||
55 | 2486 | void* gate_mem_realloc(void* ptr, gate_size_t newsize) | |
56 | { | ||
57 | 2486 | GATE_DEBUG_ASSERT(newsize != 0); | |
58 | 2486 | return realloc(ptr, newsize); | |
59 | } | ||
60 | 68433 | void gate_mem_dealloc(void* ptr) | |
61 | { | ||
62 | 68433 | GATE_DEBUG_ASSERT(ptr != NULL); | |
63 | 68433 | free(ptr); | |
64 | 68433 | } | |
65 | |||
66 | #endif /* GATE_MEMALLOC_ALLOC_STD_IMPL */ | ||
67 | |||
68 | |||
69 | |||
70 | |||
71 | |||
72 | #if defined(GATE_MEMALLOC_ACCESS_STD_IMPL) | ||
73 | |||
74 | /* memory access C standard implementation */ | ||
75 | |||
76 | #include <stdlib.h> | ||
77 | #include <string.h> | ||
78 | |||
79 | 228094 | void* gate_mem_copy(void* dst, void const* src, gate_size_t sz) | |
80 | { | ||
81 |
3/6✓ Branch 0 taken 228094 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 228094 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 228094 times.
✗ Branch 5 not taken.
|
228094 | GATE_DEBUG_ASSERT((dst != NULL) && (src != NULL) && (sz != 0)); |
82 | 228094 | return memcpy(dst, src, sz); | |
83 | } | ||
84 | |||
85 | 239 | void* gate_mem_move(void* dst, void const* src, gate_size_t sz) | |
86 | { | ||
87 |
3/6✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 239 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 239 times.
✗ Branch 5 not taken.
|
239 | GATE_DEBUG_ASSERT((dst != NULL) && (src != NULL) && (sz != 0)); |
88 | 239 | return memmove(dst, src, sz); | |
89 | } | ||
90 | |||
91 | 18900 | void gate_mem_clear(void* dst, gate_size_t sz) | |
92 | { | ||
93 | 18900 | memset(dst, 0, sz); | |
94 | 18900 | } | |
95 | |||
96 | 14 | void gate_mem_fill(void* dst, char chr, gate_size_t count) | |
97 | { | ||
98 | 14 | memset(dst, (unsigned char)chr, count); | |
99 | 14 | } | |
100 | |||
101 | 6105 | int gate_mem_compare(void const* ptr1, void const* ptr2, gate_size_t sz) | |
102 | { | ||
103 | 6105 | return (int)memcmp(ptr1, ptr2, sz); | |
104 | } | ||
105 | |||
106 | #endif /* GATE_MEMALLOC_MOVE_STD_IMPL */ | ||
107 | |||
108 | |||
109 | #if defined(GATE_MEMALLOC_ACCESS_INTERNAL_IMPL) | ||
110 | |||
111 | /* internal direct byte access implementation */ | ||
112 | |||
113 | void* gate_mem_copy(void* dst, void const* src, gate_size_t sz) | ||
114 | { | ||
115 | char* ptr_dst = (char*)dst; | ||
116 | char const* ptr_src = (char const*)src; | ||
117 | GATE_DEBUG_ASSERT((dst != NULL) && (src != NULL) && (sz != 0)); | ||
118 | |||
119 | while (sz-- != 0) | ||
120 | { | ||
121 | *ptr_dst = *ptr_src; | ||
122 | ++ptr_dst; | ||
123 | ++ptr_src; | ||
124 | } | ||
125 | return dst; | ||
126 | } | ||
127 | |||
128 | void* gate_mem_move(void* dst, void const* src, gate_size_t sz) | ||
129 | { | ||
130 | char* ptr_dst = (char*)dst; | ||
131 | char const* ptr_src = (char const*)src; | ||
132 | GATE_DEBUG_ASSERT((dst != NULL) && (src != NULL) && (sz != 0)); | ||
133 | |||
134 | if ((ptr_dst <= ptr_src) || (ptr_src + sz < ptr_dst)) | ||
135 | { | ||
136 | return gate_mem_copy(dst, src, sz); | ||
137 | } | ||
138 | else | ||
139 | { | ||
140 | ptr_dst += sz; | ||
141 | ptr_src += sz; | ||
142 | while (sz-- != 0) | ||
143 | { | ||
144 | --ptr_dst; | ||
145 | --ptr_src; | ||
146 | *ptr_dst = *ptr_src; | ||
147 | } | ||
148 | return dst; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | void gate_mem_clear(void* dst, gate_size_t count) | ||
153 | { | ||
154 | gate_mem_fill(dst, 0, count); | ||
155 | } | ||
156 | |||
157 | void gate_mem_fill(void* dst, char chr, gate_size_t count) | ||
158 | { | ||
159 | char* ptr = (char*)dst; | ||
160 | while (count-- != 0) | ||
161 | { | ||
162 | *ptr = chr; | ||
163 | ++ptr; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | |||
168 | int gate_mem_compare(void const* ptr1, void const* ptr2, gate_size_t sz) | ||
169 | { | ||
170 | unsigned char const* p1 = (unsigned char const*)ptr1; | ||
171 | unsigned char const* p2 = (unsigned char const*)ptr2; | ||
172 | while (sz-- != 0) | ||
173 | { | ||
174 | if (*p1 < *p2) | ||
175 | { | ||
176 | return -1; | ||
177 | } | ||
178 | if (*p1 > *p2) | ||
179 | { | ||
180 | return 1; | ||
181 | } | ||
182 | ++p1; | ||
183 | ++p2; | ||
184 | } | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | #endif /* GATE_MEMALLOC_ACCESS_INTERNAL_IMPL */ | ||
189 | |||
190 | |||
191 | |||
192 | |||
193 | |||
194 | |||
195 | /*************************** | ||
196 | * Generic implementations * | ||
197 | ***************************/ | ||
198 | |||
199 | 129209 | gate_size_t gate_mem_align_size(gate_size_t sz) | |
200 | { | ||
201 | 129209 | gate_size_t m = sz % sizeof(gate_c_maxalign_t); | |
202 |
2/2✓ Branch 0 taken 128016 times.
✓ Branch 1 taken 1193 times.
|
129209 | if (m != 0) |
203 | { | ||
204 | 128016 | sz += (sizeof(gate_c_maxalign_t) - m); | |
205 | } | ||
206 | 129209 | return sz; | |
207 | } | ||
208 | 3 | void gate_mem_reversebyteorder(void* ptr, gate_size_t sz) | |
209 | { | ||
210 | 3 | gate_size_t cnt = sz / 2; | |
211 | 3 | char* ptr1 = (char*)ptr; | |
212 | 3 | char* ptr2 = ptr1 + sz - 1; | |
213 | char tmp; | ||
214 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
|
11 | while (cnt-- != 0) |
215 | { | ||
216 | 8 | tmp = *ptr1; | |
217 | 8 | *ptr1 = *ptr2; | |
218 | 8 | *ptr2 = tmp; | |
219 | 8 | ++ptr1; | |
220 | 8 | --ptr2; | |
221 | } | ||
222 | 3 | } | |
223 | 3 | void* gate_mem_copy_reverse(void* dst, void const* src, gate_size_t sz) | |
224 | { | ||
225 | 3 | char* ptrdst = (char*)dst; | |
226 | 3 | char const* ptrsrc = (char const*)src + sz; | |
227 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 3 times.
|
19 | while (sz-- != 0) |
228 | { | ||
229 | 16 | --ptrsrc; | |
230 | 16 | *ptrdst = *ptrsrc; | |
231 | 16 | ++ptrdst; | |
232 | } | ||
233 | 3 | return dst; | |
234 | } | ||
235 | |||
236 | 4508 | gate_result_t gate_mem_copy_construct(void* dest_item, void const* src_item, gate_size_t item_size, gate_mem_copyctor_t ctor) | |
237 | { | ||
238 |
2/2✓ Branch 0 taken 221 times.
✓ Branch 1 taken 4287 times.
|
4508 | if (ctor == NULL) |
239 | { | ||
240 | 221 | gate_mem_copy(dest_item, src_item, item_size); | |
241 | 221 | return GATE_RESULT_OK; | |
242 | } | ||
243 | else | ||
244 | { | ||
245 | 4287 | return ctor(dest_item, src_item); | |
246 | } | ||
247 | } | ||
248 | |||
249 | 2852 | void gate_mem_destruct(void* dest_item, gate_mem_dtor_t dtor) | |
250 | { | ||
251 |
2/2✓ Branch 0 taken 2641 times.
✓ Branch 1 taken 211 times.
|
2852 | if (dtor != NULL) |
252 | { | ||
253 | 2641 | dtor(dest_item); | |
254 | } | ||
255 | 2852 | } | |
256 | 26 | gate_result_t gate_mem_move_construct(void* dest_item, void* src_item, gate_size_t item_size, gate_mem_copyctor_t ctor, gate_mem_dtor_t dtor) | |
257 | { | ||
258 | gate_result_t result; | ||
259 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 4 times.
|
26 | if (dest_item == src_item) |
260 | { | ||
261 | 22 | return GATE_RESULT_OK; | |
262 | } | ||
263 | 4 | result = gate_mem_copy_construct(dest_item, src_item, item_size, ctor); | |
264 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (GATE_SUCCEEDED(result)) |
265 | { | ||
266 | 4 | gate_mem_destruct(src_item, dtor); | |
267 | } | ||
268 | 4 | return result; | |
269 | } | ||
270 | |||
271 | |||
272 | 61 | gate_bool_t gate_mem_swap(void* item1, void* item2, gate_size_t item_size, gate_mem_copyctor_t copy_constructor, gate_mem_dtor_t destructor) | |
273 | { | ||
274 | gate_result_t result; | ||
275 | 61 | gate_bool_t ret = false; | |
276 | char buffer[GATE_MAX_COPYBUFFER_LENGTH]; | ||
277 | 61 | char* ptr_buffer = &buffer[0]; | |
278 | |||
279 | do | ||
280 | { | ||
281 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | if (item1 == item2) |
282 | { | ||
283 | /* pointers are equal -> nothing to swap */ | ||
284 | ✗ | ret = true; | |
285 | ✗ | break; | |
286 | } | ||
287 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | if (item_size > sizeof(buffer)) |
288 | { | ||
289 | ✗ | ptr_buffer = gate_mem_alloc(item_size); | |
290 | ✗ | if (ptr_buffer == NULL) | |
291 | { | ||
292 | ✗ | ptr_buffer = &buffer[0]; | |
293 | ✗ | break; | |
294 | } | ||
295 | } | ||
296 | |||
297 | 61 | result = gate_mem_copy_construct(ptr_buffer, item1, item_size, copy_constructor); | |
298 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | GATE_BREAK_IF_FAILED(result); |
299 | |||
300 | 61 | gate_mem_destruct(item1, destructor); | |
301 | 61 | result = gate_mem_copy_construct(item1, item2, item_size, copy_constructor); | |
302 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | if (GATE_FAILED(result)) |
303 | { | ||
304 | ✗ | gate_mem_copy_construct(item1, ptr_buffer, item_size, copy_constructor); | |
305 | ✗ | gate_mem_destruct(ptr_buffer, destructor); | |
306 | ✗ | break; | |
307 | } | ||
308 | |||
309 | 61 | gate_mem_destruct(item2, destructor); | |
310 | 61 | result = gate_mem_copy_construct(item2, ptr_buffer, item_size, copy_constructor); | |
311 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | if (GATE_FAILED(result)) |
312 | { | ||
313 | ✗ | gate_mem_copy_construct(item2, item1, item_size, copy_constructor); | |
314 | ✗ | gate_mem_destruct(item1, destructor); | |
315 | ✗ | gate_mem_copy_construct(item1, ptr_buffer, item_size, copy_constructor); | |
316 | ✗ | gate_mem_destruct(ptr_buffer, destructor); | |
317 | ✗ | break; | |
318 | } | ||
319 | |||
320 | 61 | gate_mem_destruct(ptr_buffer, destructor); | |
321 | 61 | ret = true; | |
322 | } while (0); | ||
323 | |||
324 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | if (ptr_buffer != &buffer[0]) |
325 | { | ||
326 | ✗ | gate_mem_dealloc(ptr_buffer); | |
327 | } | ||
328 | 61 | return ret; | |
329 | } | ||
330 | |||
331 | 2 | static gate_bool_t is_pointer_aligned(void const* ptr) | |
332 | { | ||
333 | 2 | const gate_uintptr_t addr = (gate_uintptr_t)ptr; | |
334 | 2 | return (addr % sizeof(void*) == 0); | |
335 | } | ||
336 | |||
337 | 1 | void gate_mem_swap_bytes(void* mem1, void* mem2, gate_size_t length) | |
338 | { | ||
339 | 1 | gate_size_t bytelen = length % sizeof(void*); | |
340 | gate_uint8_t* b1; | ||
341 | gate_uint8_t* b2; | ||
342 | |||
343 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | if (is_pointer_aligned(mem1) && is_pointer_aligned(mem2)) |
344 | { | ||
345 | /* faster transfer using aligned pointer-swap */ | ||
346 | 1 | void** v1 = (void**)mem1; | |
347 | 1 | void** v2 = (void**)mem2; | |
348 | 1 | gate_size_t reglen = length / sizeof(void*); | |
349 | 1 | const gate_size_t skiplen = reglen * sizeof(void*); | |
350 | |||
351 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
|
6 | for (; reglen != 0; --reglen, ++v1, ++v2) |
352 | { | ||
353 | 5 | void* const tmp = *v1; | |
354 | 5 | *v1 = *v2; | |
355 | 5 | *v2 = tmp; | |
356 | } | ||
357 | |||
358 | 1 | length -= skiplen; | |
359 | 1 | mem1 = (void*)((char*)mem1 + skiplen); | |
360 | 1 | mem2 = (void*)((char*)mem2 + skiplen); | |
361 | } | ||
362 | |||
363 | 1 | b1 = (gate_uint8_t*)mem1; | |
364 | 1 | b2 = (gate_uint8_t*)mem2; | |
365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | for (; bytelen != 0; --bytelen, ++b1, ++b2) |
366 | { | ||
367 | ✗ | const gate_uint8_t tmp = *b1; | |
368 | ✗ | *b1 = *b2; | |
369 | ✗ | *b2 = tmp; | |
370 | } | ||
371 | 1 | } | |
372 |