Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | Copyright 2020 - 2024 Joel Svensson svenssonjoel@yahoo.se | ||
3 | 2024 Benjamin Vedder | ||
4 | |||
5 | This program is free software: you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation, either version 3 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <stdint.h> | ||
20 | #include <stdlib.h> | ||
21 | #include <stdio.h> | ||
22 | |||
23 | #include "lbm_memory.h" | ||
24 | #include "platform_mutex.h" | ||
25 | |||
26 | // pull in from eval_cps | ||
27 | void lbm_request_gc(void); | ||
28 | |||
29 | /* Status bit patterns */ | ||
30 | #define FREE_OR_USED 0 //00b | ||
31 | #define END 1 //01b | ||
32 | #define START 2 //10b | ||
33 | #define START_END 3 //11b | ||
34 | |||
35 | /* States in memory_allocate state-machine*/ | ||
36 | #define INIT 0 | ||
37 | #define FREE_LENGTH_CHECK 1 | ||
38 | #define SKIP 2 | ||
39 | #define ALLOC_DONE 0xF00DF00D | ||
40 | #define ALLOC_FAILED 0xDEADBEAF | ||
41 | |||
42 | static lbm_uint *bitmap = NULL; | ||
43 | static lbm_uint *memory = NULL; | ||
44 | static lbm_uint memory_size; // in 4 or 8 byte words depending on 32 or 64 bit platform | ||
45 | static lbm_uint bitmap_size; // in 4 or 8 byte words | ||
46 | static lbm_uint memory_base_address = 0; | ||
47 | static lbm_uint memory_num_free = 0; | ||
48 | static volatile lbm_uint memory_reserve_level = 0; | ||
49 | static mutex_t lbm_mem_mutex; | ||
50 | static bool lbm_mem_mutex_initialized; | ||
51 | static lbm_uint alloc_offset = 0; | ||
52 | |||
53 | 43008 | int lbm_memory_init(lbm_uint *data, lbm_uint data_size, | |
54 | lbm_uint *bits, lbm_uint bits_size) { | ||
55 | |||
56 |
2/2✓ Branch 0 taken 21504 times.
✓ Branch 1 taken 21504 times.
|
43008 | if (!lbm_mem_mutex_initialized) { |
57 | 21504 | mutex_init(&lbm_mem_mutex); | |
58 | 21504 | lbm_mem_mutex_initialized = true; | |
59 | } | ||
60 | |||
61 | 43008 | alloc_offset = 0; | |
62 | |||
63 | 43008 | mutex_lock(&lbm_mem_mutex); | |
64 | 43008 | int res = 0; | |
65 |
2/4✓ Branch 0 taken 43008 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 43008 times.
|
43008 | if (data == NULL || bits == NULL) return 0; |
66 | |||
67 |
1/2✓ Branch 0 taken 43008 times.
✗ Branch 1 not taken.
|
43008 | if (((lbm_uint)data % sizeof(lbm_uint) != 0) || |
68 |
1/2✓ Branch 0 taken 43008 times.
✗ Branch 1 not taken.
|
43008 | (data_size * 2) != (bits_size * sizeof(lbm_uint) * 8) || |
69 |
1/2✓ Branch 0 taken 43008 times.
✗ Branch 1 not taken.
|
43008 | data_size % 4 != 0 || |
70 |
2/4✓ Branch 0 taken 43008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43008 times.
✗ Branch 3 not taken.
|
43008 | ((lbm_uint)bits % sizeof(lbm_uint) != 0) || |
71 | 43008 | bits_size < 1 || | |
72 |
1/2✓ Branch 0 taken 43008 times.
✗ Branch 1 not taken.
|
43008 | bits_size % 4 != 0) { |
73 | // data is not aligned to sizeof lbm_uint | ||
74 | // size is too small | ||
75 | // or size is not a multiple of 4 | ||
76 | } else { | ||
77 | |||
78 | 43008 | bitmap = bits; | |
79 | 43008 | bitmap_size = bits_size; | |
80 | |||
81 |
2/2✓ Branch 0 taken 11010048 times.
✓ Branch 1 taken 43008 times.
|
11053056 | for (lbm_uint i = 0; i < bitmap_size; i ++) { |
82 | 11010048 | bitmap[i] = 0; | |
83 | } | ||
84 | |||
85 | 43008 | memory = data; | |
86 | 43008 | memory_base_address = (lbm_uint)data; | |
87 | 43008 | memory_size = data_size; | |
88 | 43008 | memory_num_free = data_size; | |
89 | 43008 | memory_reserve_level = (lbm_uint)(0.1 * (lbm_float)data_size); | |
90 | 43008 | res = 1; | |
91 | } | ||
92 | 43008 | mutex_unlock(&lbm_mem_mutex); | |
93 | 43008 | return res; | |
94 | } | ||
95 | |||
96 | ✗ | void lbm_memory_set_reserve(lbm_uint num_words) { | |
97 | ✗ | memory_reserve_level = num_words; | |
98 | ✗ | } | |
99 | |||
100 | ✗ | lbm_uint lbm_memory_get_reserve(void) { | |
101 | ✗ | return memory_reserve_level; | |
102 | } | ||
103 | |||
104 | 9676966 | static inline lbm_uint address_to_bitmap_ix(lbm_uint *ptr) { | |
105 | #ifndef LBM64 | ||
106 | 9676966 | return ((lbm_uint)ptr - memory_base_address) >> 2; | |
107 | #else | ||
108 | return ((lbm_uint)ptr - memory_base_address) >> 3; | ||
109 | #endif | ||
110 | } | ||
111 | |||
112 | 22540 | lbm_int lbm_memory_address_to_ix(lbm_uint *ptr) { | |
113 | /* TODO: assuming that index | ||
114 | will have more then enough room in the | ||
115 | positive half of a 28bit integer */ | ||
116 | 22540 | return (lbm_int)address_to_bitmap_ix(ptr); | |
117 | } | ||
118 | |||
119 | |||
120 | 10394155 | static inline lbm_uint *bitmap_ix_to_address(lbm_uint ix) { | |
121 | 10394155 | return &((lbm_uint*)(memory_base_address))[ix];// + (ix << 2)); | |
122 | } | ||
123 | |||
124 | #ifndef LBM64 | ||
125 | #define WORD_IX_SHIFT 5 | ||
126 | #define WORD_MOD_MASK 0x1F | ||
127 | #define BITMAP_SIZE_SHIFT 4 // 16 statuses per bitmap word | ||
128 | #else | ||
129 | #define WORD_IX_SHIFT 6 // divide by 64 | ||
130 | #define WORD_MOD_MASK 0x3F // mod 64 | ||
131 | #define BITMAP_SIZE_SHIFT 5 // times 32, 32 statuses per bitmap word | ||
132 | #endif | ||
133 | |||
134 | 459317070 | static inline lbm_uint status(lbm_uint i) { | |
135 | |||
136 | 459317070 | lbm_uint ix = i << 1; // * 2 | |
137 | 459317070 | lbm_uint word_ix = ix >> WORD_IX_SHIFT; // / 32 | |
138 | 459317070 | lbm_uint bit_ix = ix & WORD_MOD_MASK; // % 32 | |
139 | |||
140 | 459317070 | lbm_uint mask = ((lbm_uint)3) << bit_ix; // 000110..0 | |
141 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 459317070 times.
|
459317070 | if (word_ix > bitmap_size) { |
142 | ✗ | return (lbm_uint)NULL; | |
143 | } | ||
144 | 459317070 | return (bitmap[word_ix] & mask) >> bit_ix; | |
145 | } | ||
146 | |||
147 | 39955956 | static inline void set_status(lbm_uint i, lbm_uint status) { | |
148 | 39955956 | lbm_uint ix = i << 1; // * 2 | |
149 | 39955956 | lbm_uint word_ix = ix >> WORD_IX_SHIFT; // / 32 | |
150 | 39955956 | lbm_uint bit_ix = ix & WORD_MOD_MASK; // % 32 | |
151 | |||
152 | 39955956 | lbm_uint clr_mask = ~(((lbm_uint)3) << bit_ix); | |
153 | 39955956 | lbm_uint mask = status << bit_ix; | |
154 | |||
155 | 39955956 | bitmap[word_ix] &= clr_mask; | |
156 | 39955956 | bitmap[word_ix] |= mask; | |
157 | 39955956 | } | |
158 | |||
159 | 28 | lbm_uint lbm_memory_num_words(void) { | |
160 | 28 | return memory_size; | |
161 | } | ||
162 | |||
163 | 44072 | lbm_uint lbm_memory_num_free(void) { | |
164 |
2/4✓ Branch 0 taken 44072 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 44072 times.
|
44072 | if (memory == NULL || bitmap == NULL) { |
165 | ✗ | return 0; | |
166 | } | ||
167 | 44072 | mutex_lock(&lbm_mem_mutex); | |
168 | 44072 | unsigned int state = INIT; | |
169 | 44072 | lbm_uint sum_length = 0; | |
170 | |||
171 |
2/2✓ Branch 0 taken 180518912 times.
✓ Branch 1 taken 44072 times.
|
180562984 | for (unsigned int i = 0; i < (bitmap_size << BITMAP_SIZE_SHIFT); i ++) { |
172 | |||
173 |
4/5✓ Branch 1 taken 178375400 times.
✓ Branch 2 taken 1071448 times.
✓ Branch 3 taken 1071448 times.
✓ Branch 4 taken 616 times.
✗ Branch 5 not taken.
|
180518912 | switch(status(i)) { |
174 |
3/4✓ Branch 0 taken 45248 times.
✓ Branch 1 taken 158216520 times.
✓ Branch 2 taken 20113632 times.
✗ Branch 3 not taken.
|
178375400 | case FREE_OR_USED: |
175 | switch (state) { | ||
176 | 45248 | case INIT: | |
177 | 45248 | state = FREE_LENGTH_CHECK; | |
178 | 45248 | sum_length ++; | |
179 | 45248 | break; | |
180 | 158216520 | case FREE_LENGTH_CHECK: | |
181 | 158216520 | sum_length ++; | |
182 | 158216520 | state = FREE_LENGTH_CHECK; | |
183 | 158216520 | break; | |
184 | 20113632 | case SKIP: | |
185 | 20113632 | break; | |
186 | } | ||
187 | 178375400 | break; | |
188 | 1071448 | case END: | |
189 | 1071448 | state = INIT; | |
190 | 1071448 | break; | |
191 | 1071448 | case START: | |
192 | 1071448 | state = SKIP; | |
193 | 1071448 | break; | |
194 | 616 | case START_END: | |
195 | 616 | state = INIT; | |
196 | 616 | break; | |
197 | ✗ | default: | |
198 | ✗ | mutex_unlock(&lbm_mem_mutex); | |
199 | ✗ | return 0; | |
200 | break; | ||
201 | } | ||
202 | } | ||
203 | 44072 | mutex_unlock(&lbm_mem_mutex); | |
204 | 44072 | return sum_length; | |
205 | } | ||
206 | |||
207 | 3360 | lbm_uint lbm_memory_longest_free(void) { | |
208 |
2/4✓ Branch 0 taken 3360 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3360 times.
|
3360 | if (memory == NULL || bitmap == NULL) { |
209 | ✗ | return 0; | |
210 | } | ||
211 | 3360 | mutex_lock(&lbm_mem_mutex); | |
212 | 3360 | unsigned int state = INIT; | |
213 | 3360 | lbm_uint max_length = 0; | |
214 | |||
215 | 3360 | lbm_uint curr_length = 0; | |
216 |
2/2✓ Branch 0 taken 13762560 times.
✓ Branch 1 taken 3360 times.
|
13765920 | for (unsigned int i = 0; i < (bitmap_size << BITMAP_SIZE_SHIFT); i ++) { |
217 | |||
218 |
4/5✓ Branch 1 taken 13477520 times.
✓ Branch 2 taken 140504 times.
✓ Branch 3 taken 140504 times.
✓ Branch 4 taken 4032 times.
✗ Branch 5 not taken.
|
13762560 | switch(status(i)) { |
219 |
3/4✓ Branch 0 taken 3808 times.
✓ Branch 1 taken 10138828 times.
✓ Branch 2 taken 3334884 times.
✗ Branch 3 not taken.
|
13477520 | case FREE_OR_USED: |
220 | switch (state) { | ||
221 | 3808 | case INIT: | |
222 | 3808 | curr_length = 1; | |
223 |
2/2✓ Branch 0 taken 3360 times.
✓ Branch 1 taken 448 times.
|
3808 | if (curr_length > max_length) max_length = curr_length; |
224 | 3808 | state = FREE_LENGTH_CHECK; | |
225 | 3808 | break; | |
226 | 10138828 | case FREE_LENGTH_CHECK: | |
227 | 10138828 | curr_length ++; | |
228 |
2/2✓ Branch 0 taken 10114090 times.
✓ Branch 1 taken 24738 times.
|
10138828 | if (curr_length > max_length) max_length = curr_length; |
229 | 10138828 | state = FREE_LENGTH_CHECK; | |
230 | 10138828 | break; | |
231 | 3334884 | case SKIP: | |
232 | 3334884 | break; | |
233 | } | ||
234 | 13477520 | break; | |
235 | 140504 | case END: | |
236 | 140504 | state = INIT; | |
237 | 140504 | break; | |
238 | 140504 | case START: | |
239 | 140504 | state = SKIP; | |
240 | 140504 | break; | |
241 | 4032 | case START_END: | |
242 | 4032 | state = INIT; | |
243 | 4032 | break; | |
244 | ✗ | default: | |
245 | ✗ | mutex_unlock(&lbm_mem_mutex); | |
246 | ✗ | return 0; | |
247 | break; | ||
248 | } | ||
249 | } | ||
250 | 3360 | mutex_unlock(&lbm_mem_mutex); | |
251 |
1/2✓ Branch 0 taken 3360 times.
✗ Branch 1 not taken.
|
3360 | if (memory_num_free - max_length < memory_reserve_level) { |
252 | 3360 | lbm_uint n = memory_reserve_level - (memory_num_free - max_length); | |
253 | 3360 | max_length -= n; | |
254 | } | ||
255 | 3360 | return max_length; | |
256 | } | ||
257 | |||
258 | 10400001 | static lbm_uint *lbm_memory_allocate_internal(lbm_uint num_words) { | |
259 | |||
260 |
2/4✓ Branch 0 taken 10400001 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10400001 times.
|
10400001 | if (memory == NULL || bitmap == NULL) { |
261 | ✗ | return NULL; | |
262 | } | ||
263 | |||
264 | 10400001 | mutex_lock(&lbm_mem_mutex); | |
265 | |||
266 | 10400001 | lbm_uint start_ix = 0; | |
267 | 10400001 | lbm_uint end_ix = 0; | |
268 | 10400001 | lbm_uint free_length = 0; | |
269 | 10400001 | unsigned int state = INIT; | |
270 | 10400001 | lbm_uint loop_max = (bitmap_size << BITMAP_SIZE_SHIFT); | |
271 | |||
272 |
2/2✓ Branch 0 taken 100720527 times.
✓ Branch 1 taken 5846 times.
|
100726373 | for (lbm_uint i = 0; i < loop_max; i ++) { |
273 |
4/5✓ Branch 1 taken 89474637 times.
✓ Branch 2 taken 10707372 times.
✓ Branch 3 taken 458564 times.
✓ Branch 4 taken 79954 times.
✗ Branch 5 not taken.
|
100720527 | switch(status(alloc_offset)) { |
274 |
3/4✓ Branch 0 taken 10470867 times.
✓ Branch 1 taken 59357366 times.
✓ Branch 2 taken 19646404 times.
✗ Branch 3 not taken.
|
89474637 | case FREE_OR_USED: |
275 | switch (state) { | ||
276 | 10470867 | case INIT: | |
277 | 10470867 | start_ix = alloc_offset; | |
278 |
2/2✓ Branch 0 taken 73352 times.
✓ Branch 1 taken 10397515 times.
|
10470867 | if (num_words == 1) { |
279 | 73352 | end_ix = alloc_offset; | |
280 | 73352 | state = ALLOC_DONE; | |
281 | } else { | ||
282 | 10397515 | state = FREE_LENGTH_CHECK; | |
283 | 10397515 | free_length = 1; | |
284 | } | ||
285 | 10470867 | break; | |
286 | 59357366 | case FREE_LENGTH_CHECK: | |
287 | 59357366 | free_length ++; | |
288 |
2/2✓ Branch 0 taken 10320803 times.
✓ Branch 1 taken 49036563 times.
|
59357366 | if (free_length == num_words) { |
289 | 10320803 | end_ix = alloc_offset; | |
290 | 10320803 | state = ALLOC_DONE; | |
291 | } else { | ||
292 | 49036563 | state = FREE_LENGTH_CHECK; | |
293 | } | ||
294 | 59357366 | break; | |
295 | 19646404 | case SKIP: | |
296 | 19646404 | break; | |
297 | } | ||
298 | 89474637 | break; | |
299 | 10707372 | case END: | |
300 | 10707372 | state = INIT; | |
301 | 10707372 | break; | |
302 | 458564 | case START: | |
303 | 458564 | state = SKIP; | |
304 | 458564 | break; | |
305 | 79954 | case START_END: | |
306 | 79954 | state = INIT; | |
307 | 79954 | break; | |
308 | ✗ | default: // error case | |
309 | ✗ | mutex_unlock(&lbm_mem_mutex); | |
310 | ✗ | return NULL; | |
311 | } | ||
312 | |||
313 |
2/2✓ Branch 0 taken 10394155 times.
✓ Branch 1 taken 90326372 times.
|
100720527 | if (state == ALLOC_DONE) break; |
314 | |||
315 | 90326372 | alloc_offset++; | |
316 |
2/2✓ Branch 0 taken 6182 times.
✓ Branch 1 taken 90320190 times.
|
90326372 | if (alloc_offset == loop_max ) { |
317 | 6182 | free_length = 0; | |
318 | 6182 | alloc_offset = 0; | |
319 | 6182 | state = INIT; | |
320 | } | ||
321 | } | ||
322 | |||
323 |
2/2✓ Branch 0 taken 10394155 times.
✓ Branch 1 taken 5846 times.
|
10400001 | if (state == ALLOC_DONE) { |
324 |
2/2✓ Branch 0 taken 73352 times.
✓ Branch 1 taken 10320803 times.
|
10394155 | if (start_ix == end_ix) { |
325 | 73352 | set_status(start_ix, START_END); | |
326 | } else { | ||
327 | 10320803 | set_status(start_ix, START); | |
328 | 10320803 | set_status(end_ix, END); | |
329 | } | ||
330 | 10394155 | memory_num_free -= num_words; | |
331 | 10394155 | mutex_unlock(&lbm_mem_mutex); | |
332 | 10394155 | return bitmap_ix_to_address(start_ix); | |
333 | } | ||
334 | 5846 | mutex_unlock(&lbm_mem_mutex); | |
335 | 5846 | return NULL; | |
336 | } | ||
337 | |||
338 | 454328 | lbm_uint *lbm_memory_allocate(lbm_uint num_words) { | |
339 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 454328 times.
|
454328 | if (memory_num_free - num_words < memory_reserve_level) { |
340 | ✗ | lbm_request_gc(); | |
341 | ✗ | return NULL; | |
342 | } | ||
343 | 454328 | return lbm_memory_allocate_internal(num_words); | |
344 | } | ||
345 | |||
346 | 9691839 | int lbm_memory_free(lbm_uint *ptr) { | |
347 | 9691839 | int r = 0; | |
348 | 9691839 | lbm_uint count_freed = 0; | |
349 |
2/2✓ Branch 1 taken 9644657 times.
✓ Branch 2 taken 47182 times.
|
9691839 | if (lbm_memory_ptr_inside(ptr)) { |
350 | 9644657 | mutex_lock(&lbm_mem_mutex); | |
351 | 9644657 | lbm_uint ix = address_to_bitmap_ix(ptr); | |
352 | 9644657 | alloc_offset = ix; | |
353 | |||
354 |
2/3✓ Branch 1 taken 9576803 times.
✓ Branch 2 taken 67854 times.
✗ Branch 3 not taken.
|
9644657 | switch(status(ix)) { |
355 | 9576803 | case START: | |
356 | 9576803 | set_status(ix, FREE_OR_USED); | |
357 |
1/2✓ Branch 0 taken 45759004 times.
✗ Branch 1 not taken.
|
45759004 | for (lbm_uint i = ix; i < (bitmap_size << BITMAP_SIZE_SHIFT); i ++) { |
358 | 45759004 | count_freed ++; | |
359 |
2/2✓ Branch 1 taken 9576803 times.
✓ Branch 2 taken 36182201 times.
|
45759004 | if (status(i) == END) { |
360 | 9576803 | set_status(i, FREE_OR_USED); | |
361 | 9576803 | r = 1; | |
362 | 9576803 | break; | |
363 | } | ||
364 | } | ||
365 | 9576803 | break; | |
366 | 67854 | case START_END: | |
367 | 67854 | set_status(ix, FREE_OR_USED); | |
368 | 67854 | count_freed = 1; | |
369 | 67854 | r = 1; | |
370 | 67854 | break; | |
371 | ✗ | default: | |
372 | ✗ | break; | |
373 | } | ||
374 |
1/2✓ Branch 0 taken 9644657 times.
✗ Branch 1 not taken.
|
9644657 | if (r) { |
375 |
3/4✓ Branch 0 taken 101216679 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 91572022 times.
✓ Branch 4 taken 9644657 times.
|
101216679 | while (alloc_offset > 0 && status(alloc_offset - 1) == FREE_OR_USED) { |
376 | 91572022 | alloc_offset--; | |
377 | } | ||
378 | } | ||
379 | 9644657 | memory_num_free += count_freed; | |
380 | 9644657 | mutex_unlock(&lbm_mem_mutex); | |
381 | } | ||
382 | 9691839 | return r; | |
383 | } | ||
384 | //Malloc/free like interface | ||
385 | 9908858 | void* lbm_malloc(size_t size) { | |
386 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9908858 times.
|
9908858 | if (size == 0) return NULL; |
387 | lbm_uint alloc_size; | ||
388 | |||
389 | 9908858 | alloc_size = size / sizeof(lbm_uint); | |
390 |
2/2✓ Branch 0 taken 325174 times.
✓ Branch 1 taken 9583684 times.
|
9908858 | if (size % sizeof(lbm_uint)) alloc_size += 1; |
391 | |||
392 |
2/2✓ Branch 0 taken 4280 times.
✓ Branch 1 taken 9904578 times.
|
9908858 | if (memory_num_free - alloc_size < memory_reserve_level) { |
393 | 4280 | lbm_request_gc(); | |
394 | 4280 | return NULL; | |
395 | } | ||
396 | 9904578 | return lbm_memory_allocate_internal(alloc_size); | |
397 | } | ||
398 | |||
399 | 41095 | void* lbm_malloc_reserve(size_t size) { | |
400 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41095 times.
|
41095 | if (size == 0) return NULL; |
401 | lbm_uint alloc_size; | ||
402 | |||
403 | 41095 | alloc_size = size / sizeof(lbm_uint); | |
404 |
2/2✓ Branch 0 taken 40695 times.
✓ Branch 1 taken 400 times.
|
41095 | if (size % sizeof(lbm_uint)) alloc_size += 1; |
405 | |||
406 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 41007 times.
|
41095 | if (memory_num_free - alloc_size < memory_reserve_level) { |
407 | 88 | lbm_request_gc(); | |
408 | } | ||
409 | 41095 | return lbm_memory_allocate_internal(alloc_size); | |
410 | } | ||
411 | |||
412 | 30335 | void lbm_free(void *ptr) { | |
413 | 30335 | lbm_memory_free(ptr); | |
414 | 30335 | } | |
415 | |||
416 | 9769 | int lbm_memory_shrink(lbm_uint *ptr, lbm_uint n) { | |
417 |
2/4✓ Branch 1 taken 9769 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 9769 times.
|
9769 | if (!lbm_memory_ptr_inside(ptr) || n == 0) return 0; |
418 | |||
419 | 9769 | lbm_uint ix = address_to_bitmap_ix(ptr); | |
420 | |||
421 | 9769 | mutex_lock(&lbm_mem_mutex); | |
422 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9769 times.
|
9769 | if (status(ix) == START_END) { |
423 | ✗ | mutex_unlock(&lbm_mem_mutex); | |
424 | ✗ | return 1; // A one word arrays always succeeds at remaining at 1 word | |
425 | } | ||
426 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9769 times.
|
9769 | if (status(ix) != START) { |
427 | ✗ | mutex_unlock(&lbm_mem_mutex); | |
428 | ✗ | return 0; // ptr does not point to the start of an allocated range. | |
429 | } | ||
430 | |||
431 | 9769 | bool done = false; | |
432 | 9769 | unsigned int i = 0; | |
433 | |||
434 |
1/2✓ Branch 0 taken 114178 times.
✗ Branch 1 not taken.
|
114178 | for (i = 0; i < ((bitmap_size << BITMAP_SIZE_SHIFT) - ix); i ++) { |
435 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 114178 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
114178 | if (status(ix+i) == END && i < n) { |
436 | ✗ | mutex_unlock(&lbm_mem_mutex); | |
437 | ✗ | return 0; // cannot shrink allocation to a larger size | |
438 | } | ||
439 | |||
440 |
2/2✓ Branch 0 taken 9769 times.
✓ Branch 1 taken 104409 times.
|
114178 | if (i == (n-1)) { |
441 |
2/4✓ Branch 1 taken 9769 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 9769 times.
|
19538 | if (status(ix+i) == END || |
442 | 9769 | status(ix+i) == START_END) { | |
443 | ✗ | done = true; | |
444 | } | ||
445 |
2/2✓ Branch 0 taken 1176 times.
✓ Branch 1 taken 8593 times.
|
9769 | if (i == 0) { |
446 | 1176 | set_status(ix+i, START_END); | |
447 | } | ||
448 | else { | ||
449 | 8593 | set_status(ix+i, END); | |
450 | } | ||
451 | 9769 | break; | |
452 | } | ||
453 | } | ||
454 | 9769 | alloc_offset = ix+i; | |
455 | |||
456 | 9769 | lbm_uint count = 0; | |
457 |
1/2✓ Branch 0 taken 9769 times.
✗ Branch 1 not taken.
|
9769 | if (!done) { |
458 | 9769 | i++; // move to next position, prev position should be END or START_END | |
459 |
1/2✓ Branch 0 taken 7541477 times.
✗ Branch 1 not taken.
|
7541477 | for (;i < ((bitmap_size << BITMAP_SIZE_SHIFT) - ix); i ++) { |
460 | 7541477 | count ++; | |
461 |
2/2✓ Branch 1 taken 9769 times.
✓ Branch 2 taken 7531708 times.
|
7541477 | if (status(ix+i) == END) { |
462 | 9769 | set_status(ix+i, FREE_OR_USED); | |
463 | 9769 | break; | |
464 | } | ||
465 | } | ||
466 | } | ||
467 | |||
468 | 9769 | memory_num_free += count; | |
469 | 9769 | mutex_unlock(&lbm_mem_mutex); | |
470 | 9769 | return 1; | |
471 | } | ||
472 | |||
473 | 9701608 | int lbm_memory_ptr_inside(lbm_uint *ptr) { | |
474 |
2/2✓ Branch 0 taken 9654426 times.
✓ Branch 1 taken 47182 times.
|
19356034 | return ((lbm_uint)ptr >= (lbm_uint)memory && |
475 |
1/2✓ Branch 0 taken 9654426 times.
✗ Branch 1 not taken.
|
9654426 | (lbm_uint)ptr < (lbm_uint)memory + (memory_size * sizeof(lbm_uint))); |
476 | } | ||
477 |