summaryrefslogtreecommitdiff
path: root/firmware/chunk_alloc.c
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2023-01-16 01:14:15 -0500
committerWilliam Wilgus <me.theuser@yahoo.com>2023-01-19 00:04:25 -0500
commit1b383ef4804a29a78927f193f978f2efa8636eff (patch)
treee33c775b0382205183c89e75ffbed0f88f57352b /firmware/chunk_alloc.c
parentbd7b54a3c4f12793f855a7e2885b318edba7b06e (diff)
downloadrockbox-1b383ef4804a29a78927f193f978f2efa8636eff.tar.gz
rockbox-1b383ef4804a29a78927f193f978f2efa8636eff.zip
chunk alloc add buflib_get_pinned and chunk caching
Change-Id: Ia581656793b8ce9b80545705cfbba0fb225bb616
Diffstat (limited to 'firmware/chunk_alloc.c')
-rw-r--r--firmware/chunk_alloc.c125
1 files changed, 70 insertions, 55 deletions
diff --git a/firmware/chunk_alloc.c b/firmware/chunk_alloc.c
index 85ad5d3489..30959e393d 100644
--- a/firmware/chunk_alloc.c
+++ b/firmware/chunk_alloc.c
@@ -40,17 +40,22 @@
40 * offset / sizeof(data) or index * sizeof(data) to convert 40 * offset / sizeof(data) or index * sizeof(data) to convert
41 */ 41 */
42 42
43struct chunk 43struct chunk_alloc
44{ 44{
45 int handle; /* data handle of buflib allocated bytes */ 45 int handle; /* data handle of buflib allocated bytes */
46 size_t max_start_offset; /* start of last allocation */ 46 size_t max_start_offset; /* start of last allocation */
47}; 47};
48 48
49#define CHUNK_ARRSZ(n) (sizeof(struct chunk) * n) 49#define CHUNK_ARRSZ(n) (sizeof(struct chunk_alloc) * n)
50 50
51static struct chunk* get_chunk_array(struct buflib_context *ctx, int handle) 51static struct chunk_alloc* get_chunk_array(struct buflib_context *ctx, int handle)
52{ 52{
53 return (struct chunk*)buflib_get_data(ctx, handle); 53 return (struct chunk_alloc*)buflib_get_data_pinned(ctx, handle);
54}
55
56static void put_chunk_array(struct buflib_context *ctx, struct chunk_alloc *data)
57{
58 buflib_put_data_pinned(ctx, data);
54} 59}
55 60
56/* shrink or grow chunk allocation 61/* shrink or grow chunk allocation
@@ -63,8 +68,8 @@ bool chunk_realloc(struct chunk_alloc_header *hdr,
63 size_t chunk_size, size_t max_chunks) 68 size_t chunk_size, size_t max_chunks)
64{ 69{
65 struct buflib_context *ctx = hdr->context; 70 struct buflib_context *ctx = hdr->context;
66 struct chunk *new_chunk = NULL; 71 struct chunk_alloc *new_chunk = NULL;
67 struct chunk *old_chunk; 72 struct chunk_alloc *old_chunk;
68 size_t min_chunk = 1; 73 size_t min_chunk = 1;
69 int new_handle = 0; 74 int new_handle = 0;
70 75
@@ -83,10 +88,8 @@ bool chunk_realloc(struct chunk_alloc_header *hdr,
83 } 88 }
84 if (hdr->chunk_handle > 0) /* handle existing chunk */ 89 if (hdr->chunk_handle > 0) /* handle existing chunk */
85 { 90 {
86 logf("%s %ld chunks (%ld bytes) => %ld chunks (%ld bytes)", __func__, 91 logf("%s %ld chunks => %ld chunks", __func__, hdr->count, max_chunks);
87 hdr->count, CHUNK_ARRSZ(hdr->count), max_chunks, CHUNK_ARRSZ(max_chunks));
88 92
89 buflib_pin(ctx, hdr->chunk_handle);
90 old_chunk = get_chunk_array(ctx, hdr->chunk_handle); 93 old_chunk = get_chunk_array(ctx, hdr->chunk_handle);
91 94
92 if (new_chunk != NULL) /* copy any valid old chunks to new */ 95 if (new_chunk != NULL) /* copy any valid old chunks to new */
@@ -94,6 +97,7 @@ bool chunk_realloc(struct chunk_alloc_header *hdr,
94 min_chunk = MIN(max_chunks, hdr->current + 1); 97 min_chunk = MIN(max_chunks, hdr->current + 1);
95 logf("%s copying %ld chunks", __func__, min_chunk); 98 logf("%s copying %ld chunks", __func__, min_chunk);
96 memcpy(new_chunk, old_chunk, CHUNK_ARRSZ(min_chunk)); 99 memcpy(new_chunk, old_chunk, CHUNK_ARRSZ(min_chunk));
100 put_chunk_array(ctx, new_chunk);
97 } 101 }
98 /* free any chunks that no longer fit */ 102 /* free any chunks that no longer fit */
99 for (size_t i = max_chunks; i <= hdr->current; i++) 103 for (size_t i = max_chunks; i <= hdr->current; i++)
@@ -101,7 +105,7 @@ bool chunk_realloc(struct chunk_alloc_header *hdr,
101 logf("%s discarding chunk[%ld]", __func__, i); 105 logf("%s discarding chunk[%ld]", __func__, i);
102 buflib_free(ctx, old_chunk[i].handle); 106 buflib_free(ctx, old_chunk[i].handle);
103 } 107 }
104 buflib_unpin(ctx, hdr->chunk_handle); 108 put_chunk_array(ctx, old_chunk);
105 109
106 if (max_chunks < hdr->count && max_chunks > 0) 110 if (max_chunks < hdr->count && max_chunks > 0)
107 { 111 {
@@ -122,10 +126,9 @@ bool chunk_realloc(struct chunk_alloc_header *hdr,
122 } 126 }
123 else 127 else
124 { 128 {
125 logf("chunk_alloc_init %ld chunks (%ld bytes)", 129 logf("chunk_alloc_init %ld chunks", hdr->count);
126 hdr->count, (hdr->count));
127 } 130 }
128 131 hdr->cached_chunk.handle = 0; /* reset last chunk to force new lookup */
129 hdr->chunk_handle = new_handle; 132 hdr->chunk_handle = new_handle;
130 hdr->chunk_size = chunk_size; 133 hdr->chunk_size = chunk_size;
131 hdr->count = max_chunks; 134 hdr->count = max_chunks;
@@ -152,20 +155,16 @@ bool chunk_alloc_init(struct chunk_alloc_header *hdr,
152 size_t chunk_size, size_t max_chunks) 155 size_t chunk_size, size_t max_chunks)
153{ 156{
154 /* initialize header */ 157 /* initialize header */
155 hdr->chunk_handle = 0; 158 memset(hdr, 0, sizeof(struct chunk_alloc_header));
156 hdr->chunk_bytes_total = 0;
157 hdr->chunk_bytes_free = 0;
158 hdr->current = 0;
159 hdr->context = ctx; 159 hdr->context = ctx;
160 hdr->count = 0;
161 160
162 return chunk_realloc(hdr, chunk_size, max_chunks); 161 return chunk_realloc(hdr, chunk_size, max_chunks);
163} 162}
164 163
165/* shrink current chunk to size used */ 164/* shrink current chunk to size used */
166static void finalize(struct chunk_alloc_header *hdr, struct chunk *chunk_array) 165static void finalize(struct chunk_alloc_header *hdr, struct chunk_alloc *chunk_array)
167{ 166{
168 /*Note calling functions check if chunk_bytes_free > 0*/ 167 /* Note calling functions check if chunk_bytes_free > 0 */
169 size_t idx = hdr->current; 168 size_t idx = hdr->current;
170 if (idx >= hdr->count) 169 if (idx >= hdr->count)
171 return; 170 return;
@@ -186,8 +185,10 @@ void chunk_alloc_finalize(struct chunk_alloc_header *hdr)
186{ 185{
187 if (hdr->chunk_bytes_free > 0) 186 if (hdr->chunk_bytes_free > 0)
188 { 187 {
189 struct chunk *chunk = get_chunk_array(hdr->context, hdr->chunk_handle); 188 struct chunk_alloc *chunk;
189 chunk = get_chunk_array(hdr->context, hdr->chunk_handle);
190 finalize(hdr, chunk); 190 finalize(hdr, chunk);
191 put_chunk_array(hdr->context, chunk);
191 } 192 }
192} 193}
193 194
@@ -197,19 +198,19 @@ void chunk_alloc_finalize(struct chunk_alloc_header *hdr)
197*/ 198*/
198size_t chunk_alloc(struct chunk_alloc_header *hdr, size_t size) 199size_t chunk_alloc(struct chunk_alloc_header *hdr, size_t size)
199{ 200{
201 size_t virtual_offset = CHUNK_ALLOC_INVALID;
200 size_t idx = hdr->current; 202 size_t idx = hdr->current;
201 int handle = hdr->chunk_handle; 203 int handle = hdr->chunk_handle;
202 struct buflib_context *ctx = hdr->context; 204 struct buflib_context *ctx = hdr->context;
203 205
204 buflib_pin(ctx, handle); 206 struct chunk_alloc *chunk = get_chunk_array(ctx, handle);
205 struct chunk *chunk = get_chunk_array(ctx, handle);
206 207
207 while (size > 0) 208 while (size > 0)
208 { 209 {
209 if (idx >= hdr->count) 210 if (idx >= hdr->count)
210 { 211 {
211 logf("%s Error OOM -- out of chunks", __func__); 212 logf("%s Error OOM -- out of chunks", __func__);
212 break; 213 break; /* Out of chunks */
213 } 214 }
214 hdr->current = idx; 215 hdr->current = idx;
215 216
@@ -222,7 +223,7 @@ size_t chunk_alloc(struct chunk_alloc_header *hdr, size_t size)
222 if (chunk[idx].handle <= 0) 223 if (chunk[idx].handle <= 0)
223 { 224 {
224 logf("%s Error OOM", __func__); 225 logf("%s Error OOM", __func__);
225 goto fail; /* OOM */ 226 break; /* OOM */
226 } 227 }
227 228
228 hdr->chunk_bytes_total = new_alloc_size; 229 hdr->chunk_bytes_total = new_alloc_size;
@@ -237,14 +238,17 @@ size_t chunk_alloc(struct chunk_alloc_header *hdr, size_t size)
237 238
238 if(size <= hdr->chunk_bytes_free) /* request will fit */ 239 if(size <= hdr->chunk_bytes_free) /* request will fit */
239 { 240 {
240 size_t offset = chunk[idx].max_start_offset; 241 virtual_offset = chunk[idx].max_start_offset;
241 chunk[idx].max_start_offset += size; 242 chunk[idx].max_start_offset += size;
242 hdr->chunk_bytes_free -= size; 243 hdr->chunk_bytes_free -= size;
244
245 if (hdr->cached_chunk.handle == chunk[idx].handle)
246 hdr->cached_chunk.max_offset = chunk[idx].max_start_offset;
247
243 /*logf("%s hdr idx[%ld] offset[%ld] size: %ld", 248 /*logf("%s hdr idx[%ld] offset[%ld] size: %ld",
244 __func__, idx, offset, size);*/ 249 __func__, idx, offset, size);*/
245 250
246 buflib_unpin(ctx, handle); 251 break; /* Success */
247 return offset;
248 } 252 }
249 else if (hdr->chunk_bytes_free > 0) /* shrink the current chunk */ 253 else if (hdr->chunk_bytes_free > 0) /* shrink the current chunk */
250 { 254 {
@@ -252,26 +256,42 @@ size_t chunk_alloc(struct chunk_alloc_header *hdr, size_t size)
252 } 256 }
253 idx++; 257 idx++;
254 } 258 }
255fail: 259
256 buflib_unpin(ctx, handle); 260 put_chunk_array(ctx, chunk);
257 return CHUNK_ALLOC_INVALID; 261 return virtual_offset;
258} 262}
259 263
260/* returns chunk idx given virtual offset */ 264/* retrieves chunk given virtual offset
261static size_t chunk_find_data_idx(struct chunk_alloc_header *hdr, 265 * returns actual offset
262 size_t offset, struct chunk **chunk) 266*/
267static size_t chunk_get_at_offset(struct chunk_alloc_header *hdr, size_t offset)
263{ 268{
264 size_t idx; 269 if ((hdr->cached_chunk.handle > 0)
265 *chunk = get_chunk_array(hdr->context, hdr->chunk_handle); 270 && (offset >= hdr->cached_chunk.min_offset)
266 /*logf("%s search for offset[%ld]", __func__, offset);*/ 271 && (offset < hdr->cached_chunk.max_offset))
267 for (idx = hdr->current; idx < hdr->count; idx--) 272 {
273 /* convert virtual offset to real internal offset */
274 return offset - hdr->cached_chunk.min_offset;
275 }
276
277 /* chunk isn't cached perform new lookup */
278 struct chunk_alloc *chunk = get_chunk_array(hdr->context, hdr->chunk_handle);
279 logf("%s search for offset[%ld]", __func__, offset);
280 for (size_t idx = hdr->current; idx < hdr->count; idx--)
268 { 281 {
269 if (offset < (*chunk)[idx].max_start_offset 282 size_t min_offset = (idx == 0 ? 0 : chunk[idx - 1].max_start_offset);
270 && (idx == 0 || offset >= (*chunk)[idx - 1].max_start_offset)) 283 if (offset < chunk[idx].max_start_offset && offset >= min_offset)
271 { 284 {
272 /*logf("%s found hdr idx[%ld] max offset[%ld]", 285 logf("%s found hdr idx[%ld] min offset[%ld] max offset[%ld]",
273 __func__, idx, (*chunk)[idx].max_start_offset);*/ 286 __func__, idx, min_offset, chunk[idx].max_start_offset);
274 return idx; 287
288 /* store found chunk */
289 hdr->cached_chunk.handle = chunk[idx].handle;
290 hdr->cached_chunk.max_offset = chunk[idx].max_start_offset;
291 hdr->cached_chunk.min_offset = min_offset;
292 put_chunk_array(hdr->context, chunk);
293 /* convert virtual offset to real internal offset */
294 return offset - hdr->cached_chunk.min_offset;
275 } 295 }
276 } 296 }
277 panicf("%s Error offset %d does not exist", __func__, (unsigned int)offset); 297 panicf("%s Error offset %d does not exist", __func__, (unsigned int)offset);
@@ -284,19 +304,14 @@ static size_t chunk_find_data_idx(struct chunk_alloc_header *hdr,
284*/ 304*/
285void* chunk_get_data(struct chunk_alloc_header *hdr, size_t offset) 305void* chunk_get_data(struct chunk_alloc_header *hdr, size_t offset)
286{ 306{
287 struct chunk *chunk; 307 size_t real = chunk_get_at_offset(hdr, offset);
288 size_t idx = chunk_find_data_idx(hdr, offset, &chunk); 308 logf("%s offset: %ld real: %ld", __func__, offset, real);
289 if (idx > 0) 309 return buflib_get_data_pinned(hdr->context, hdr->cached_chunk.handle) + real;
290 offset -= chunk[idx - 1].max_start_offset;
291 logf("%s adjusted offset: %ld", __func__, offset);
292 buflib_pin(hdr->context, chunk[idx].handle);
293 return buflib_get_data(hdr->context, chunk[idx].handle) + offset;
294} 310}
295 311
296/* release a pinned buffer, chunk can't be moved till pin count == 0 */ 312/* release a pinned buffer, chunk can't be moved till pin count == 0 */
297void chunk_put_data(struct chunk_alloc_header *hdr, size_t offset) 313void chunk_put_data(struct chunk_alloc_header *hdr, void* data, size_t offset)
298{ 314{
299 struct chunk *chunk; 315 size_t real = chunk_get_at_offset(hdr, offset);
300 size_t idx = chunk_find_data_idx(hdr, offset, &chunk); 316 buflib_put_data_pinned(hdr->context, data - real);
301 buflib_unpin(hdr->context, chunk[idx].handle);
302} 317}