mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-13 18:17:39 -04:00
chunk alloc add buflib_get_pinned and chunk caching
Change-Id: Ia581656793b8ce9b80545705cfbba0fb225bb616
This commit is contained in:
parent
bd7b54a3c4
commit
1b383ef480
3 changed files with 84 additions and 64 deletions
|
@ -1205,7 +1205,7 @@ static int get_track_filename(struct playlist_info* playlist, int index, int see
|
||||||
{
|
{
|
||||||
char *namebuf = chunk_get_data(&playlist->name_chunk_buffer, seek);
|
char *namebuf = chunk_get_data(&playlist->name_chunk_buffer, seek);
|
||||||
strmemccpy(tmp_buf, namebuf, sizeof(tmp_buf));
|
strmemccpy(tmp_buf, namebuf, sizeof(tmp_buf));
|
||||||
chunk_put_data(&playlist->name_chunk_buffer, seek);
|
chunk_put_data(&playlist->name_chunk_buffer, namebuf, seek);
|
||||||
NOTEF("%s [in Ram]: 0x%x %s", __func__, seek, tmp_buf);
|
NOTEF("%s [in Ram]: 0x%x %s", __func__, seek, tmp_buf);
|
||||||
}
|
}
|
||||||
else if (max < 0)
|
else if (max < 0)
|
||||||
|
@ -2145,11 +2145,9 @@ int playlist_add(const char *filename)
|
||||||
|
|
||||||
char *namebuf = (char*)chunk_get_data(&playlist->name_chunk_buffer, indice);
|
char *namebuf = (char*)chunk_get_data(&playlist->name_chunk_buffer, indice);
|
||||||
strcpy(namebuf, filename);
|
strcpy(namebuf, filename);
|
||||||
|
namebuf[len] = '\0';
|
||||||
|
chunk_put_data(&playlist->name_chunk_buffer, namebuf, indice);
|
||||||
|
|
||||||
namebuf += len;
|
|
||||||
namebuf[0] = '\0';
|
|
||||||
|
|
||||||
chunk_put_data(&playlist->name_chunk_buffer, indice);
|
|
||||||
playlist->indices[playlist->amount] = indice;
|
playlist->indices[playlist->amount] = indice;
|
||||||
|
|
||||||
#ifdef HAVE_DIRCACHE
|
#ifdef HAVE_DIRCACHE
|
||||||
|
|
|
@ -40,17 +40,22 @@
|
||||||
* offset / sizeof(data) or index * sizeof(data) to convert
|
* offset / sizeof(data) or index * sizeof(data) to convert
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct chunk
|
struct chunk_alloc
|
||||||
{
|
{
|
||||||
int handle; /* data handle of buflib allocated bytes */
|
int handle; /* data handle of buflib allocated bytes */
|
||||||
size_t max_start_offset; /* start of last allocation */
|
size_t max_start_offset; /* start of last allocation */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CHUNK_ARRSZ(n) (sizeof(struct chunk) * n)
|
#define CHUNK_ARRSZ(n) (sizeof(struct chunk_alloc) * n)
|
||||||
|
|
||||||
static struct chunk* get_chunk_array(struct buflib_context *ctx, int handle)
|
static struct chunk_alloc* get_chunk_array(struct buflib_context *ctx, int handle)
|
||||||
{
|
{
|
||||||
return (struct chunk*)buflib_get_data(ctx, handle);
|
return (struct chunk_alloc*)buflib_get_data_pinned(ctx, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void put_chunk_array(struct buflib_context *ctx, struct chunk_alloc *data)
|
||||||
|
{
|
||||||
|
buflib_put_data_pinned(ctx, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* shrink or grow chunk allocation
|
/* shrink or grow chunk allocation
|
||||||
|
@ -63,8 +68,8 @@ bool chunk_realloc(struct chunk_alloc_header *hdr,
|
||||||
size_t chunk_size, size_t max_chunks)
|
size_t chunk_size, size_t max_chunks)
|
||||||
{
|
{
|
||||||
struct buflib_context *ctx = hdr->context;
|
struct buflib_context *ctx = hdr->context;
|
||||||
struct chunk *new_chunk = NULL;
|
struct chunk_alloc *new_chunk = NULL;
|
||||||
struct chunk *old_chunk;
|
struct chunk_alloc *old_chunk;
|
||||||
size_t min_chunk = 1;
|
size_t min_chunk = 1;
|
||||||
int new_handle = 0;
|
int new_handle = 0;
|
||||||
|
|
||||||
|
@ -83,10 +88,8 @@ bool chunk_realloc(struct chunk_alloc_header *hdr,
|
||||||
}
|
}
|
||||||
if (hdr->chunk_handle > 0) /* handle existing chunk */
|
if (hdr->chunk_handle > 0) /* handle existing chunk */
|
||||||
{
|
{
|
||||||
logf("%s %ld chunks (%ld bytes) => %ld chunks (%ld bytes)", __func__,
|
logf("%s %ld chunks => %ld chunks", __func__, hdr->count, max_chunks);
|
||||||
hdr->count, CHUNK_ARRSZ(hdr->count), max_chunks, CHUNK_ARRSZ(max_chunks));
|
|
||||||
|
|
||||||
buflib_pin(ctx, hdr->chunk_handle);
|
|
||||||
old_chunk = get_chunk_array(ctx, hdr->chunk_handle);
|
old_chunk = get_chunk_array(ctx, hdr->chunk_handle);
|
||||||
|
|
||||||
if (new_chunk != NULL) /* copy any valid old chunks to new */
|
if (new_chunk != NULL) /* copy any valid old chunks to new */
|
||||||
|
@ -94,6 +97,7 @@ bool chunk_realloc(struct chunk_alloc_header *hdr,
|
||||||
min_chunk = MIN(max_chunks, hdr->current + 1);
|
min_chunk = MIN(max_chunks, hdr->current + 1);
|
||||||
logf("%s copying %ld chunks", __func__, min_chunk);
|
logf("%s copying %ld chunks", __func__, min_chunk);
|
||||||
memcpy(new_chunk, old_chunk, CHUNK_ARRSZ(min_chunk));
|
memcpy(new_chunk, old_chunk, CHUNK_ARRSZ(min_chunk));
|
||||||
|
put_chunk_array(ctx, new_chunk);
|
||||||
}
|
}
|
||||||
/* free any chunks that no longer fit */
|
/* free any chunks that no longer fit */
|
||||||
for (size_t i = max_chunks; i <= hdr->current; i++)
|
for (size_t i = max_chunks; i <= hdr->current; i++)
|
||||||
|
@ -101,7 +105,7 @@ bool chunk_realloc(struct chunk_alloc_header *hdr,
|
||||||
logf("%s discarding chunk[%ld]", __func__, i);
|
logf("%s discarding chunk[%ld]", __func__, i);
|
||||||
buflib_free(ctx, old_chunk[i].handle);
|
buflib_free(ctx, old_chunk[i].handle);
|
||||||
}
|
}
|
||||||
buflib_unpin(ctx, hdr->chunk_handle);
|
put_chunk_array(ctx, old_chunk);
|
||||||
|
|
||||||
if (max_chunks < hdr->count && max_chunks > 0)
|
if (max_chunks < hdr->count && max_chunks > 0)
|
||||||
{
|
{
|
||||||
|
@ -122,10 +126,9 @@ bool chunk_realloc(struct chunk_alloc_header *hdr,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logf("chunk_alloc_init %ld chunks (%ld bytes)",
|
logf("chunk_alloc_init %ld chunks", hdr->count);
|
||||||
hdr->count, (hdr->count));
|
|
||||||
}
|
}
|
||||||
|
hdr->cached_chunk.handle = 0; /* reset last chunk to force new lookup */
|
||||||
hdr->chunk_handle = new_handle;
|
hdr->chunk_handle = new_handle;
|
||||||
hdr->chunk_size = chunk_size;
|
hdr->chunk_size = chunk_size;
|
||||||
hdr->count = max_chunks;
|
hdr->count = max_chunks;
|
||||||
|
@ -152,20 +155,16 @@ bool chunk_alloc_init(struct chunk_alloc_header *hdr,
|
||||||
size_t chunk_size, size_t max_chunks)
|
size_t chunk_size, size_t max_chunks)
|
||||||
{
|
{
|
||||||
/* initialize header */
|
/* initialize header */
|
||||||
hdr->chunk_handle = 0;
|
memset(hdr, 0, sizeof(struct chunk_alloc_header));
|
||||||
hdr->chunk_bytes_total = 0;
|
|
||||||
hdr->chunk_bytes_free = 0;
|
|
||||||
hdr->current = 0;
|
|
||||||
hdr->context = ctx;
|
hdr->context = ctx;
|
||||||
hdr->count = 0;
|
|
||||||
|
|
||||||
return chunk_realloc(hdr, chunk_size, max_chunks);
|
return chunk_realloc(hdr, chunk_size, max_chunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* shrink current chunk to size used */
|
/* shrink current chunk to size used */
|
||||||
static void finalize(struct chunk_alloc_header *hdr, struct chunk *chunk_array)
|
static void finalize(struct chunk_alloc_header *hdr, struct chunk_alloc *chunk_array)
|
||||||
{
|
{
|
||||||
/*Note calling functions check if chunk_bytes_free > 0*/
|
/* Note calling functions check if chunk_bytes_free > 0 */
|
||||||
size_t idx = hdr->current;
|
size_t idx = hdr->current;
|
||||||
if (idx >= hdr->count)
|
if (idx >= hdr->count)
|
||||||
return;
|
return;
|
||||||
|
@ -186,8 +185,10 @@ void chunk_alloc_finalize(struct chunk_alloc_header *hdr)
|
||||||
{
|
{
|
||||||
if (hdr->chunk_bytes_free > 0)
|
if (hdr->chunk_bytes_free > 0)
|
||||||
{
|
{
|
||||||
struct chunk *chunk = get_chunk_array(hdr->context, hdr->chunk_handle);
|
struct chunk_alloc *chunk;
|
||||||
|
chunk = get_chunk_array(hdr->context, hdr->chunk_handle);
|
||||||
finalize(hdr, chunk);
|
finalize(hdr, chunk);
|
||||||
|
put_chunk_array(hdr->context, chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,19 +198,19 @@ void chunk_alloc_finalize(struct chunk_alloc_header *hdr)
|
||||||
*/
|
*/
|
||||||
size_t chunk_alloc(struct chunk_alloc_header *hdr, size_t size)
|
size_t chunk_alloc(struct chunk_alloc_header *hdr, size_t size)
|
||||||
{
|
{
|
||||||
|
size_t virtual_offset = CHUNK_ALLOC_INVALID;
|
||||||
size_t idx = hdr->current;
|
size_t idx = hdr->current;
|
||||||
int handle = hdr->chunk_handle;
|
int handle = hdr->chunk_handle;
|
||||||
struct buflib_context *ctx = hdr->context;
|
struct buflib_context *ctx = hdr->context;
|
||||||
|
|
||||||
buflib_pin(ctx, handle);
|
struct chunk_alloc *chunk = get_chunk_array(ctx, handle);
|
||||||
struct chunk *chunk = get_chunk_array(ctx, handle);
|
|
||||||
|
|
||||||
while (size > 0)
|
while (size > 0)
|
||||||
{
|
{
|
||||||
if (idx >= hdr->count)
|
if (idx >= hdr->count)
|
||||||
{
|
{
|
||||||
logf("%s Error OOM -- out of chunks", __func__);
|
logf("%s Error OOM -- out of chunks", __func__);
|
||||||
break;
|
break; /* Out of chunks */
|
||||||
}
|
}
|
||||||
hdr->current = idx;
|
hdr->current = idx;
|
||||||
|
|
||||||
|
@ -222,7 +223,7 @@ size_t chunk_alloc(struct chunk_alloc_header *hdr, size_t size)
|
||||||
if (chunk[idx].handle <= 0)
|
if (chunk[idx].handle <= 0)
|
||||||
{
|
{
|
||||||
logf("%s Error OOM", __func__);
|
logf("%s Error OOM", __func__);
|
||||||
goto fail; /* OOM */
|
break; /* OOM */
|
||||||
}
|
}
|
||||||
|
|
||||||
hdr->chunk_bytes_total = new_alloc_size;
|
hdr->chunk_bytes_total = new_alloc_size;
|
||||||
|
@ -237,14 +238,17 @@ size_t chunk_alloc(struct chunk_alloc_header *hdr, size_t size)
|
||||||
|
|
||||||
if(size <= hdr->chunk_bytes_free) /* request will fit */
|
if(size <= hdr->chunk_bytes_free) /* request will fit */
|
||||||
{
|
{
|
||||||
size_t offset = chunk[idx].max_start_offset;
|
virtual_offset = chunk[idx].max_start_offset;
|
||||||
chunk[idx].max_start_offset += size;
|
chunk[idx].max_start_offset += size;
|
||||||
hdr->chunk_bytes_free -= size;
|
hdr->chunk_bytes_free -= size;
|
||||||
/*logf("%s hdr idx[%ld] offset[%ld] size: %ld",
|
|
||||||
__func__, idx, offset, size);*/
|
|
||||||
|
|
||||||
buflib_unpin(ctx, handle);
|
if (hdr->cached_chunk.handle == chunk[idx].handle)
|
||||||
return offset;
|
hdr->cached_chunk.max_offset = chunk[idx].max_start_offset;
|
||||||
|
|
||||||
|
/*logf("%s hdr idx[%ld] offset[%ld] size: %ld",
|
||||||
|
__func__, idx, offset, size);*/
|
||||||
|
|
||||||
|
break; /* Success */
|
||||||
}
|
}
|
||||||
else if (hdr->chunk_bytes_free > 0) /* shrink the current chunk */
|
else if (hdr->chunk_bytes_free > 0) /* shrink the current chunk */
|
||||||
{
|
{
|
||||||
|
@ -252,26 +256,42 @@ size_t chunk_alloc(struct chunk_alloc_header *hdr, size_t size)
|
||||||
}
|
}
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
fail:
|
|
||||||
buflib_unpin(ctx, handle);
|
put_chunk_array(ctx, chunk);
|
||||||
return CHUNK_ALLOC_INVALID;
|
return virtual_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns chunk idx given virtual offset */
|
/* retrieves chunk given virtual offset
|
||||||
static size_t chunk_find_data_idx(struct chunk_alloc_header *hdr,
|
* returns actual offset
|
||||||
size_t offset, struct chunk **chunk)
|
*/
|
||||||
|
static size_t chunk_get_at_offset(struct chunk_alloc_header *hdr, size_t offset)
|
||||||
{
|
{
|
||||||
size_t idx;
|
if ((hdr->cached_chunk.handle > 0)
|
||||||
*chunk = get_chunk_array(hdr->context, hdr->chunk_handle);
|
&& (offset >= hdr->cached_chunk.min_offset)
|
||||||
/*logf("%s search for offset[%ld]", __func__, offset);*/
|
&& (offset < hdr->cached_chunk.max_offset))
|
||||||
for (idx = hdr->current; idx < hdr->count; idx--)
|
|
||||||
{
|
{
|
||||||
if (offset < (*chunk)[idx].max_start_offset
|
/* convert virtual offset to real internal offset */
|
||||||
&& (idx == 0 || offset >= (*chunk)[idx - 1].max_start_offset))
|
return offset - hdr->cached_chunk.min_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* chunk isn't cached perform new lookup */
|
||||||
|
struct chunk_alloc *chunk = get_chunk_array(hdr->context, hdr->chunk_handle);
|
||||||
|
logf("%s search for offset[%ld]", __func__, offset);
|
||||||
|
for (size_t idx = hdr->current; idx < hdr->count; idx--)
|
||||||
|
{
|
||||||
|
size_t min_offset = (idx == 0 ? 0 : chunk[idx - 1].max_start_offset);
|
||||||
|
if (offset < chunk[idx].max_start_offset && offset >= min_offset)
|
||||||
{
|
{
|
||||||
/*logf("%s found hdr idx[%ld] max offset[%ld]",
|
logf("%s found hdr idx[%ld] min offset[%ld] max offset[%ld]",
|
||||||
__func__, idx, (*chunk)[idx].max_start_offset);*/
|
__func__, idx, min_offset, chunk[idx].max_start_offset);
|
||||||
return idx;
|
|
||||||
|
/* store found chunk */
|
||||||
|
hdr->cached_chunk.handle = chunk[idx].handle;
|
||||||
|
hdr->cached_chunk.max_offset = chunk[idx].max_start_offset;
|
||||||
|
hdr->cached_chunk.min_offset = min_offset;
|
||||||
|
put_chunk_array(hdr->context, chunk);
|
||||||
|
/* convert virtual offset to real internal offset */
|
||||||
|
return offset - hdr->cached_chunk.min_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panicf("%s Error offset %d does not exist", __func__, (unsigned int)offset);
|
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,
|
||||||
*/
|
*/
|
||||||
void* chunk_get_data(struct chunk_alloc_header *hdr, size_t offset)
|
void* chunk_get_data(struct chunk_alloc_header *hdr, size_t offset)
|
||||||
{
|
{
|
||||||
struct chunk *chunk;
|
size_t real = chunk_get_at_offset(hdr, offset);
|
||||||
size_t idx = chunk_find_data_idx(hdr, offset, &chunk);
|
logf("%s offset: %ld real: %ld", __func__, offset, real);
|
||||||
if (idx > 0)
|
return buflib_get_data_pinned(hdr->context, hdr->cached_chunk.handle) + real;
|
||||||
offset -= chunk[idx - 1].max_start_offset;
|
|
||||||
logf("%s adjusted offset: %ld", __func__, offset);
|
|
||||||
buflib_pin(hdr->context, chunk[idx].handle);
|
|
||||||
return buflib_get_data(hdr->context, chunk[idx].handle) + offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* release a pinned buffer, chunk can't be moved till pin count == 0 */
|
/* release a pinned buffer, chunk can't be moved till pin count == 0 */
|
||||||
void chunk_put_data(struct chunk_alloc_header *hdr, size_t offset)
|
void chunk_put_data(struct chunk_alloc_header *hdr, void* data, size_t offset)
|
||||||
{
|
{
|
||||||
struct chunk *chunk;
|
size_t real = chunk_get_at_offset(hdr, offset);
|
||||||
size_t idx = chunk_find_data_idx(hdr, offset, &chunk);
|
buflib_put_data_pinned(hdr->context, data - real);
|
||||||
buflib_unpin(hdr->context, chunk[idx].handle);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,16 +28,23 @@
|
||||||
|
|
||||||
#define CHUNK_ALLOC_INVALID ((size_t)-1)
|
#define CHUNK_ALLOC_INVALID ((size_t)-1)
|
||||||
|
|
||||||
|
|
||||||
struct chunk_alloc_header
|
struct chunk_alloc_header
|
||||||
{
|
{
|
||||||
|
struct buflib_context *context; /* buflib context for all allocations */
|
||||||
|
int chunk_handle; /* data handle of buflib allocated array of struct chunk */
|
||||||
|
|
||||||
size_t chunk_bytes_total; /* total bytes in current chunk */
|
size_t chunk_bytes_total; /* total bytes in current chunk */
|
||||||
size_t chunk_bytes_free; /* free bytes in current chunk */
|
size_t chunk_bytes_free; /* free bytes in current chunk */
|
||||||
size_t chunk_size; /* default chunk size */
|
size_t chunk_size; /* default chunk size */
|
||||||
size_t count; /* total chunks possible */
|
size_t count; /* total chunks possible */
|
||||||
size_t current; /* current chunk in use */
|
size_t current; /* current chunk in use */
|
||||||
|
|
||||||
struct buflib_context *context; /* buflib context for all allocations */
|
struct {
|
||||||
int chunk_handle; /* data handle of buflib allocated array of struct chunk */
|
int handle;
|
||||||
|
size_t min_offset;
|
||||||
|
size_t max_offset;
|
||||||
|
} cached_chunk;
|
||||||
};
|
};
|
||||||
|
|
||||||
void chunk_alloc_free(struct chunk_alloc_header *hdr);
|
void chunk_alloc_free(struct chunk_alloc_header *hdr);
|
||||||
|
@ -55,7 +62,7 @@ size_t chunk_alloc(struct chunk_alloc_header *hdr, size_t size); /* Returns offs
|
||||||
|
|
||||||
void* chunk_get_data(struct chunk_alloc_header *hdr, size_t offset); /* Returns data */
|
void* chunk_get_data(struct chunk_alloc_header *hdr, size_t offset); /* Returns data */
|
||||||
|
|
||||||
void chunk_put_data(struct chunk_alloc_header *hdr, size_t offset);
|
void chunk_put_data(struct chunk_alloc_header *hdr, void* data, size_t offset);
|
||||||
|
|
||||||
static inline bool chunk_alloc_is_initialized(struct chunk_alloc_header *hdr)
|
static inline bool chunk_alloc_is_initialized(struct chunk_alloc_header *hdr)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue