| 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 | 34888 | 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 17444 times.
✓ Branch 1 taken 17444 times.
|
34888 | if (!lbm_mem_mutex_initialized) { |
| 57 | 17444 | mutex_init(&lbm_mem_mutex); | |
| 58 | 17444 | lbm_mem_mutex_initialized = true; | |
| 59 | } | ||
| 60 | |||
| 61 | 34888 | alloc_offset = 0; | |
| 62 | |||
| 63 | 34888 | mutex_lock(&lbm_mem_mutex); | |
| 64 | 34888 | int res = 0; | |
| 65 |
2/4✓ Branch 0 taken 34888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 34888 times.
|
34888 | if (data == NULL || bits == NULL) return 0; |
| 66 | |||
| 67 |
1/2✓ Branch 0 taken 34888 times.
✗ Branch 1 not taken.
|
34888 | if (((lbm_uint)data % sizeof(lbm_uint) != 0) || |
| 68 |
1/2✓ Branch 0 taken 34888 times.
✗ Branch 1 not taken.
|
34888 | (data_size * 2) != (bits_size * sizeof(lbm_uint) * 8) || |
| 69 |
1/2✓ Branch 0 taken 34888 times.
✗ Branch 1 not taken.
|
34888 | data_size % 4 != 0 || |
| 70 |
2/4✓ Branch 0 taken 34888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34888 times.
✗ Branch 3 not taken.
|
34888 | ((lbm_uint)bits % sizeof(lbm_uint) != 0) || |
| 71 | 34888 | bits_size < 1 || | |
| 72 |
1/2✓ Branch 0 taken 34888 times.
✗ Branch 1 not taken.
|
34888 | 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 | 34888 | bitmap = bits; | |
| 79 | 34888 | bitmap_size = bits_size; | |
| 80 | |||
| 81 |
2/2✓ Branch 0 taken 8931328 times.
✓ Branch 1 taken 34888 times.
|
8966216 | for (lbm_uint i = 0; i < bitmap_size; i ++) { |
| 82 | 8931328 | bitmap[i] = 0; | |
| 83 | } | ||
| 84 | |||
| 85 | 34888 | memory = data; | |
| 86 | 34888 | memory_base_address = (lbm_uint)data; | |
| 87 | 34888 | memory_size = data_size; | |
| 88 | 34888 | memory_num_free = data_size; | |
| 89 | 34888 | memory_reserve_level = (lbm_uint)(0.1 * (lbm_float)data_size); | |
| 90 | 34888 | res = 1; | |
| 91 | } | ||
| 92 | 34888 | mutex_unlock(&lbm_mem_mutex); | |
| 93 | 34888 | 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 | 8796070 | static inline lbm_uint address_to_bitmap_ix(lbm_uint *ptr) { | |
| 105 | #ifndef LBM64 | ||
| 106 | 8796070 | return ((lbm_uint)ptr - memory_base_address) >> 2; | |
| 107 | #else | ||
| 108 | return ((lbm_uint)ptr - memory_base_address) >> 3; | ||
| 109 | #endif | ||
| 110 | } | ||
| 111 | |||
| 112 | 18228 | 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 | 18228 | return (lbm_int)address_to_bitmap_ix(ptr); | |
| 117 | } | ||
| 118 | |||
| 119 | |||
| 120 | 9344182 | static inline lbm_uint *bitmap_ix_to_address(lbm_uint ix) { | |
| 121 | 9344182 | 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 | 382365100 | static inline lbm_uint status(lbm_uint i) { | |
| 135 | |||
| 136 | 382365100 | lbm_uint ix = i << 1; // * 2 | |
| 137 | 382365100 | lbm_uint word_ix = ix >> WORD_IX_SHIFT; // / 32 | |
| 138 | 382365100 | lbm_uint bit_ix = ix & WORD_MOD_MASK; // % 32 | |
| 139 | |||
| 140 | 382365100 | lbm_uint mask = ((lbm_uint)3) << bit_ix; // 000110..0 | |
| 141 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 382365100 times.
|
382365100 | if (word_ix > bitmap_size) { |
| 142 | ✗ | return (lbm_uint)NULL; | |
| 143 | } | ||
| 144 | 382365100 | return (bitmap[word_ix] & mask) >> bit_ix; | |
| 145 | } | ||
| 146 | |||
| 147 | 36106448 | static inline void set_status(lbm_uint i, lbm_uint status) { | |
| 148 | 36106448 | lbm_uint ix = i << 1; // * 2 | |
| 149 | 36106448 | lbm_uint word_ix = ix >> WORD_IX_SHIFT; // / 32 | |
| 150 | 36106448 | lbm_uint bit_ix = ix & WORD_MOD_MASK; // % 32 | |
| 151 | |||
| 152 | 36106448 | lbm_uint clr_mask = ~(((lbm_uint)3) << bit_ix); | |
| 153 | 36106448 | lbm_uint mask = status << bit_ix; | |
| 154 | |||
| 155 | 36106448 | bitmap[word_ix] &= clr_mask; | |
| 156 | 36106448 | bitmap[word_ix] |= mask; | |
| 157 | 36106448 | } | |
| 158 | |||
| 159 | ✗ | lbm_uint lbm_memory_num_words(void) { | |
| 160 | ✗ | return memory_size; | |
| 161 | } | ||
| 162 | |||
| 163 | 35952 | lbm_uint lbm_memory_num_free(void) { | |
| 164 |
2/4✓ Branch 0 taken 35952 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35952 times.
|
35952 | if (memory == NULL || bitmap == NULL) { |
| 165 | ✗ | return 0; | |
| 166 | } | ||
| 167 | 35952 | mutex_lock(&lbm_mem_mutex); | |
| 168 | 35952 | unsigned int state = INIT; | |
| 169 | 35952 | lbm_uint sum_length = 0; | |
| 170 | |||
| 171 |
2/2✓ Branch 0 taken 147259392 times.
✓ Branch 1 taken 35952 times.
|
147295344 | for (unsigned int i = 0; i < (bitmap_size << BITMAP_SIZE_SHIFT); i ++) { |
| 172 | |||
| 173 |
4/5✓ Branch 1 taken 145505640 times.
✓ Branch 2 taken 876568 times.
✓ Branch 3 taken 876568 times.
✓ Branch 4 taken 616 times.
✗ Branch 5 not taken.
|
147259392 | switch(status(i)) { |
| 174 |
3/4✓ Branch 0 taken 37128 times.
✓ Branch 1 taken 128999696 times.
✓ Branch 2 taken 16468816 times.
✗ Branch 3 not taken.
|
145505640 | case FREE_OR_USED: |
| 175 | switch (state) { | ||
| 176 | 37128 | case INIT: | |
| 177 | 37128 | state = FREE_LENGTH_CHECK; | |
| 178 | 37128 | sum_length ++; | |
| 179 | 37128 | break; | |
| 180 | 128999696 | case FREE_LENGTH_CHECK: | |
| 181 | 128999696 | sum_length ++; | |
| 182 | 128999696 | state = FREE_LENGTH_CHECK; | |
| 183 | 128999696 | break; | |
| 184 | 16468816 | case SKIP: | |
| 185 | 16468816 | break; | |
| 186 | } | ||
| 187 | 145505640 | break; | |
| 188 | 876568 | case END: | |
| 189 | 876568 | state = INIT; | |
| 190 | 876568 | break; | |
| 191 | 876568 | case START: | |
| 192 | 876568 | state = SKIP; | |
| 193 | 876568 | 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 | 35952 | mutex_unlock(&lbm_mem_mutex); | |
| 204 | 35952 | return sum_length; | |
| 205 | } | ||
| 206 | |||
| 207 | 2912 | lbm_uint lbm_memory_longest_free(void) { | |
| 208 |
2/4✓ Branch 0 taken 2912 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2912 times.
|
2912 | if (memory == NULL || bitmap == NULL) { |
| 209 | ✗ | return 0; | |
| 210 | } | ||
| 211 | 2912 | mutex_lock(&lbm_mem_mutex); | |
| 212 | 2912 | unsigned int state = INIT; | |
| 213 | 2912 | lbm_uint max_length = 0; | |
| 214 | |||
| 215 | 2912 | lbm_uint curr_length = 0; | |
| 216 |
2/2✓ Branch 0 taken 11927552 times.
✓ Branch 1 taken 2912 times.
|
11930464 | for (unsigned int i = 0; i < (bitmap_size << BITMAP_SIZE_SHIFT); i ++) { |
| 217 | |||
| 218 |
4/5✓ Branch 1 taken 11674838 times.
✓ Branch 2 taken 124348 times.
✓ Branch 3 taken 124348 times.
✓ Branch 4 taken 4018 times.
✗ Branch 5 not taken.
|
11927552 | switch(status(i)) { |
| 219 |
3/4✓ Branch 0 taken 3360 times.
✓ Branch 1 taken 8670746 times.
✓ Branch 2 taken 3000732 times.
✗ Branch 3 not taken.
|
11674838 | case FREE_OR_USED: |
| 220 | switch (state) { | ||
| 221 | 3360 | case INIT: | |
| 222 | 3360 | curr_length = 1; | |
| 223 |
2/2✓ Branch 0 taken 2912 times.
✓ Branch 1 taken 448 times.
|
3360 | if (curr_length > max_length) max_length = curr_length; |
| 224 | 3360 | state = FREE_LENGTH_CHECK; | |
| 225 | 3360 | break; | |
| 226 | 8670746 | case FREE_LENGTH_CHECK: | |
| 227 | 8670746 | curr_length ++; | |
| 228 |
2/2✓ Branch 0 taken 8645994 times.
✓ Branch 1 taken 24752 times.
|
8670746 | if (curr_length > max_length) max_length = curr_length; |
| 229 | 8670746 | state = FREE_LENGTH_CHECK; | |
| 230 | 8670746 | break; | |
| 231 | 3000732 | case SKIP: | |
| 232 | 3000732 | break; | |
| 233 | } | ||
| 234 | 11674838 | break; | |
| 235 | 124348 | case END: | |
| 236 | 124348 | state = INIT; | |
| 237 | 124348 | break; | |
| 238 | 124348 | case START: | |
| 239 | 124348 | state = SKIP; | |
| 240 | 124348 | break; | |
| 241 | 4018 | case START_END: | |
| 242 | 4018 | state = INIT; | |
| 243 | 4018 | break; | |
| 244 | ✗ | default: | |
| 245 | ✗ | mutex_unlock(&lbm_mem_mutex); | |
| 246 | ✗ | return 0; | |
| 247 | break; | ||
| 248 | } | ||
| 249 | } | ||
| 250 | 2912 | mutex_unlock(&lbm_mem_mutex); | |
| 251 |
1/2✓ Branch 0 taken 2912 times.
✗ Branch 1 not taken.
|
2912 | if (memory_num_free - max_length < memory_reserve_level) { |
| 252 | 2912 | lbm_uint n = memory_reserve_level - (memory_num_free - max_length); | |
| 253 | 2912 | max_length -= n; | |
| 254 | } | ||
| 255 | 2912 | return max_length; | |
| 256 | } | ||
| 257 | |||
| 258 | 9349862 | static lbm_uint *lbm_memory_allocate_internal(lbm_uint num_words) { | |
| 259 | |||
| 260 |
2/4✓ Branch 0 taken 9349862 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9349862 times.
|
9349862 | if (memory == NULL || bitmap == NULL) { |
| 261 | ✗ | return NULL; | |
| 262 | } | ||
| 263 | |||
| 264 | 9349862 | mutex_lock(&lbm_mem_mutex); | |
| 265 | |||
| 266 | 9349862 | lbm_uint start_ix = 0; | |
| 267 | 9349862 | lbm_uint end_ix = 0; | |
| 268 | 9349862 | lbm_uint free_length = 0; | |
| 269 | 9349862 | unsigned int state = INIT; | |
| 270 | 9349862 | lbm_uint loop_max = (bitmap_size << BITMAP_SIZE_SHIFT); | |
| 271 | |||
| 272 |
2/2✓ Branch 0 taken 85821296 times.
✓ Branch 1 taken 5680 times.
|
85826976 | for (lbm_uint i = 0; i < loop_max; i ++) { |
| 273 |
4/5✓ Branch 1 taken 75700646 times.
✓ Branch 2 taken 9629050 times.
✓ Branch 3 taken 415536 times.
✓ Branch 4 taken 76064 times.
✗ Branch 5 not taken.
|
85821296 | switch(status(alloc_offset)) { |
| 274 |
3/4✓ Branch 0 taken 9404368 times.
✓ Branch 1 taken 47041242 times.
✓ Branch 2 taken 19255036 times.
✗ Branch 3 not taken.
|
75700646 | case FREE_OR_USED: |
| 275 | switch (state) { | ||
| 276 | 9404368 | case INIT: | |
| 277 | 9404368 | start_ix = alloc_offset; | |
| 278 |
2/2✓ Branch 0 taken 69932 times.
✓ Branch 1 taken 9334436 times.
|
9404368 | if (num_words == 1) { |
| 279 | 69932 | end_ix = alloc_offset; | |
| 280 | 69932 | state = ALLOC_DONE; | |
| 281 | } else { | ||
| 282 | 9334436 | state = FREE_LENGTH_CHECK; | |
| 283 | 9334436 | free_length = 1; | |
| 284 | } | ||
| 285 | 9404368 | break; | |
| 286 | 47041242 | case FREE_LENGTH_CHECK: | |
| 287 | 47041242 | free_length ++; | |
| 288 |
2/2✓ Branch 0 taken 9274250 times.
✓ Branch 1 taken 37766992 times.
|
47041242 | if (free_length == num_words) { |
| 289 | 9274250 | end_ix = alloc_offset; | |
| 290 | 9274250 | state = ALLOC_DONE; | |
| 291 | } else { | ||
| 292 | 37766992 | state = FREE_LENGTH_CHECK; | |
| 293 | } | ||
| 294 | 47041242 | break; | |
| 295 | 19255036 | case SKIP: | |
| 296 | 19255036 | break; | |
| 297 | } | ||
| 298 | 75700646 | break; | |
| 299 | 9629050 | case END: | |
| 300 | 9629050 | state = INIT; | |
| 301 | 9629050 | break; | |
| 302 | 415536 | case START: | |
| 303 | 415536 | state = SKIP; | |
| 304 | 415536 | break; | |
| 305 | 76064 | case START_END: | |
| 306 | 76064 | state = INIT; | |
| 307 | 76064 | break; | |
| 308 | ✗ | default: // error case | |
| 309 | ✗ | mutex_unlock(&lbm_mem_mutex); | |
| 310 | ✗ | return NULL; | |
| 311 | } | ||
| 312 | |||
| 313 |
2/2✓ Branch 0 taken 9344182 times.
✓ Branch 1 taken 76477114 times.
|
85821296 | if (state == ALLOC_DONE) break; |
| 314 | |||
| 315 | 76477114 | alloc_offset++; | |
| 316 |
2/2✓ Branch 0 taken 5976 times.
✓ Branch 1 taken 76471138 times.
|
76477114 | if (alloc_offset == loop_max ) { |
| 317 | 5976 | free_length = 0; | |
| 318 | 5976 | alloc_offset = 0; | |
| 319 | 5976 | state = INIT; | |
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 |
2/2✓ Branch 0 taken 9344182 times.
✓ Branch 1 taken 5680 times.
|
9349862 | if (state == ALLOC_DONE) { |
| 324 |
2/2✓ Branch 0 taken 69932 times.
✓ Branch 1 taken 9274250 times.
|
9344182 | if (start_ix == end_ix) { |
| 325 | 69932 | set_status(start_ix, START_END); | |
| 326 | } else { | ||
| 327 | 9274250 | set_status(start_ix, START); | |
| 328 | 9274250 | set_status(end_ix, END); | |
| 329 | } | ||
| 330 | 9344182 | memory_num_free -= num_words; | |
| 331 | 9344182 | mutex_unlock(&lbm_mem_mutex); | |
| 332 | 9344182 | return bitmap_ix_to_address(start_ix); | |
| 333 | } | ||
| 334 | 5680 | mutex_unlock(&lbm_mem_mutex); | |
| 335 | 5680 | return NULL; | |
| 336 | } | ||
| 337 | |||
| 338 | 510474 | lbm_uint *lbm_memory_allocate(lbm_uint num_words) { | |
| 339 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 510432 times.
|
510474 | if (memory_num_free - num_words < memory_reserve_level) { |
| 340 | 42 | lbm_request_gc(); | |
| 341 | 42 | return NULL; | |
| 342 | } | ||
| 343 | 510432 | return lbm_memory_allocate_internal(num_words); | |
| 344 | } | ||
| 345 | |||
| 346 | 8767004 | int lbm_memory_free(lbm_uint *ptr) { | |
| 347 | 8767004 | int r = 0; | |
| 348 | 8767004 | lbm_uint count_freed = 0; | |
| 349 |
1/2✓ Branch 1 taken 8767004 times.
✗ Branch 2 not taken.
|
8767004 | if (lbm_memory_ptr_inside(ptr)) { |
| 350 | 8767004 | mutex_lock(&lbm_mem_mutex); | |
| 351 | 8767004 | lbm_uint ix = address_to_bitmap_ix(ptr); | |
| 352 | 8767004 | alloc_offset = ix; | |
| 353 | |||
| 354 |
2/3✓ Branch 1 taken 8699336 times.
✓ Branch 2 taken 67668 times.
✗ Branch 3 not taken.
|
8767004 | switch(status(ix)) { |
| 355 | 8699336 | case START: | |
| 356 | 8699336 | set_status(ix, FREE_OR_USED); | |
| 357 |
1/2✓ Branch 0 taken 36318090 times.
✗ Branch 1 not taken.
|
36318090 | for (lbm_uint i = ix; i < (bitmap_size << BITMAP_SIZE_SHIFT); i ++) { |
| 358 | 36318090 | count_freed ++; | |
| 359 |
2/2✓ Branch 1 taken 8699336 times.
✓ Branch 2 taken 27618754 times.
|
36318090 | if (status(i) == END) { |
| 360 | 8699336 | set_status(i, FREE_OR_USED); | |
| 361 | 8699336 | r = 1; | |
| 362 | 8699336 | break; | |
| 363 | } | ||
| 364 | } | ||
| 365 | 8699336 | break; | |
| 366 | 67668 | case START_END: | |
| 367 | 67668 | set_status(ix, FREE_OR_USED); | |
| 368 | 67668 | count_freed = 1; | |
| 369 | 67668 | r = 1; | |
| 370 | 67668 | break; | |
| 371 | ✗ | default: | |
| 372 | ✗ | break; | |
| 373 | } | ||
| 374 |
1/2✓ Branch 0 taken 8767004 times.
✗ Branch 1 not taken.
|
8767004 | if (r) { |
| 375 |
3/4✓ Branch 0 taken 85718344 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 76951340 times.
✓ Branch 4 taken 8767004 times.
|
85718344 | while (alloc_offset > 0 && status(alloc_offset - 1) == FREE_OR_USED) { |
| 376 | 76951340 | alloc_offset--; | |
| 377 | } | ||
| 378 | } | ||
| 379 | 8767004 | memory_num_free += count_freed; | |
| 380 | 8767004 | mutex_unlock(&lbm_mem_mutex); | |
| 381 | } | ||
| 382 | 8767004 | return r; | |
| 383 | } | ||
| 384 | //Malloc/free like interface | ||
| 385 | 8833970 | void* lbm_malloc(size_t size) { | |
| 386 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8833970 times.
|
8833970 | if (size == 0) return NULL; |
| 387 | lbm_uint alloc_size; | ||
| 388 | |||
| 389 | 8833970 | alloc_size = size / sizeof(lbm_uint); | |
| 390 |
2/2✓ Branch 0 taken 108870 times.
✓ Branch 1 taken 8725100 times.
|
8833970 | if (size % sizeof(lbm_uint)) alloc_size += 1; |
| 391 | |||
| 392 |
2/2✓ Branch 0 taken 2894 times.
✓ Branch 1 taken 8831076 times.
|
8833970 | if (memory_num_free - alloc_size < memory_reserve_level) { |
| 393 | 2894 | lbm_request_gc(); | |
| 394 | 2894 | return NULL; | |
| 395 | } | ||
| 396 | 8831076 | return lbm_memory_allocate_internal(alloc_size); | |
| 397 | } | ||
| 398 | |||
| 399 | 8354 | void* lbm_malloc_reserve(size_t size) { | |
| 400 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8354 times.
|
8354 | if (size == 0) return NULL; |
| 401 | lbm_uint alloc_size; | ||
| 402 | |||
| 403 | 8354 | alloc_size = size / sizeof(lbm_uint); | |
| 404 |
2/2✓ Branch 0 taken 8290 times.
✓ Branch 1 taken 64 times.
|
8354 | if (size % sizeof(lbm_uint)) alloc_size += 1; |
| 405 | |||
| 406 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8354 times.
|
8354 | if (memory_num_free - alloc_size < memory_reserve_level) { |
| 407 | ✗ | lbm_request_gc(); | |
| 408 | } | ||
| 409 | 8354 | return lbm_memory_allocate_internal(alloc_size); | |
| 410 | } | ||
| 411 | |||
| 412 | 8961 | void lbm_free(void *ptr) { | |
| 413 | 8961 | lbm_memory_free(ptr); | |
| 414 | 8961 | } | |
| 415 | |||
| 416 | 10838 | int lbm_memory_shrink(lbm_uint *ptr, lbm_uint n) { | |
| 417 |
2/4✓ Branch 1 taken 10838 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 10838 times.
|
10838 | if (!lbm_memory_ptr_inside(ptr) || n == 0) return 0; |
| 418 | |||
| 419 | 10838 | lbm_uint ix = address_to_bitmap_ix(ptr); | |
| 420 | |||
| 421 | 10838 | mutex_lock(&lbm_mem_mutex); | |
| 422 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10838 times.
|
10838 | 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 10838 times.
|
10838 | 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 | 10838 | bool done = false; | |
| 432 | 10838 | unsigned int i = 0; | |
| 433 | |||
| 434 |
1/2✓ Branch 0 taken 118748 times.
✗ Branch 1 not taken.
|
118748 | for (i = 0; i < ((bitmap_size << BITMAP_SIZE_SHIFT) - ix); i ++) { |
| 435 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 118748 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
118748 | 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 10838 times.
✓ Branch 1 taken 107910 times.
|
118748 | if (i == (n-1)) { |
| 441 |
2/4✓ Branch 1 taken 10838 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 10838 times.
|
21676 | if (status(ix+i) == END || |
| 442 | 10838 | status(ix+i) == START_END) { | |
| 443 | ✗ | done = true; | |
| 444 | } | ||
| 445 |
2/2✓ Branch 0 taken 1064 times.
✓ Branch 1 taken 9774 times.
|
10838 | if (i == 0) { |
| 446 | 1064 | set_status(ix+i, START_END); | |
| 447 | } | ||
| 448 | else { | ||
| 449 | 9774 | set_status(ix+i, END); | |
| 450 | } | ||
| 451 | 10838 | break; | |
| 452 | } | ||
| 453 | } | ||
| 454 | 10838 | alloc_offset = ix+i; | |
| 455 | |||
| 456 | 10838 | lbm_uint count = 0; | |
| 457 |
1/2✓ Branch 0 taken 10838 times.
✗ Branch 1 not taken.
|
10838 | if (!done) { |
| 458 | 10838 | i++; // move to next position, prev position should be END or START_END | |
| 459 |
1/2✓ Branch 0 taken 6391322 times.
✗ Branch 1 not taken.
|
6391322 | for (;i < ((bitmap_size << BITMAP_SIZE_SHIFT) - ix); i ++) { |
| 460 | 6391322 | count ++; | |
| 461 |
2/2✓ Branch 1 taken 10838 times.
✓ Branch 2 taken 6380484 times.
|
6391322 | if (status(ix+i) == END) { |
| 462 | 10838 | set_status(ix+i, FREE_OR_USED); | |
| 463 | 10838 | break; | |
| 464 | } | ||
| 465 | } | ||
| 466 | } | ||
| 467 | |||
| 468 | 10838 | memory_num_free += count; | |
| 469 | 10838 | mutex_unlock(&lbm_mem_mutex); | |
| 470 | 10838 | return 1; | |
| 471 | } | ||
| 472 | |||
| 473 | 8979761 | int lbm_memory_ptr_inside(lbm_uint *ptr) { | |
| 474 |
2/2✓ Branch 0 taken 8942564 times.
✓ Branch 1 taken 37197 times.
|
17922325 | return ((lbm_uint)ptr >= (lbm_uint)memory && |
| 475 |
1/2✓ Branch 0 taken 8942564 times.
✗ Branch 1 not taken.
|
8942564 | (lbm_uint)ptr < (lbm_uint)memory + (memory_size * sizeof(lbm_uint))); |
| 476 | } | ||
| 477 |