| 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 |