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 lbm_uint memory_min_free = 0; |
49 |
|
|
static volatile lbm_uint memory_reserve_level = 0; |
50 |
|
|
static mutex_t lbm_mem_mutex; |
51 |
|
|
static bool lbm_mem_mutex_initialized; |
52 |
|
|
static lbm_uint alloc_offset = 0; |
53 |
|
|
|
54 |
|
43344 |
int lbm_memory_init(lbm_uint *data, lbm_uint data_size, |
55 |
|
|
lbm_uint *bits, lbm_uint bits_size) { |
56 |
|
|
|
57 |
✓✓ |
43344 |
if (!lbm_mem_mutex_initialized) { |
58 |
|
21672 |
mutex_init(&lbm_mem_mutex); |
59 |
|
21672 |
lbm_mem_mutex_initialized = true; |
60 |
|
|
} |
61 |
|
|
|
62 |
|
43344 |
alloc_offset = 0; |
63 |
|
|
|
64 |
|
43344 |
mutex_lock(&lbm_mem_mutex); |
65 |
|
43344 |
int res = 0; |
66 |
✓✗✗✓
|
43344 |
if (data == NULL || bits == NULL) return 0; |
67 |
|
|
|
68 |
✓✗ |
43344 |
if (((lbm_uint)data % sizeof(lbm_uint) != 0) || |
69 |
✓✗ |
43344 |
(data_size * 2) != (bits_size * sizeof(lbm_uint) * 8) || |
70 |
✓✗ |
43344 |
data_size % 4 != 0 || |
71 |
✓✗✓✗
|
43344 |
((lbm_uint)bits % sizeof(lbm_uint) != 0) || |
72 |
|
43344 |
bits_size < 1 || |
73 |
✓✗ |
43344 |
bits_size % 4 != 0) { |
74 |
|
|
// data is not aligned to sizeof lbm_uint |
75 |
|
|
// size is too small |
76 |
|
|
// or size is not a multiple of 4 |
77 |
|
|
} else { |
78 |
|
|
|
79 |
|
43344 |
bitmap = bits; |
80 |
|
43344 |
bitmap_size = bits_size; |
81 |
|
|
|
82 |
✓✓ |
11139408 |
for (lbm_uint i = 0; i < bitmap_size; i ++) { |
83 |
|
11096064 |
bitmap[i] = 0; |
84 |
|
|
} |
85 |
|
|
|
86 |
|
43344 |
memory = data; |
87 |
|
43344 |
memory_base_address = (lbm_uint)data; |
88 |
|
43344 |
memory_size = data_size; |
89 |
|
43344 |
memory_min_free = data_size; |
90 |
|
43344 |
memory_num_free = data_size; |
91 |
|
43344 |
memory_reserve_level = (lbm_uint)(0.1 * (lbm_float)data_size); |
92 |
|
43344 |
res = 1; |
93 |
|
|
} |
94 |
|
43344 |
mutex_unlock(&lbm_mem_mutex); |
95 |
|
43344 |
return res; |
96 |
|
|
} |
97 |
|
|
|
98 |
|
|
void lbm_memory_set_reserve(lbm_uint num_words) { |
99 |
|
|
memory_reserve_level = num_words; |
100 |
|
|
} |
101 |
|
|
|
102 |
|
|
lbm_uint lbm_memory_get_reserve(void) { |
103 |
|
|
return memory_reserve_level; |
104 |
|
|
} |
105 |
|
|
|
106 |
|
9679873 |
static inline lbm_uint address_to_bitmap_ix(lbm_uint *ptr) { |
107 |
|
|
#ifndef LBM64 |
108 |
|
9679873 |
return ((lbm_uint)ptr - memory_base_address) >> 2; |
109 |
|
|
#else |
110 |
|
|
return ((lbm_uint)ptr - memory_base_address) >> 3; |
111 |
|
|
#endif |
112 |
|
|
} |
113 |
|
|
|
114 |
|
22708 |
lbm_int lbm_memory_address_to_ix(lbm_uint *ptr) { |
115 |
|
|
/* TODO: assuming that index |
116 |
|
|
will have more then enough room in the |
117 |
|
|
positive half of a 28bit integer */ |
118 |
|
22708 |
return (lbm_int)address_to_bitmap_ix(ptr); |
119 |
|
|
} |
120 |
|
|
|
121 |
|
|
|
122 |
|
10400437 |
static inline lbm_uint *bitmap_ix_to_address(lbm_uint ix) { |
123 |
|
10400437 |
return &((lbm_uint*)(memory_base_address))[ix];// + (ix << 2)); |
124 |
|
|
} |
125 |
|
|
|
126 |
|
|
#ifndef LBM64 |
127 |
|
|
#define WORD_IX_SHIFT 5 |
128 |
|
|
#define WORD_MOD_MASK 0x1F |
129 |
|
|
#define BITMAP_SIZE_SHIFT 4 // 16 statuses per bitmap word |
130 |
|
|
#else |
131 |
|
|
#define WORD_IX_SHIFT 6 // divide by 64 |
132 |
|
|
#define WORD_MOD_MASK 0x3F // mod 64 |
133 |
|
|
#define BITMAP_SIZE_SHIFT 5 // times 32, 32 statuses per bitmap word |
134 |
|
|
#endif |
135 |
|
|
|
136 |
|
279058183 |
static inline lbm_uint status(lbm_uint i) { |
137 |
|
|
|
138 |
|
279058183 |
lbm_uint ix = i << 1; // * 2 |
139 |
|
279058183 |
lbm_uint word_ix = ix >> WORD_IX_SHIFT; // / 32 |
140 |
|
279058183 |
lbm_uint bit_ix = ix & WORD_MOD_MASK; // % 32 |
141 |
|
|
|
142 |
|
279058183 |
lbm_uint mask = ((lbm_uint)3) << bit_ix; // 000110..0 |
143 |
✗✓ |
279058183 |
if (word_ix > bitmap_size) { |
144 |
|
|
return (lbm_uint)NULL; |
145 |
|
|
} |
146 |
|
279058183 |
return (bitmap[word_ix] & mask) >> bit_ix; |
147 |
|
|
} |
148 |
|
|
|
149 |
|
39973998 |
static inline void set_status(lbm_uint i, lbm_uint status) { |
150 |
|
39973998 |
lbm_uint ix = i << 1; // * 2 |
151 |
|
39973998 |
lbm_uint word_ix = ix >> WORD_IX_SHIFT; // / 32 |
152 |
|
39973998 |
lbm_uint bit_ix = ix & WORD_MOD_MASK; // % 32 |
153 |
|
|
|
154 |
|
39973998 |
lbm_uint clr_mask = ~(((lbm_uint)3) << bit_ix); |
155 |
|
39973998 |
lbm_uint mask = status << bit_ix; |
156 |
|
|
|
157 |
|
39973998 |
bitmap[word_ix] &= clr_mask; |
158 |
|
39973998 |
bitmap[word_ix] |= mask; |
159 |
|
39973998 |
} |
160 |
|
|
|
161 |
|
28 |
lbm_uint lbm_memory_num_words(void) { |
162 |
|
28 |
return memory_size; |
163 |
|
|
} |
164 |
|
|
|
165 |
|
44408 |
lbm_uint lbm_memory_num_free(void) { |
166 |
|
44408 |
return memory_num_free; |
167 |
|
|
} |
168 |
|
|
|
169 |
|
|
lbm_uint lbm_memory_maximum_used(void) { |
170 |
|
|
return (memory_size - memory_min_free); |
171 |
|
|
} |
172 |
|
|
|
173 |
|
347919 |
void lbm_memory_update_min_free(void) { |
174 |
✓✓ |
347919 |
if (memory_num_free < memory_min_free) |
175 |
|
3350 |
memory_min_free = memory_num_free; |
176 |
|
347919 |
} |
177 |
|
|
|
178 |
|
3360 |
lbm_uint lbm_memory_longest_free(void) { |
179 |
✓✗✗✓
|
3360 |
if (memory == NULL || bitmap == NULL) { |
180 |
|
|
return 0; |
181 |
|
|
} |
182 |
|
3360 |
mutex_lock(&lbm_mem_mutex); |
183 |
|
3360 |
unsigned int state = INIT; |
184 |
|
3360 |
lbm_uint max_length = 0; |
185 |
|
|
|
186 |
|
3360 |
lbm_uint curr_length = 0; |
187 |
✓✓ |
13765920 |
for (unsigned int i = 0; i < (bitmap_size << BITMAP_SIZE_SHIFT); i ++) { |
188 |
|
|
|
189 |
✓✓✓✓ ✗ |
13762560 |
switch(status(i)) { |
190 |
✓✓✓✗
|
13477520 |
case FREE_OR_USED: |
191 |
|
|
switch (state) { |
192 |
|
3808 |
case INIT: |
193 |
|
3808 |
curr_length = 1; |
194 |
✓✓ |
3808 |
if (curr_length > max_length) max_length = curr_length; |
195 |
|
3808 |
state = FREE_LENGTH_CHECK; |
196 |
|
3808 |
break; |
197 |
|
10138828 |
case FREE_LENGTH_CHECK: |
198 |
|
10138828 |
curr_length ++; |
199 |
✓✓ |
10138828 |
if (curr_length > max_length) max_length = curr_length; |
200 |
|
10138828 |
state = FREE_LENGTH_CHECK; |
201 |
|
10138828 |
break; |
202 |
|
3334884 |
case SKIP: |
203 |
|
3334884 |
break; |
204 |
|
|
} |
205 |
|
13477520 |
break; |
206 |
|
140504 |
case END: |
207 |
|
140504 |
state = INIT; |
208 |
|
140504 |
break; |
209 |
|
140504 |
case START: |
210 |
|
140504 |
state = SKIP; |
211 |
|
140504 |
break; |
212 |
|
4032 |
case START_END: |
213 |
|
4032 |
state = INIT; |
214 |
|
4032 |
break; |
215 |
|
|
default: |
216 |
|
|
mutex_unlock(&lbm_mem_mutex); |
217 |
|
|
return 0; |
218 |
|
|
break; |
219 |
|
|
} |
220 |
|
|
} |
221 |
|
3360 |
mutex_unlock(&lbm_mem_mutex); |
222 |
✓✗ |
3360 |
if (memory_num_free - max_length < memory_reserve_level) { |
223 |
|
3360 |
lbm_uint n = memory_reserve_level - (memory_num_free - max_length); |
224 |
|
3360 |
max_length -= n; |
225 |
|
|
} |
226 |
|
3360 |
return max_length; |
227 |
|
|
} |
228 |
|
|
|
229 |
|
10406283 |
static lbm_uint *lbm_memory_allocate_internal(lbm_uint num_words) { |
230 |
|
|
|
231 |
✓✗✗✓
|
10406283 |
if (memory == NULL || bitmap == NULL) { |
232 |
|
|
return NULL; |
233 |
|
|
} |
234 |
|
|
|
235 |
|
10406283 |
mutex_lock(&lbm_mem_mutex); |
236 |
|
|
|
237 |
|
10406283 |
lbm_uint start_ix = 0; |
238 |
|
10406283 |
lbm_uint end_ix = 0; |
239 |
|
10406283 |
lbm_uint free_length = 0; |
240 |
|
10406283 |
unsigned int state = INIT; |
241 |
|
10406283 |
lbm_uint loop_max = (bitmap_size << BITMAP_SIZE_SHIFT); |
242 |
|
|
|
243 |
✓✓ |
100874255 |
for (lbm_uint i = 0; i < loop_max; i ++) { |
244 |
✓✓✓✓ ✗ |
100868409 |
switch(status(alloc_offset)) { |
245 |
✓✓✓✗
|
89617507 |
case FREE_OR_USED: |
246 |
|
|
switch (state) { |
247 |
|
10477149 |
case INIT: |
248 |
|
10477149 |
start_ix = alloc_offset; |
249 |
✓✓ |
10477149 |
if (num_words == 1) { |
250 |
|
73352 |
end_ix = alloc_offset; |
251 |
|
73352 |
state = ALLOC_DONE; |
252 |
|
|
} else { |
253 |
|
10403797 |
state = FREE_LENGTH_CHECK; |
254 |
|
10403797 |
free_length = 1; |
255 |
|
|
} |
256 |
|
10477149 |
break; |
257 |
|
59493954 |
case FREE_LENGTH_CHECK: |
258 |
|
59493954 |
free_length ++; |
259 |
✓✓ |
59493954 |
if (free_length == num_words) { |
260 |
|
10327085 |
end_ix = alloc_offset; |
261 |
|
10327085 |
state = ALLOC_DONE; |
262 |
|
|
} else { |
263 |
|
49166869 |
state = FREE_LENGTH_CHECK; |
264 |
|
|
} |
265 |
|
59493954 |
break; |
266 |
|
19646404 |
case SKIP: |
267 |
|
19646404 |
break; |
268 |
|
|
} |
269 |
|
89617507 |
break; |
270 |
|
10712384 |
case END: |
271 |
|
10712384 |
state = INIT; |
272 |
|
10712384 |
break; |
273 |
|
458564 |
case START: |
274 |
|
458564 |
state = SKIP; |
275 |
|
458564 |
break; |
276 |
|
79954 |
case START_END: |
277 |
|
79954 |
state = INIT; |
278 |
|
79954 |
break; |
279 |
|
|
default: // error case |
280 |
|
|
mutex_unlock(&lbm_mem_mutex); |
281 |
|
|
return NULL; |
282 |
|
|
} |
283 |
|
|
|
284 |
✓✓ |
100868409 |
if (state == ALLOC_DONE) break; |
285 |
|
|
|
286 |
|
90467972 |
alloc_offset++; |
287 |
✓✓ |
90467972 |
if (alloc_offset == loop_max ) { |
288 |
|
6182 |
free_length = 0; |
289 |
|
6182 |
alloc_offset = 0; |
290 |
|
6182 |
state = INIT; |
291 |
|
|
} |
292 |
|
|
} |
293 |
|
|
|
294 |
✓✓ |
10406283 |
if (state == ALLOC_DONE) { |
295 |
✓✓ |
10400437 |
if (start_ix == end_ix) { |
296 |
|
73352 |
set_status(start_ix, START_END); |
297 |
|
|
} else { |
298 |
|
10327085 |
set_status(start_ix, START); |
299 |
|
10327085 |
set_status(end_ix, END); |
300 |
|
|
} |
301 |
|
10400437 |
memory_num_free -= num_words; |
302 |
|
10400437 |
mutex_unlock(&lbm_mem_mutex); |
303 |
|
10400437 |
return bitmap_ix_to_address(start_ix); |
304 |
|
|
} |
305 |
|
5846 |
mutex_unlock(&lbm_mem_mutex); |
306 |
|
5846 |
return NULL; |
307 |
|
|
} |
308 |
|
|
|
309 |
|
457856 |
lbm_uint *lbm_memory_allocate(lbm_uint num_words) { |
310 |
✗✓ |
457856 |
if (memory_num_free - num_words < memory_reserve_level) { |
311 |
|
|
lbm_request_gc(); |
312 |
|
|
return NULL; |
313 |
|
|
} |
314 |
|
457856 |
return lbm_memory_allocate_internal(num_words); |
315 |
|
|
} |
316 |
|
|
|
317 |
|
9693832 |
int lbm_memory_free(lbm_uint *ptr) { |
318 |
|
9693832 |
int r = 0; |
319 |
✓✓ |
9693832 |
if (lbm_memory_ptr_inside(ptr)) { |
320 |
|
9646294 |
mutex_lock(&lbm_mem_mutex); |
321 |
|
9646294 |
lbm_uint ix = address_to_bitmap_ix(ptr); |
322 |
|
9646294 |
lbm_uint count_freed = 0; |
323 |
|
9646294 |
alloc_offset = ix; |
324 |
✓✓✗ |
9646294 |
switch(status(ix)) { |
325 |
|
9578440 |
case START: |
326 |
|
9578440 |
set_status(ix, FREE_OR_USED); |
327 |
✓✗ |
45810911 |
for (lbm_uint i = ix; i < (bitmap_size << BITMAP_SIZE_SHIFT); i ++) { |
328 |
|
45810911 |
count_freed ++; |
329 |
✓✓ |
45810911 |
if (status(i) == END) { |
330 |
|
9578440 |
set_status(i, FREE_OR_USED); |
331 |
|
9578440 |
r = 1; |
332 |
|
9578440 |
break; |
333 |
|
|
} |
334 |
|
|
} |
335 |
|
9578440 |
break; |
336 |
|
67854 |
case START_END: |
337 |
|
67854 |
set_status(ix, FREE_OR_USED); |
338 |
|
67854 |
count_freed = 1; |
339 |
|
67854 |
r = 1; |
340 |
|
67854 |
break; |
341 |
|
|
default: |
342 |
|
|
break; |
343 |
|
|
} |
344 |
✓✗ |
9646294 |
if (r) { |
345 |
✓✗✓✓
|
101263156 |
while (alloc_offset > 0 && status(alloc_offset - 1) == FREE_OR_USED) { |
346 |
|
91616862 |
alloc_offset--; |
347 |
|
|
} |
348 |
|
|
} |
349 |
|
9646294 |
memory_num_free += count_freed; |
350 |
|
9646294 |
mutex_unlock(&lbm_mem_mutex); |
351 |
|
|
} |
352 |
|
9693832 |
return r; |
353 |
|
|
} |
354 |
|
|
//Malloc/free like interface |
355 |
|
9910510 |
void* lbm_malloc(size_t size) { |
356 |
✗✓ |
9910510 |
if (size == 0) return NULL; |
357 |
|
|
lbm_uint alloc_size; |
358 |
|
|
|
359 |
|
9910510 |
alloc_size = size / sizeof(lbm_uint); |
360 |
✓✓ |
9910510 |
if (size % sizeof(lbm_uint)) alloc_size += 1; |
361 |
|
|
|
362 |
✓✓ |
9910510 |
if (memory_num_free - alloc_size < memory_reserve_level) { |
363 |
|
4280 |
lbm_request_gc(); |
364 |
|
4280 |
return NULL; |
365 |
|
|
} |
366 |
|
9906230 |
return lbm_memory_allocate_internal(alloc_size); |
367 |
|
|
} |
368 |
|
|
|
369 |
|
42197 |
void* lbm_malloc_reserve(size_t size) { |
370 |
✗✓ |
42197 |
if (size == 0) return NULL; |
371 |
|
|
lbm_uint alloc_size; |
372 |
|
|
|
373 |
|
42197 |
alloc_size = size / sizeof(lbm_uint); |
374 |
✓✓ |
42197 |
if (size % sizeof(lbm_uint)) alloc_size += 1; |
375 |
|
|
|
376 |
✓✓ |
42197 |
if (memory_num_free - alloc_size < memory_reserve_level) { |
377 |
|
88 |
lbm_request_gc(); |
378 |
|
|
} |
379 |
|
42197 |
return lbm_memory_allocate_internal(alloc_size); |
380 |
|
|
} |
381 |
|
|
|
382 |
|
31606 |
void lbm_free(void *ptr) { |
383 |
|
31606 |
lbm_memory_free(ptr); |
384 |
|
31606 |
} |
385 |
|
|
|
386 |
|
10871 |
int lbm_memory_shrink(lbm_uint *ptr, lbm_uint n) { |
387 |
✓✗✗✓
|
10871 |
if (!lbm_memory_ptr_inside(ptr) || n == 0) return 0; |
388 |
|
|
|
389 |
|
10871 |
lbm_uint ix = address_to_bitmap_ix(ptr); |
390 |
|
|
|
391 |
|
10871 |
mutex_lock(&lbm_mem_mutex); |
392 |
✗✓ |
10871 |
if (status(ix) == START_END) { |
393 |
|
|
mutex_unlock(&lbm_mem_mutex); |
394 |
|
|
return 1; // A one word arrays always succeeds at remaining at 1 word |
395 |
|
|
} |
396 |
✗✓ |
10871 |
if (status(ix) != START) { |
397 |
|
|
mutex_unlock(&lbm_mem_mutex); |
398 |
|
|
return 0; // ptr does not point to the start of an allocated range. |
399 |
|
|
} |
400 |
|
|
|
401 |
|
10871 |
bool done = false; |
402 |
|
10871 |
unsigned int i = 0; |
403 |
|
|
|
404 |
✓✗ |
116382 |
for (i = 0; i < ((bitmap_size << BITMAP_SIZE_SHIFT) - ix); i ++) { |
405 |
✗✓✗✗
|
116382 |
if (status(ix+i) == END && i < n) { |
406 |
|
|
mutex_unlock(&lbm_mem_mutex); |
407 |
|
|
return 0; // cannot shrink allocation to a larger size |
408 |
|
|
} |
409 |
|
|
|
410 |
✓✓ |
116382 |
if (i == (n-1)) { |
411 |
✓✗✗✓
|
21742 |
if (status(ix+i) == END || |
412 |
|
10871 |
status(ix+i) == START_END) { |
413 |
|
|
done = true; |
414 |
|
|
} |
415 |
✓✓ |
10871 |
if (i == 0) { |
416 |
|
1176 |
set_status(ix+i, START_END); |
417 |
|
|
} |
418 |
|
|
else { |
419 |
|
9695 |
set_status(ix+i, END); |
420 |
|
|
} |
421 |
|
10871 |
break; |
422 |
|
|
} |
423 |
|
|
} |
424 |
|
10871 |
alloc_offset = ix+i; |
425 |
|
|
|
426 |
|
10871 |
lbm_uint count = 0; |
427 |
✓✗ |
10871 |
if (!done) { |
428 |
|
10871 |
i++; // move to next position, prev position should be END or START_END |
429 |
✓✗ |
7546987 |
for (;i < ((bitmap_size << BITMAP_SIZE_SHIFT) - ix); i ++) { |
430 |
|
7546987 |
count ++; |
431 |
✓✓ |
7546987 |
if (status(ix+i) == END) { |
432 |
|
10871 |
set_status(ix+i, FREE_OR_USED); |
433 |
|
10871 |
break; |
434 |
|
|
} |
435 |
|
|
} |
436 |
|
|
} |
437 |
|
|
|
438 |
|
10871 |
memory_num_free += count; |
439 |
|
10871 |
mutex_unlock(&lbm_mem_mutex); |
440 |
|
10871 |
return 1; |
441 |
|
|
} |
442 |
|
|
|
443 |
|
9704703 |
int lbm_memory_ptr_inside(lbm_uint *ptr) { |
444 |
✓✓ |
19361868 |
return ((lbm_uint)ptr >= (lbm_uint)memory && |
445 |
✓✗ |
9657165 |
(lbm_uint)ptr < (lbm_uint)memory + (memory_size * sizeof(lbm_uint))); |
446 |
|
|
} |