| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | Copyright 2020 - 2025 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 | 88493 | bool lbm_memory_init(lbm_uint *data, lbm_uint data_size, | |
| 55 | lbm_uint *bits, lbm_uint bits_size) { | ||
| 56 | |||
| 57 |
2/2✓ Branch 0 taken 44304 times.
✓ Branch 1 taken 44189 times.
|
88493 | if (!lbm_mem_mutex_initialized) { |
| 58 | 44304 | mutex_init(&lbm_mem_mutex); | |
| 59 | 44304 | lbm_mem_mutex_initialized = true; | |
| 60 | } | ||
| 61 | |||
| 62 | 88493 | alloc_offset = 0; | |
| 63 | |||
| 64 | 88493 | mutex_lock(&lbm_mem_mutex); | |
| 65 | 88493 | bool res = false; | |
| 66 |
4/4✓ Branch 0 taken 88488 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 88485 times.
✓ Branch 3 taken 3 times.
|
88493 | if (data && bits) { |
| 67 | |||
| 68 |
1/2✓ Branch 0 taken 88485 times.
✗ Branch 1 not taken.
|
88485 | if (((lbm_uint)data % sizeof(lbm_uint) != 0) || |
| 69 |
2/2✓ Branch 0 taken 88480 times.
✓ Branch 1 taken 5 times.
|
88485 | (data_size * 2) != (bits_size * sizeof(lbm_uint) * 8) || |
| 70 |
1/2✓ Branch 0 taken 88480 times.
✗ Branch 1 not taken.
|
88480 | data_size % 4 != 0 || |
| 71 |
2/4✓ Branch 0 taken 88480 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88480 times.
✗ Branch 3 not taken.
|
88480 | ((lbm_uint)bits % sizeof(lbm_uint) != 0) || |
| 72 | 88480 | bits_size < 1 || | |
| 73 |
1/2✓ Branch 0 taken 88480 times.
✗ Branch 1 not taken.
|
88480 | 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 | 88480 | bitmap = bits; | |
| 80 | 88480 | bitmap_size = bits_size; | |
| 81 | |||
| 82 |
2/2✓ Branch 0 taken 195710172 times.
✓ Branch 1 taken 88480 times.
|
195798652 | for (lbm_uint i = 0; i < bitmap_size; i ++) { |
| 83 | 195710172 | bitmap[i] = 0; | |
| 84 | } | ||
| 85 | |||
| 86 | 88480 | memory = data; | |
| 87 | 88480 | memory_base_address = (lbm_uint)data; | |
| 88 | 88480 | memory_size = data_size; | |
| 89 | 88480 | memory_min_free = data_size; | |
| 90 | 88480 | memory_num_free = data_size; | |
| 91 | 88480 | memory_reserve_level = (lbm_uint)(0.1 * (lbm_float)data_size); | |
| 92 | 88480 | res = true; | |
| 93 | } | ||
| 94 | } | ||
| 95 | 88493 | mutex_unlock(&lbm_mem_mutex); | |
| 96 | 88493 | return res; | |
| 97 | } | ||
| 98 | |||
| 99 | 7 | void lbm_memory_set_reserve(lbm_uint num_words) { | |
| 100 | 7 | memory_reserve_level = num_words; | |
| 101 | 7 | } | |
| 102 | |||
| 103 | 3 | lbm_uint lbm_memory_get_reserve(void) { | |
| 104 | 3 | return memory_reserve_level; | |
| 105 | } | ||
| 106 | |||
| 107 | 12148513 | static inline lbm_uint address_to_bitmap_ix(lbm_uint *ptr) { | |
| 108 | #ifndef LBM64 | ||
| 109 | 10279885 | return ((lbm_uint)ptr - memory_base_address) >> 2; | |
| 110 | #else | ||
| 111 | 1868628 | return ((lbm_uint)ptr - memory_base_address) >> 3; | |
| 112 | #endif | ||
| 113 | } | ||
| 114 | |||
| 115 | 46520 | lbm_int lbm_memory_address_to_ix(lbm_uint *ptr) { | |
| 116 | /* TODO: assuming that index | ||
| 117 | will have more then enough room in the | ||
| 118 | positive half of a 28bit integer */ | ||
| 119 | 46520 | return (lbm_int)address_to_bitmap_ix(ptr); | |
| 120 | } | ||
| 121 | |||
| 122 | |||
| 123 | 12415879 | static inline lbm_uint *bitmap_ix_to_address(lbm_uint ix) { | |
| 124 | 12415879 | return &((lbm_uint*)(memory_base_address))[ix];// + (ix << 2)); | |
| 125 | } | ||
| 126 | |||
| 127 | #ifndef LBM64 | ||
| 128 | #define WORD_IX_SHIFT 5 | ||
| 129 | #define WORD_MOD_MASK 0x1F | ||
| 130 | #define BITMAP_SIZE_SHIFT 4 // 16 statuses per bitmap word | ||
| 131 | #else | ||
| 132 | #define WORD_IX_SHIFT 6 // divide by 64 | ||
| 133 | #define WORD_MOD_MASK 0x3F // mod 64 | ||
| 134 | #define BITMAP_SIZE_SHIFT 5 // times 32, 32 statuses per bitmap word | ||
| 135 | #endif | ||
| 136 | |||
| 137 | 490971805 | static inline lbm_uint status(lbm_uint i) { | |
| 138 | |||
| 139 | 490971805 | lbm_uint ix = i << 1; // * 2 | |
| 140 | 490971805 | lbm_uint word_ix = ix >> WORD_IX_SHIFT; // / 32 | |
| 141 | 490971805 | lbm_uint bit_ix = ix & WORD_MOD_MASK; // % 32 | |
| 142 | |||
| 143 | 490971805 | lbm_uint mask = ((lbm_uint)3) << bit_ix; // 000110..0 | |
| 144 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 490971805 times.
|
490971805 | if (word_ix > bitmap_size) { |
| 145 | ✗ | return (lbm_uint)NULL; | |
| 146 | } | ||
| 147 | 490971805 | return (bitmap[word_ix] & mask) >> bit_ix; | |
| 148 | } | ||
| 149 | |||
| 150 | 48608568 | static inline void set_status(lbm_uint i, lbm_uint status) { | |
| 151 | 48608568 | lbm_uint ix = i << 1; // * 2 | |
| 152 | 48608568 | lbm_uint word_ix = ix >> WORD_IX_SHIFT; // / 32 | |
| 153 | 48608568 | lbm_uint bit_ix = ix & WORD_MOD_MASK; // % 32 | |
| 154 | |||
| 155 | 48608568 | lbm_uint clr_mask = ~(((lbm_uint)3) << bit_ix); | |
| 156 | 48608568 | lbm_uint mask = status << bit_ix; | |
| 157 | |||
| 158 | 48608568 | bitmap[word_ix] &= clr_mask; | |
| 159 | 48608568 | bitmap[word_ix] |= mask; | |
| 160 | 48608568 | } | |
| 161 | |||
| 162 | 57 | lbm_uint lbm_memory_num_words(void) { | |
| 163 | 57 | return memory_size; | |
| 164 | } | ||
| 165 | |||
| 166 | 90296 | lbm_uint lbm_memory_num_free(void) { | |
| 167 | 90296 | return memory_num_free; | |
| 168 | } | ||
| 169 | |||
| 170 | 4 | lbm_uint lbm_memory_maximum_used(void) { | |
| 171 | 4 | return (memory_size - memory_min_free); | |
| 172 | } | ||
| 173 | |||
| 174 | 1012970 | void lbm_memory_update_min_free(void) { | |
| 175 |
2/2✓ Branch 0 taken 6409 times.
✓ Branch 1 taken 1006561 times.
|
1012970 | if (memory_num_free < memory_min_free) |
| 176 | 6409 | memory_min_free = memory_num_free; | |
| 177 | 1012970 | } | |
| 178 | |||
| 179 | 8288 | lbm_uint lbm_memory_longest_free(void) { | |
| 180 |
3/4✓ Branch 0 taken 8287 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8287 times.
|
8288 | if (memory == NULL || bitmap == NULL) { |
| 181 | 1 | return 0; | |
| 182 | } | ||
| 183 | 8287 | mutex_lock(&lbm_mem_mutex); | |
| 184 | 8287 | unsigned int state = INIT; | |
| 185 | 8287 | lbm_uint max_length = 0; | |
| 186 | |||
| 187 | 8287 | lbm_uint curr_length = 0; | |
| 188 |
2/2✓ Branch 0 taken 33792256 times.
✓ Branch 1 taken 8287 times.
|
33800543 | for (unsigned int i = 0; i < (bitmap_size << BITMAP_SIZE_SHIFT); i ++) { |
| 189 | |||
| 190 | // The status field is 2 bits and this 4 cases is exhaustive! | ||
| 191 |
4/4✓ Branch 0 taken 33539976 times.
✓ Branch 1 taken 121351 times.
✓ Branch 2 taken 121351 times.
✓ Branch 3 taken 9578 times.
|
33792256 | switch(status(i)) { |
| 192 | 33539976 | case FREE_OR_USED: | |
| 193 |
3/4✓ Branch 0 taken 9789 times.
✓ Branch 1 taken 26263044 times.
✓ Branch 2 taken 7267143 times.
✗ Branch 3 not taken.
|
33539976 | switch (state) { |
| 194 | 9789 | case INIT: | |
| 195 | 9789 | curr_length = 1; | |
| 196 |
2/2✓ Branch 0 taken 8287 times.
✓ Branch 1 taken 1502 times.
|
9789 | if (curr_length > max_length) max_length = curr_length; |
| 197 | 9789 | state = FREE_LENGTH_CHECK; | |
| 198 | 9789 | break; | |
| 199 | 26263044 | case FREE_LENGTH_CHECK: | |
| 200 | 26263044 | curr_length ++; | |
| 201 |
2/2✓ Branch 0 taken 26207722 times.
✓ Branch 1 taken 55322 times.
|
26263044 | if (curr_length > max_length) max_length = curr_length; |
| 202 | 26263044 | state = FREE_LENGTH_CHECK; | |
| 203 | 26263044 | break; | |
| 204 | 7267143 | case SKIP: | |
| 205 | 7267143 | break; | |
| 206 | } | ||
| 207 | 33539976 | break; | |
| 208 | 121351 | case END: | |
| 209 | 121351 | state = INIT; | |
| 210 | 121351 | break; | |
| 211 | 121351 | case START: | |
| 212 | 121351 | state = SKIP; | |
| 213 | 121351 | break; | |
| 214 | 9578 | default: // START_END | |
| 215 | 9578 | state = INIT; | |
| 216 | 9578 | break; | |
| 217 | } | ||
| 218 | } | ||
| 219 | 8287 | mutex_unlock(&lbm_mem_mutex); | |
| 220 |
2/2✓ Branch 0 taken 8285 times.
✓ Branch 1 taken 2 times.
|
8287 | if (memory_num_free - max_length < memory_reserve_level) { |
| 221 | 8285 | lbm_uint n = memory_reserve_level - (memory_num_free - max_length); | |
| 222 | 8285 | max_length -= n; | |
| 223 | } | ||
| 224 | 8287 | return max_length; | |
| 225 | } | ||
| 226 | |||
| 227 | 12424397 | static lbm_uint *lbm_memory_allocate_internal(lbm_uint num_words) { | |
| 228 | |||
| 229 |
3/4✓ Branch 0 taken 12424396 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12424396 times.
|
12424397 | if (memory == NULL || bitmap == NULL) { |
| 230 | 1 | return NULL; | |
| 231 | } | ||
| 232 | |||
| 233 | 12424396 | mutex_lock(&lbm_mem_mutex); | |
| 234 | |||
| 235 | 12424396 | lbm_uint start_ix = 0; | |
| 236 | 12424396 | lbm_uint end_ix = 0; | |
| 237 | 12424396 | lbm_uint free_length = 0; | |
| 238 | 12424396 | unsigned int state = INIT; | |
| 239 | 12424396 | lbm_uint loop_max = (bitmap_size << BITMAP_SIZE_SHIFT); | |
| 240 | |||
| 241 |
2/2✓ Branch 0 taken 165246318 times.
✓ Branch 1 taken 8517 times.
|
165254835 | for (lbm_uint i = 0; i < loop_max; i ++) { |
| 242 |
4/4✓ Branch 0 taken 152699162 times.
✓ Branch 1 taken 12195526 times.
✓ Branch 2 taken 122594 times.
✓ Branch 3 taken 229036 times.
|
165246318 | switch(status(alloc_offset)) { |
| 243 | 152699162 | case FREE_OR_USED: | |
| 244 |
3/4✓ Branch 0 taken 12431704 times.
✓ Branch 1 taken 111708337 times.
✓ Branch 2 taken 28559121 times.
✗ Branch 3 not taken.
|
152699162 | switch (state) { |
| 245 | 12431704 | case INIT: | |
| 246 | 12431704 | start_ix = alloc_offset; | |
| 247 |
2/2✓ Branch 0 taken 223838 times.
✓ Branch 1 taken 12207866 times.
|
12431704 | if (num_words == 1) { |
| 248 | 223838 | end_ix = alloc_offset; | |
| 249 | 223838 | state = ALLOC_DONE; | |
| 250 | } else { | ||
| 251 | 12207866 | state = FREE_LENGTH_CHECK; | |
| 252 | 12207866 | free_length = 1; | |
| 253 | } | ||
| 254 | 12431704 | break; | |
| 255 | 111708337 | case FREE_LENGTH_CHECK: | |
| 256 | 111708337 | free_length ++; | |
| 257 |
2/2✓ Branch 0 taken 12192041 times.
✓ Branch 1 taken 99516296 times.
|
111708337 | if (free_length == num_words) { |
| 258 | 12192041 | end_ix = alloc_offset; | |
| 259 | 12192041 | state = ALLOC_DONE; | |
| 260 | } else { | ||
| 261 | 99516296 | state = FREE_LENGTH_CHECK; | |
| 262 | } | ||
| 263 | 111708337 | break; | |
| 264 | 28559121 | case SKIP: | |
| 265 | 28559121 | break; | |
| 266 | } | ||
| 267 | 152699162 | break; | |
| 268 | 12195526 | case END: | |
| 269 | 12195526 | state = INIT; | |
| 270 | 12195526 | break; | |
| 271 | 122594 | case START: | |
| 272 | 122594 | state = SKIP; | |
| 273 | 122594 | break; | |
| 274 | 229036 | default: // START_END | |
| 275 | 229036 | state = INIT; | |
| 276 | 229036 | break; | |
| 277 | } | ||
| 278 | |||
| 279 |
2/2✓ Branch 0 taken 12415879 times.
✓ Branch 1 taken 152830439 times.
|
165246318 | if (state == ALLOC_DONE) break; |
| 280 | |||
| 281 | 152830439 | alloc_offset++; | |
| 282 |
2/2✓ Branch 0 taken 8527 times.
✓ Branch 1 taken 152821912 times.
|
152830439 | if (alloc_offset == loop_max ) { |
| 283 | 8527 | free_length = 0; | |
| 284 | 8527 | alloc_offset = 0; | |
| 285 | 8527 | state = INIT; | |
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 |
2/2✓ Branch 0 taken 12415879 times.
✓ Branch 1 taken 8517 times.
|
12424396 | if (state == ALLOC_DONE) { |
| 290 |
2/2✓ Branch 0 taken 223838 times.
✓ Branch 1 taken 12192041 times.
|
12415879 | if (start_ix == end_ix) { |
| 291 | 223838 | set_status(start_ix, START_END); | |
| 292 | } else { | ||
| 293 | 12192041 | set_status(start_ix, START); | |
| 294 | 12192041 | set_status(end_ix, END); | |
| 295 | } | ||
| 296 | 12415879 | memory_num_free -= num_words; | |
| 297 | 12415879 | mutex_unlock(&lbm_mem_mutex); | |
| 298 | 12415879 | return bitmap_ix_to_address(start_ix); | |
| 299 | } | ||
| 300 | 8517 | mutex_unlock(&lbm_mem_mutex); | |
| 301 | 8517 | return NULL; | |
| 302 | } | ||
| 303 | |||
| 304 | 94768 | lbm_uint *lbm_memory_allocate(lbm_uint num_words) { | |
| 305 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 94767 times.
|
94768 | if (memory_num_free - num_words < memory_reserve_level) { |
| 306 | 1 | lbm_request_gc(); | |
| 307 | 1 | return NULL; | |
| 308 | } | ||
| 309 | 94767 | return lbm_memory_allocate_internal(num_words); | |
| 310 | } | ||
| 311 | |||
| 312 | 12176460 | int lbm_memory_free(lbm_uint *ptr) { | |
| 313 | 12176460 | int r = 0; | |
| 314 |
2/2✓ Branch 0 taken 12078974 times.
✓ Branch 1 taken 97486 times.
|
12176460 | if (lbm_memory_ptr_inside(ptr)) { |
| 315 | 12078974 | mutex_lock(&lbm_mem_mutex); | |
| 316 | 12078974 | lbm_uint ix = address_to_bitmap_ix(ptr); | |
| 317 | 12078974 | lbm_uint count_freed = 0; | |
| 318 | 12078974 | alloc_offset = ix; | |
| 319 |
3/3✓ Branch 0 taken 11875644 times.
✓ Branch 1 taken 203328 times.
✓ Branch 2 taken 2 times.
|
12078974 | switch(status(ix)) { |
| 320 | 11875644 | case START: | |
| 321 | 11875644 | set_status(ix, FREE_OR_USED); | |
| 322 |
1/2✓ Branch 0 taken 76031549 times.
✗ Branch 1 not taken.
|
76031549 | for (lbm_uint i = ix; i < (bitmap_size << BITMAP_SIZE_SHIFT); i ++) { |
| 323 | 76031549 | count_freed ++; | |
| 324 |
2/2✓ Branch 0 taken 11875644 times.
✓ Branch 1 taken 64155905 times.
|
76031549 | if (status(i) == END) { |
| 325 | 11875644 | set_status(i, FREE_OR_USED); | |
| 326 | 11875644 | r = 1; | |
| 327 | 11875644 | break; | |
| 328 | } | ||
| 329 | } | ||
| 330 | 11875644 | break; | |
| 331 | 203328 | case START_END: | |
| 332 | 203328 | set_status(ix, FREE_OR_USED); | |
| 333 | 203328 | count_freed = 1; | |
| 334 | 203328 | r = 1; | |
| 335 | 203328 | break; | |
| 336 | 2 | default: | |
| 337 | 2 | break; | |
| 338 | } | ||
| 339 |
2/2✓ Branch 0 taken 12078972 times.
✓ Branch 1 taken 2 times.
|
12078974 | if (r) { |
| 340 |
4/4✓ Branch 0 taken 184185968 times.
✓ Branch 1 taken 1235 times.
✓ Branch 2 taken 172108231 times.
✓ Branch 3 taken 12077737 times.
|
184187203 | while (alloc_offset > 0 && status(alloc_offset - 1) == FREE_OR_USED) { |
| 341 | 172108231 | alloc_offset--; | |
| 342 | } | ||
| 343 | } | ||
| 344 | 12078974 | memory_num_free += count_freed; | |
| 345 | 12078974 | mutex_unlock(&lbm_mem_mutex); | |
| 346 | } | ||
| 347 | 12176460 | return r; | |
| 348 | } | ||
| 349 | //Malloc/free like interface | ||
| 350 | 12235716 | void* lbm_malloc(size_t size) { | |
| 351 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12235715 times.
|
12235716 | if (size == 0) return NULL; |
| 352 | lbm_uint alloc_size; | ||
| 353 | |||
| 354 | 12235715 | alloc_size = size / sizeof(lbm_uint); | |
| 355 |
2/2✓ Branch 0 taken 480510 times.
✓ Branch 1 taken 11755205 times.
|
12235715 | if (size % sizeof(lbm_uint)) alloc_size += 1; |
| 356 | |||
| 357 |
2/2✓ Branch 0 taken 7418 times.
✓ Branch 1 taken 12228297 times.
|
12235715 | if (memory_num_free - alloc_size < memory_reserve_level) { |
| 358 | 7418 | lbm_request_gc(); | |
| 359 | 7418 | return NULL; | |
| 360 | } | ||
| 361 | 12228297 | return lbm_memory_allocate_internal(alloc_size); | |
| 362 | } | ||
| 363 | |||
| 364 | 101334 | void* lbm_malloc_reserve(size_t size) { | |
| 365 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 101333 times.
|
101334 | if (size == 0) return NULL; |
| 366 | lbm_uint alloc_size; | ||
| 367 | |||
| 368 | 101333 | alloc_size = size / sizeof(lbm_uint); | |
| 369 |
2/2✓ Branch 0 taken 83620 times.
✓ Branch 1 taken 17713 times.
|
101333 | if (size % sizeof(lbm_uint)) alloc_size += 1; |
| 370 | |||
| 371 |
2/2✓ Branch 0 taken 186 times.
✓ Branch 1 taken 101147 times.
|
101333 | if (memory_num_free - alloc_size < memory_reserve_level) { |
| 372 | 186 | lbm_request_gc(); | |
| 373 | } | ||
| 374 | 101333 | return lbm_memory_allocate_internal(alloc_size); | |
| 375 | } | ||
| 376 | |||
| 377 | 78934 | void lbm_free(void *ptr) { | |
| 378 | 78934 | lbm_memory_free(ptr); | |
| 379 | 78934 | } | |
| 380 | |||
| 381 | 23026 | int lbm_memory_shrink(lbm_uint *ptr, lbm_uint n) { | |
| 382 |
4/4✓ Branch 0 taken 23023 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 23019 times.
|
23026 | if (!lbm_memory_ptr_inside(ptr) || n == 0) return 0; |
| 383 | |||
| 384 | 23019 | lbm_uint ix = address_to_bitmap_ix(ptr); | |
| 385 | |||
| 386 | 23019 | mutex_lock(&lbm_mem_mutex); | |
| 387 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23017 times.
|
23019 | if (status(ix) == START_END) { |
| 388 | 2 | mutex_unlock(&lbm_mem_mutex); | |
| 389 | 2 | return 1; // A one word arrays always succeeds at remaining at 1 word | |
| 390 | } | ||
| 391 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23017 times.
|
23017 | if (status(ix) != START) { |
| 392 | ✗ | mutex_unlock(&lbm_mem_mutex); | |
| 393 | ✗ | return 0; // ptr does not point to the start of an allocated range. | |
| 394 | } | ||
| 395 | |||
| 396 | 23017 | bool done = false; | |
| 397 | 23017 | unsigned int i = 0; | |
| 398 | |||
| 399 |
1/2✓ Branch 0 taken 186109 times.
✗ Branch 1 not taken.
|
186109 | for (i = 0; i < ((bitmap_size << BITMAP_SIZE_SHIFT) - ix); i ++) { |
| 400 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 186108 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
186109 | if (status(ix+i) == END && i < n) { |
| 401 | 1 | mutex_unlock(&lbm_mem_mutex); | |
| 402 | 1 | return 0; // cannot shrink allocation to a larger size | |
| 403 | } | ||
| 404 | |||
| 405 |
2/2✓ Branch 0 taken 23016 times.
✓ Branch 1 taken 163092 times.
|
186108 | if (i == (n-1)) { |
| 406 |
2/4✓ Branch 0 taken 23016 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23016 times.
|
46032 | if (status(ix+i) == END || |
| 407 | 23016 | status(ix+i) == START_END) { | |
| 408 | ✗ | done = true; | |
| 409 | } | ||
| 410 |
2/2✓ Branch 0 taken 5188 times.
✓ Branch 1 taken 17828 times.
|
23016 | if (i == 0) { |
| 411 | 5188 | set_status(ix+i, START_END); | |
| 412 | } | ||
| 413 | else { | ||
| 414 | 17828 | set_status(ix+i, END); | |
| 415 | } | ||
| 416 | 23016 | break; | |
| 417 | } | ||
| 418 | } | ||
| 419 | 23016 | alloc_offset = ix+i; | |
| 420 | |||
| 421 | 23016 | lbm_uint count = 0; | |
| 422 |
1/2✓ Branch 0 taken 23016 times.
✗ Branch 1 not taken.
|
23016 | if (!done) { |
| 423 | 23016 | i++; // move to next position, prev position should be END or START_END | |
| 424 |
1/2✓ Branch 0 taken 19358563 times.
✗ Branch 1 not taken.
|
19358563 | for (;i < ((bitmap_size << BITMAP_SIZE_SHIFT) - ix); i ++) { |
| 425 | 19358563 | count ++; | |
| 426 |
2/2✓ Branch 0 taken 23016 times.
✓ Branch 1 taken 19335547 times.
|
19358563 | if (status(ix+i) == END) { |
| 427 | 23016 | set_status(ix+i, FREE_OR_USED); | |
| 428 | 23016 | break; | |
| 429 | } | ||
| 430 | } | ||
| 431 | } | ||
| 432 | |||
| 433 | 23016 | memory_num_free += count; | |
| 434 | 23016 | mutex_unlock(&lbm_mem_mutex); | |
| 435 | 23016 | return 1; | |
| 436 | } | ||
| 437 | |||
| 438 | 12204963 | int lbm_memory_ptr_inside(lbm_uint *ptr) { | |
| 439 |
2/2✓ Branch 0 taken 12102017 times.
✓ Branch 1 taken 102946 times.
|
24306980 | return ((lbm_uint)ptr >= (lbm_uint)memory && |
| 440 |
2/2✓ Branch 0 taken 12102008 times.
✓ Branch 1 taken 9 times.
|
12102017 | (lbm_uint)ptr < (lbm_uint)memory + (memory_size * sizeof(lbm_uint))); |
| 441 | } | ||
| 442 |