From 64b9e1fa7b645daa36ca0018dc168d4f871fd538 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Thu, 21 Nov 2013 11:40:04 +0100 Subject: 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 --- firmware/buflib.c | 26 ++++++++++++++++++++++++++ firmware/include/buflib.h | 15 +++++++++++++++ 2 files changed, 41 insertions(+) (limited to 'firmware') diff --git a/firmware/buflib.c b/firmware/buflib.c index 4233bf9a61..d7a24b8722 100644 --- a/firmware/buflib.c +++ b/firmware/buflib.c @@ -117,6 +117,32 @@ buflib_init(struct buflib_context *ctx, void *buf, size_t size) (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 */ static inline union buflib_data* handle_alloc(struct buflib_context *ctx) diff --git a/firmware/include/buflib.h b/firmware/include/buflib.h index aa6c232f72..0b26c04bcd 100644 --- a/firmware/include/buflib.h +++ b/firmware/include/buflib.h @@ -157,6 +157,21 @@ size_t buflib_available(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 -- cgit v1.2.3