buflib: optimize getting start of block from end of block

The block header has a variable length due to the embedded name.
The name length is stored at the back of the header after the
name, in order to allow finding the start of the header if only
the user data pointer is known (eg. from the handle table).

The name length is actually not interesting in itself; storing
the total length of the block header instead is marginally more
efficient, saving one addition in handle_to_block().

Instead the extra arithmetic must be done by buflib_get_name(),
which is a much less common operation than handle_to_block().

Change-Id: Ia339a1d2f556a11a49deae0871203e70548bd234
This commit is contained in:
Aidan MacDonald 2022-03-30 01:29:19 +01:00
parent ef476ba298
commit fdde6bb5a7

View file

@ -65,7 +65,7 @@
* H - handle table entry pointer * H - handle table entry pointer
* C - pointer to struct buflib_callbacks * C - pointer to struct buflib_callbacks
* c - variable sized string identifier * c - variable sized string identifier
* L2 - second length marker for string identifier * L2 - length of the metadata
* crc - crc32 protecting buflib metadata integrity * crc - crc32 protecting buflib metadata integrity
* X - actual payload * X - actual payload
* Y - unallocated space * Y - unallocated space
@ -240,8 +240,8 @@ union buflib_data* handle_to_block(struct buflib_context* ctx, int handle)
* has already been allocated but not the data */ * has already been allocated but not the data */
if (!data) if (!data)
return NULL; return NULL;
volatile size_t len = data[-2].val;
return data - (len + 4); return data - data[-2].val;
} }
/* Shrink the handle table, returning true if its size was reduced, false if /* Shrink the handle table, returning true if its size was reduced, false if
@ -627,15 +627,15 @@ buffer_alloc:
/* Set up the allocated block, by marking the size allocated, and storing /* Set up the allocated block, by marking the size allocated, and storing
* a pointer to the handle. * a pointer to the handle.
*/ */
union buflib_data *name_len_slot, *crc_slot; union buflib_data *header_size_slot, *crc_slot;
block->val = size; block->val = size;
block[1].handle = handle; block[1].handle = handle;
block[2].ops = ops; block[2].ops = ops;
if (name_len > 0) if (name_len > 0)
strcpy(block[3].name, name); strcpy(block[3].name, name);
name_len_slot = (union buflib_data*)B_ALIGN_UP(block[3].name + name_len); header_size_slot = (union buflib_data*)B_ALIGN_UP(block[3].name + name_len);
name_len_slot->val = 1 + name_len/sizeof(union buflib_data); header_size_slot->val = 5 + name_len/sizeof(union buflib_data);
crc_slot = (union buflib_data*)(name_len_slot + 1); crc_slot = (union buflib_data*)(header_size_slot + 1);
crc_slot->crc = crc_32((void *)block, crc_slot->crc = crc_32((void *)block,
(crc_slot - block)*sizeof(union buflib_data), (crc_slot - block)*sizeof(union buflib_data),
0xffffffff); 0xffffffff);
@ -742,7 +742,7 @@ static size_t
free_space_at_end(struct buflib_context* ctx) free_space_at_end(struct buflib_context* ctx)
{ {
/* subtract 5 elements for /* subtract 5 elements for
* val, handle, name_len, ops and the handle table entry*/ * val, handle, meta_len, ops and the handle table entry*/
ptrdiff_t diff = (ctx->last_handle - ctx->alloc_end - 5); ptrdiff_t diff = (ctx->last_handle - ctx->alloc_end - 5);
diff -= 16; /* space for future handles */ diff -= 16; /* space for future handles */
diff *= sizeof(union buflib_data); /* make it bytes */ diff *= sizeof(union buflib_data); /* make it bytes */
@ -933,9 +933,11 @@ const char* buflib_get_name(struct buflib_context *ctx, int handle)
{ {
union buflib_data *data = ALIGN_DOWN(buflib_get_data(ctx, handle), sizeof (*data)); union buflib_data *data = ALIGN_DOWN(buflib_get_data(ctx, handle), sizeof (*data));
size_t len = data[-2].val; size_t len = data[-2].val;
if (len <= 1) if (len <= 5)
return NULL; return NULL;
return data[-len-1].name;
data -= len;
return data[3].name;
} }
#ifdef DEBUG #ifdef DEBUG