Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Address some weaknesses and bugs of buflib_compact() and make the code prettier. Thanks to Boris Gjenero for his great investigation.

Flyspray: FS#12409
Author: myself

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31101 a1c6a512-1295-4272-9138-f99709370657

+36 -24
+36 -24
firmware/buflib.c
··· 237 237 { 238 238 BDEBUGF("%s(): Compacting!\n", __func__); 239 239 union buflib_data *block, 240 - *first_free = find_first_free(ctx); 240 + *hole = NULL; 241 241 int shift = 0, len; 242 242 /* Store the results of attempting to shrink the handle table */ 243 243 bool ret = handle_table_shrink(ctx); 244 - for(block = first_free; block < ctx->alloc_end; block += len) 244 + /* compaction has basically two modes of operation: 245 + * 1) the buffer is nicely movable: In this mode, blocks can be simply 246 + * moved towards the beginning. Free blocks add to a shift value, 247 + * which is the amount to move. 248 + * 2) the buffer contains unmovable blocks: unmovable blocks create 249 + * holes and reset shift. Once a hole is found, we're trying to fill 250 + * holes first, moving by shift is the fallback. As the shift is reset, 251 + * this effectively splits the buffer into portions of movable blocks. 252 + * This mode cannot be used if no holes are found yet as it only works 253 + * when it moves blocks across the portions. On the other side, 254 + * moving by shift only works within the same portion 255 + * For simplicity only 1 hole at a time is considered */ 256 + for(block = find_first_free(ctx); block < ctx->alloc_end; block += len) 245 257 { 258 + bool movable = true; /* cache result to avoid 2nd call to move_block */ 246 259 len = block->val; 247 260 /* This block is free, add its length to the shift value */ 248 261 if (len < 0) ··· 252 265 continue; 253 266 } 254 267 /* attempt to fill any hole */ 255 - if (-first_free->val >= block->val) 268 + if (hole && -hole->val >= len) 256 269 { 257 - intptr_t size = -first_free->val; 258 - union buflib_data* next_block = block + block->val; 259 - if (move_block(ctx, block, first_free - block)) 270 + intptr_t hlen = -hole->val; 271 + if ((movable = move_block(ctx, block, hole - block))) 260 272 { 261 - /* moving was successful. Move alloc_end down if necessary */ 262 - if (ctx->alloc_end == next_block) 263 - ctx->alloc_end = block; 264 - /* Mark the block behind the just moved as free 265 - * be careful to not overwrite an existing block */ 266 - if (size != block->val) 273 + ret = true; 274 + /* Move was successful. The memory at block is now free */ 275 + block->val = -len; 276 + /* add its length to shift */ 277 + shift += -len; 278 + /* Reduce the size of the hole accordingly 279 + * but be careful to not overwrite an existing block */ 280 + if (hlen != len) 267 281 { 268 - first_free += block->val; 269 - first_free->val = block->val - size; /* negative */ 282 + hole += len; 283 + hole->val = len - hlen; /* negative */ 270 284 } 271 - continue; 285 + else /* hole closed */ 286 + hole = NULL; 272 287 } 273 288 } 274 289 /* attempt move the allocation by shift */ 275 290 if (shift) 276 291 { 277 - /* failing to move creates a hole, 278 - * therefore mark this block as not allocated */ 279 292 union buflib_data* target_block = block + shift; 280 - if (!move_block(ctx, block, shift)) 293 + if (!movable || !move_block(ctx, block, shift)) 281 294 { 282 - target_block->val = shift; /* this is a hole */ 295 + /* free space before an unmovable block becomes a hole, 296 + * therefore mark this block free and track the hole */ 297 + target_block->val = shift; 298 + hole = target_block; 283 299 shift = 0; 284 300 } 285 301 else 286 - { /* need to update the next free block, since the above hole 287 - * handling might make shift 0 before alloc_end is reached */ 288 - union buflib_data* new_free = target_block + target_block->val; 289 - new_free->val = shift; 290 - } 302 + ret = true; 291 303 } 292 304 } 293 305 /* Move the end-of-allocation mark, and return true if any new space has