summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2013-11-21 11:40:04 +0100
committerThomas Martitz <kugel@rockbox.org>2013-12-22 23:11:32 +0100
commit64b9e1fa7b645daa36ca0018dc168d4f871fd538 (patch)
tree207a693773d001307c5f3247fd435f9bc65a192c /firmware
parentd25a512caf4adf2aac3ce6ac8e1f2c556c0c6c37 (diff)
downloadrockbox-64b9e1fa7b645daa36ca0018dc168d4f871fd538.tar.gz
rockbox-64b9e1fa7b645daa36ca0018dc168d4f871fd538.zip
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
Diffstat (limited to 'firmware')
-rw-r--r--firmware/buflib.c26
-rw-r--r--firmware/include/buflib.h15
2 files changed, 41 insertions, 0 deletions
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)
117 (unsigned long)size / 1024, ((unsigned long)size%1000)/10); 117 (unsigned long)size / 1024, ((unsigned long)size%1000)/10);
118} 118}
119 119
120bool buflib_context_relocate(struct buflib_context *ctx, void *buf)
121{
122 union buflib_data *handle, *bd_buf = buf;
123 ptrdiff_t diff = bd_buf - ctx->buf_start;
124
125 /* cannot continue if the buffer is not aligned, since we would need
126 * to reduce the size of the buffer for aligning */
127 if ((uintptr_t)buf & 0x3)
128 return false;
129
130 /* relocate the handle table entries */
131 for (handle = ctx->last_handle; handle < ctx->handle_table; handle++)
132 {
133 if (handle->alloc)
134 handle->alloc += diff * sizeof(union buflib_data);
135 }
136 /* relocate the pointers in the context */
137 ctx->handle_table += diff;
138 ctx->last_handle += diff;
139 ctx->first_free_handle += diff;
140 ctx->buf_start += diff;
141 ctx->alloc_end += diff;
142
143 return true;
144}
145
120/* Allocate a new handle, returning 0 on failure */ 146/* Allocate a new handle, returning 0 on failure */
121static inline 147static inline
122union buflib_data* handle_alloc(struct buflib_context *ctx) 148union 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);
157 */ 157 */
158size_t buflib_allocatable(struct buflib_context *ctx); 158size_t buflib_allocatable(struct buflib_context *ctx);
159 159
160/**
161 * Relocates the fields in *ctx to the new buffer position pointed to by buf.
162 * This does _not_ move any data but updates the pointers. The data has
163 * to be moved afterwards manually and only if this function returned true.
164 *
165 * This is intended to be called from within a move_callback(), for
166 * buflib-on-buflib scenarios (i.e. a new buflib instance backed by a buffer
167 * that was allocated by another buflib instance). Be aware that if the parent
168 * move_callback() moves the underlying buffer _no_ move_callback() of the
169 * underlying buffer are called.
170 *
171 * Returns true of the relocation was successful. If it returns false no
172 * change to *ctx was made.
173 */
174bool buflib_context_relocate(struct buflib_context *ctx, void *buf);
160 175
161/** 176/**
162 * Allocates memory from buflib's memory pool 177 * Allocates memory from buflib's memory pool