forked from len0rd/rockbox
buflib: Add buflib_context_relocate().
This function relocates a buflib back buffer, updating pointers in struct buflib_context. It does not move any data by itself. The intended use-case is buflib-on-buflib, where a buflib back buffer is allocated with buflib and attempted to be moved. The move_callback() can call this and return BUFLIB_CB_OK on success. No move_callback() is called for the subordinate buflib buffer, therefore it must not contain non-movable allocations. The caller is generally responsible moving the data and all its implications. Change-Id: I869219f9cff786a172c9e917a5f34470073892e6
This commit is contained in:
parent
d25a512caf
commit
64b9e1fa7b
2 changed files with 41 additions and 0 deletions
|
|
@ -117,6 +117,32 @@ buflib_init(struct buflib_context *ctx, void *buf, size_t size)
|
||||||
(unsigned long)size / 1024, ((unsigned long)size%1000)/10);
|
(unsigned long)size / 1024, ((unsigned long)size%1000)/10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool buflib_context_relocate(struct buflib_context *ctx, void *buf)
|
||||||
|
{
|
||||||
|
union buflib_data *handle, *bd_buf = buf;
|
||||||
|
ptrdiff_t diff = bd_buf - ctx->buf_start;
|
||||||
|
|
||||||
|
/* cannot continue if the buffer is not aligned, since we would need
|
||||||
|
* to reduce the size of the buffer for aligning */
|
||||||
|
if ((uintptr_t)buf & 0x3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* relocate the handle table entries */
|
||||||
|
for (handle = ctx->last_handle; handle < ctx->handle_table; handle++)
|
||||||
|
{
|
||||||
|
if (handle->alloc)
|
||||||
|
handle->alloc += diff * sizeof(union buflib_data);
|
||||||
|
}
|
||||||
|
/* relocate the pointers in the context */
|
||||||
|
ctx->handle_table += diff;
|
||||||
|
ctx->last_handle += diff;
|
||||||
|
ctx->first_free_handle += diff;
|
||||||
|
ctx->buf_start += diff;
|
||||||
|
ctx->alloc_end += diff;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate a new handle, returning 0 on failure */
|
/* Allocate a new handle, returning 0 on failure */
|
||||||
static inline
|
static inline
|
||||||
union buflib_data* handle_alloc(struct buflib_context *ctx)
|
union buflib_data* handle_alloc(struct buflib_context *ctx)
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,21 @@ size_t buflib_available(struct buflib_context *ctx);
|
||||||
*/
|
*/
|
||||||
size_t buflib_allocatable(struct buflib_context *ctx);
|
size_t buflib_allocatable(struct buflib_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relocates the fields in *ctx to the new buffer position pointed to by buf.
|
||||||
|
* This does _not_ move any data but updates the pointers. The data has
|
||||||
|
* to be moved afterwards manually and only if this function returned true.
|
||||||
|
*
|
||||||
|
* This is intended to be called from within a move_callback(), for
|
||||||
|
* buflib-on-buflib scenarios (i.e. a new buflib instance backed by a buffer
|
||||||
|
* that was allocated by another buflib instance). Be aware that if the parent
|
||||||
|
* move_callback() moves the underlying buffer _no_ move_callback() of the
|
||||||
|
* underlying buffer are called.
|
||||||
|
*
|
||||||
|
* Returns true of the relocation was successful. If it returns false no
|
||||||
|
* change to *ctx was made.
|
||||||
|
*/
|
||||||
|
bool buflib_context_relocate(struct buflib_context *ctx, void *buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates memory from buflib's memory pool
|
* Allocates memory from buflib's memory pool
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue