Index: firmware/buflib.c =================================================================== --- firmware/buflib.c (revision 31066) +++ firmware/buflib.c (working copy) @@ -375,6 +375,24 @@ handle->alloc += shift; } +static void +merge_free_blocks(struct buflib_context *ctx, union buflib_data *block) +{ + union buflib_data *next_block; + next_block = block - block->val; + /* Check if we are merging with the free space at alloc_end. */ + if (next_block == ctx->alloc_end) + ctx->alloc_end = block; + /* Otherwise, the next block might still be a "normal" free block, and the + * mid-allocation free means that the buffer is no longer compact. + */ + else { + ctx->compact = false; + if (next_block->val < 0) + block->val += next_block->val; + } +} + /* Shift buffered items up by size bytes, or as many as possible if size == 0. * Set size to the number of bytes freed. */ @@ -397,12 +415,21 @@ return ret; } -/* Shift buffered items down by size bytes */ +/* Extend managed area by adding more space at the start. */ void buflib_buffer_in(struct buflib_context *ctx, int size) { + union buflib_data *block; + size /= sizeof(union buflib_data); - buflib_buffer_shift(ctx, -size); + + /* Move buf_start backwards and create a + * free block spanning the newly added area */ + ctx->buf_start -= size; + block = ctx->buf_start; + block->val = -size; + + merge_free_blocks(ctx, block); } /* Allocate a buffer of size bytes, returning a handle for it */ @@ -580,7 +607,7 @@ { union buflib_data *handle = ctx->handle_table - handle_num, *freed_block = handle_to_block(ctx, handle_num), - *block, *next_block; + *block; /* We need to find the block before the current one, to see if it is free * and can be merged with this one. */ @@ -598,18 +625,7 @@ block = freed_block; block->val = -block->val; } - next_block = block - block->val; - /* Check if we are merging with the free space at alloc_end. */ - if (next_block == ctx->alloc_end) - ctx->alloc_end = block; - /* Otherwise, the next block might still be a "normal" free block, and the - * mid-allocation free means that the buffer is no longer compact. - */ - else { - ctx->compact = false; - if (next_block->val < 0) - block->val += next_block->val; - } + merge_free_blocks(ctx, block); handle_free(ctx, handle); handle->alloc = NULL;