Commit graph

51 commits

Author SHA1 Message Date
Aidan MacDonald
6e9b1b344b buflib: remove buflib_print_allocs / buflib_print_blocks
These don't have any users and there is already another way to
print blocks (which is actually used by the debug menu).

Change-Id: Ic6a4f874c6499c42bc046e8af3e4aaddc9e68276
2022-09-19 15:09:51 -04:00
Aidan MacDonald
59edcc57a2 buflib: omit CRC field if CRC paranoia is not enabled
If we don't check or generate CRCs then the CRC field can be left
out of the header, which reduces buflib overhead slightly.

Change-Id: I08b4cf77a701d8f6da453e019a0373d858a79ae4
2022-09-19 15:09:51 -04:00
Aidan MacDonald
dcc4e54b77 buflib: refactor CRC checks as paranoia
Move CRC checking and updating behind a paranoia bit, like the
other checks, so it can be enabled and disabled.

Change-Id: Icff66c842cbd5af2d99aa91e6c40447a64e6d4b2
2022-09-19 15:09:51 -04:00
Aidan MacDonald
f82f3044a7 buflib: add paranoia checks for handles
Handle checks ensure that the data in the handle table points
within buflib memory and checks handle entry pointers in block
headers before dereferencing them.

Change-Id: Ic16f1b81c1a0ea63c0e7f48d87938293b75c2419
2022-09-19 15:09:51 -04:00
Aidan MacDonald
73b9b227eb buflib: add block length paranoia checks for loops
Tighten up checking by adding length checks to loops which
ensure the iteration stays within bounds. Check is disabled
by default and can be enabled using a BUFLIB_PARANOIA bit.

Change-Id: I35e911e0878797d5ebf732be548ca659f6910fe0
2022-09-19 15:09:51 -04:00
Aidan MacDonald
b12427741a buflib: clean up and refactor to improve maintainability
Buflib is written with a lot of hardcoded offsets to header fields,
arbitrary pointer arithmetic, and similar but not quite duplicated
code, making maintenance a nightmare.

Most of the pointer arithmetic involving header fields is replaced
by indexing from two well-defined pointers, the block start and end
pointers. The start pointer points to the first header field, and
he end pointer is one past the end of the header.

Hardcoded field indices are replaced by two enums. Forward indices
(fidx_XXX) are used to access fields from a block start pointer and
negated backward indices (-bidx_XXX) are used to index from a block
end pointer. There is no overlap between the indices because of the
variable length name field in the middle of the header. The length
of the fixed fields in the block header is now a #define'd constant
rather than being open coded.

There is now a function to acquire the block end pointer from the
user data pointer (ie. the pointer stored in the handle table). The
old code was not consistent in this; some functions would handle a
non-aligned user pointer, which may occur as a result of shrinking,
while other uses just assumed the user pointer was aligned.

Block CRC calculations have also been factored out to a function
that accepts block start and end pointers.

Change-Id: I6a7e8a8c58aec6c6eaf0e5021400032d8e5f841e
2022-09-19 15:09:51 -04:00
Aidan MacDonald
fdde6bb5a7 buflib: optimize getting start of block from end of block
The block header has a variable length due to the embedded name.
The name length is stored at the back of the header after the
name, in order to allow finding the start of the header if only
the user data pointer is known (eg. from the handle table).

The name length is actually not interesting in itself; storing
the total length of the block header instead is marginally more
efficient, saving one addition in handle_to_block().

Instead the extra arithmetic must be done by buflib_get_name(),
which is a much less common operation than handle_to_block().

Change-Id: Ia339a1d2f556a11a49deae0871203e70548bd234
2022-09-19 15:09:51 -04:00
Aidan MacDonald
ef476ba298 buflib: correct a confusingly indented comment
Change-Id: I9ef13d697c4abb81883d4a47273e69fcc2dafe37
2022-09-19 15:09:51 -04:00
Aidan MacDonald
c8365b2bdd buflib: fix bug in handle_table_shrink
The way it iterated over the handle table is unsafe if *every*
handle is free, leading to an out of bounds access.

This is a contrived example, but the bug can be triggered by
making several allocations, freeing them out of order so that
the handle table remains uncompacted, and then triggering a
compaction using buflib_alloc_maximum().

Change-Id: I879e2f0b223e6ca596769610ac46f4edf1107f5c
2022-09-19 15:09:51 -04:00
Aidan MacDonald
4d3bf1c446 buflib: add comment in handle_alloc, remove a dead store
It isn't obvious why the "handle->val = -1" at the end of handle_alloc
is needed so add an explanatory comment. But "handle->val = 1" prior to
calling handle_free is simply a dead store.

Change-Id: I9ab4e96e87e940cfd1a2ed56f089287821669c73
2022-09-19 15:09:51 -04:00
Aidan MacDonald
840f6b79c7 buflib: update first_free_handle in handle_alloc
Since we're scanning the handle table for the first free slot,
we know none of the scanned slots are free. Use that knowledge
to update first_free_handle and avoid rescanning filled slots
again when the next handle is allocated.

Change-Id: I457372f66c231168cfffa7e905d1e9fb80002f5f
2022-09-19 15:09:51 -04:00
Aidan MacDonald
f622bcfe4f buflib: fix buflib_context_relocate alignment check
Use the standard IS_ALIGNED macro and check alignment against
sizeof(buflib_data), as it can be greater than 4 bytes if we're
on a 64-bit platform (eg. simulator).

Change-Id: I15110937d1f2978e733d169050de9531fe218214
2022-09-19 15:09:51 -04:00
Aidan MacDonald
bcaa9465e9 buflib: optimize find_block_before
Exiting the loop implies next_block == block, so remove that check.
The check ret < block is false only if block is the first block, which
can be checked before the loop, saving a few cycles in that case.

Change-Id: Id493b5259a23a35a70b09dfe4bc4eacaf420760c
2022-09-19 15:09:51 -04:00
Aidan MacDonald
e8faf2f2ad buflib: add a common dummy callbacks struct & use it
There are various allocations that can't be moved or shrunk.
Provide a global callback struct for this use case instead of
making each caller declare its own dummy struct.

Also fixed ROLO and x1000 installer code which incorrectly
used movable allocations.

Change-Id: I00088396b9826e02e69a4a33477fe1a7816374f1
2022-02-12 10:24:32 -05:00
William Wilgus
8577d5aea3 Buflib_init Bugfix Minsize
when buflib_init is called with a buffer smaller than
sizeof(union buflib_data); size will be zero
Later when the alloc fails buflib will keep try to free items
in order to satisify the request this crashes in the sim
I suspect this behavior holds true on device as well
but I havent verified this as of yet.

patch adds minimal overhead to the buflib and panics when the size is too small

Change-Id: I46e510367fc1cac19ce01ee6f92d8cf0d65ef914
2020-07-15 13:29:21 +00:00
William Wilgus
976831e667 Buflib add range checks blocks and crc_slot raise panic if out of range
Change-Id: I81df5c145a8cb003827a5423f484f70333e2472e
2019-01-04 06:47:20 +01:00
Thomas Jarosch
bce72e6f2c buflib: Switch from term "cookie" to "metadata"
The documentation of buflib first mentions metadata
and then changes to "cookie" without explaining it.

Fix it by sticking to metadata.

Change-Id: I0b36b18f4f2590132901c10326481975f8b9b9da
2015-01-02 19:26:03 +01:00
Thomas Jarosch
66df5f3891 Improve core_alloc() / buflib_alloc() documentation
Document the fact that buffers are movable by default.
Care must be taken to not pass them to functions that yield().

Also clarify other things:
- Passing NULL as "ops" to buflib_alloc_ex() causes
  buffers to be movable by default (but not shrinkable).

- If you want shrinkable buffers during compaction,
  you have to provide a shrink callback.

- To disable buffer movement, you have to pass NULL
  for the move_callback inside the callback structure.

- The concept of default callbacks was removed
  long ago, remove the only reference of it.

Change-Id: I3bf0ea6b08b507d80a19f3c2c835aca32b3f7800
2015-01-02 18:51:15 +01:00
Thomas Jarosch
9076b433d1 PictureFlow: Add move callback for buflib allocations
If we don't provide a callback to buflib_alloc(),
the buffer is always movable (to reduce fragmentation).

Since we pass our buffer to functions that call yield(),
this could lead to memory corruption on buflib compaction.

Change-Id: Id1fad1822479d692551c55cb8bc87cea7b78f759
2015-01-01 23:49:41 +01:00
Thomas Jarosch
09f7bb82ca Add missing newline in debug output
Change-Id: Ifd67dbcc80db328391464ec93316c48f914bc590
2014-12-30 00:17:38 +01:00
Thomas Jarosch
da5a36d6d2 Document 'union buflib_data'
Change-Id: Ia98fa8e7887338d6c0b7a5795a0ae5c7a13014ba
2014-12-29 23:49:12 +01:00
Thomas Martitz
4ce39f7e73 buflib: Add a define telling the per-alloc overhead.
This allows buflib clients to more accurately estimate the total memory usage.
It's still not 100% accurate because the handle table grows in blocks, thus
buflib might use more memory that caused by allocations directly.

Change-Id: I68338bb94f510ad188fcb588aebf895b5f9197c5
2014-02-02 19:40:38 +01:00
Thomas Martitz
4ce1deacfd buflib: Properly support allocations without any name, to avoid wasting space
in micro-allocation scenarios.

Change-Id: I97a065bcfba8e0fda9b1670445e839e267c769c8
2014-02-02 19:40:38 +01:00
Thomas Martitz
d66346789c buflib: Check the validity of of handles passed to buflib_get_data() in DEBUG builds.
Change-Id: Ic274bfb4a8e1a1a10f9a54186b9173dbc0faa4c8
2014-02-02 16:59:29 +01:00
Thomas Martitz
d608d2203a buflib: Abstract panicf() into buflib_panic().
Change-Id: I4968a9bc290e10e30a77c36c19f694e286e7ef22
2014-02-02 16:59:29 +01:00
Marcin Bukat
7ab237b025 buflib: Add crc field protecting buflib cookie integrity
This should catch the case of buffer misuse which results
in corrupted cookie of next allocation. The check is performed
on move_block() so it may be a bit late.

There is buflib_check_valid() provided which checks the
integrity of all cookies for given context.
On DEBUG build with --sdl-thread this check is carried out
for core_ctx on every context switch to catch problems earlier.

Change-Id: I999d4576084592394e3dbd3bdf0f32935ff5f601
Reviewed-on: http://gerrit.rockbox.org/711
Reviewed-by: Thomas Martitz <kugel@rockbox.org>
2014-01-16 10:17:39 +01:00
Thomas Martitz
281d1fadb3 Do not include kernel.h in system.h.
system.h doesn't need it on its own and this change makes it less
dependant on Rockbox internals.

Change-Id: I4e1e4108a52a7b599627a829204eb82b392fc6d6
2014-01-05 19:35:23 +01:00
Thomas Martitz
64b9e1fa7b 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
2013-12-22 23:11:32 +01:00
Thomas Martitz
d25a512caf buflib: Try harder in buflib_alloc_maximum().
This function will now ask shrinkable allocations to give up all of their
memory. With future support of playback.c this can be used as a safe
replacement for audio_get_buffer().

Change-Id: I290a51d2c75254e66baf5698c41dc444dea6247a
2013-12-22 23:11:32 +01:00
Thomas Martitz
af4e408555 buflib: Change buflib_available() and add buflib_allocatable().
buflib_allocatable() is what buflib_available() was before (it was in fact
simply renamed). It returns the largest contiguous block of memory. This
can be allocated and will definitely succeed, although larger allocations
may also succeed if the buffer can be compacted and shrinked.

buflib_available() now counts all free bytes, contiguous or not. This
better matches the description and how the caller use it.

Change-Id: I511e4eb5f4cf1821d957b3f4ef8a685ce40fe289
Reviewed-on: http://gerrit.rockbox.org/481
Reviewed-by: Thomas Martitz <kugel@rockbox.org>
Tested-by: Thomas Martitz <kugel@rockbox.org>
2013-07-07 10:46:07 +02:00
Thomas Martitz
46ea8bfe7c buflib: Allow handle to be freed entirely during the shrink callback.
Change-Id: I3a069dcb99bbd4022faf37596b03beb926d2ea82
Reviewed-on: http://gerrit.rockbox.org/480
Reviewed-by: Thomas Martitz <kugel@rockbox.org>
Tested-by: Thomas Martitz <kugel@rockbox.org>
2013-06-24 15:24:34 +02:00
Michael Sevakis
b7e0e1a0a3 buflib: Remove compulsory IRQ disable during buffer move.
It can cause excessively long interrupt outages if moving a larger
buffer and disrupt audio where DMA is not at a higher interrupt priority
such as FIQ.

Some targets, like Gigabeat S, have very low audio interrupt latency
requirements and will even channel swap if they are missed. Pictureflow
will make the issue very obvious. Even then, moves could take
milliseconds or more depending on the buffer size which is far too long
for any target.

Change-Id: I8e7817213e901da67c36b7eb25d7cb1c1e3ba802
Reviewed-on: http://gerrit.rockbox.org/472
Reviewed-by: Michael Sevakis <jethead71@rockbox.org>
Tested-by: Michael Sevakis <jethead71@rockbox.org>
2013-05-23 18:25:29 +02:00
Michael Sevakis
7e3e9b9289 Stop the BDEBUGF format warnings in buflib.c
Change-Id: I63881da2b857cf4e462f7730f9cd54dc1743fc2f
2012-05-02 17:37:10 -04:00
Michael Sevakis
0d568bb6ce Stop lame warnings about braces and empty body of 'if' statement.
Change-Id: I9f0e3d047a91a8f49d5c64f961f8fff054f37099
2012-05-02 17:30:32 -04:00
Michael Sevakis
da6cebb6b0 Use buflib for the allocation of voice PCM resources.
Buffers are not allocated and thread is not created until the first
call where voice is required.

Adds a different callback (sync_callback) to buflib so that other
sorts of synchonization are possible, such as briefly locking-out the
PCM callback for a buffer move. It's sort of a messy addition but it
is needed so voice decoding won't have to be stopped when its buffer
is moved.

Change-Id: I4d4d8c35eed5dd15fb7ee7df9323af3d036e92b3
2012-05-02 17:22:28 -04:00
Thomas Martitz
6c6c476d57 Buflib: Fix handles being possibly moved twice
Author: Boris Gjenero
Fixes: FS#12441, FS#12464

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31359 a1c6a512-1295-4272-9138-f99709370657
2011-12-19 08:08:07 +00:00
Thomas Martitz
f0bab2ff9a Address some weaknesses and bugs of buflib_compact() and make the code prettier. Thanks to Boris Gjenero for his great investigation.
Flyspray: FS#12409
Author: myself

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31101 a1c6a512-1295-4272-9138-f99709370657
2011-12-01 07:02:18 +00:00
Boris Gjenero
d51e598335 FS#12412 : Delete old buffer allocation code which has been replaced by core_alloc, and move buffer setup code to core_alloc.c
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31088 a1c6a512-1295-4272-9138-f99709370657
2011-11-29 00:42:27 +00:00
Boris Gjenero
bd360b422a In buflib_buffer_shift(), properly update handle->alloc values, which are char * and not union buflib data *
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31066 a1c6a512-1295-4272-9138-f99709370657
2011-11-27 01:40:47 +00:00
Thomas Martitz
2a8eacdbfc Buflib: Make shrinking and buflib_available() smarter.
* shrinking now considers freespace just before the alloc-to-be-shrinked,
  that means less (or sometimes none at all) is taken from the audio buffer.
* core_available() now searches for the best free space, instead of simply the end,
  i.e. it will not return 0 if the audio buffer is allocated and there's free space
  before it. It also runs a compaction to ensure maximum contiguous memory.

audio_buffer_available() is also enhanced. It now considers the 256K reserve buffer,
and returns free buflib space instead if the audio buffer is short.

This all fixes the root problem of FS#12344 (Sansa Clip+: PANIC occurred when
dircache is enabled), that alloced from the audio buffer, even if it was very
short and buflib had many more available as free space before it.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31006 a1c6a512-1295-4272-9138-f99709370657
2011-11-17 17:55:02 +00:00
Thomas Martitz
889690c0f6 Fix audio_get_buffer() implementation on hwcodec, to be similar to the swcodec one. Should make hwcodec bood again.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30737 a1c6a512-1295-4272-9138-f99709370657
2011-10-09 12:30:37 +00:00
Thomas Martitz
aed39dbbaf Protect the move operation of buflib against IRQs.
This makes accessing the buffers with core_get_data() from
interrupt context safe, other buflib functions aren't really safe (yet).

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30736 a1c6a512-1295-4272-9138-f99709370657
2011-10-09 12:27:35 +00:00
Thomas Martitz
585eb12348 Buflib: Correct return value of handle_table_shrink() to match comment.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30495 a1c6a512-1295-4272-9138-f99709370657
2011-09-10 15:16:15 +00:00
Thomas Martitz
49b64f13e5 Remove obsolete comment
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30488 a1c6a512-1295-4272-9138-f99709370657
2011-09-09 15:44:09 +00:00
Thomas Martitz
f7cff8bd69 Buflib: Stop caching the first unallocated block. It has little benefit but is complicated to keep up-to-date.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30487 a1c6a512-1295-4272-9138-f99709370657
2011-09-09 15:35:14 +00:00
Thomas Martitz
0dcbc6cd5d Buflib: Handle not having enough space for new handles (fixes FS#12265).
Handles are allocated at the end, growing downwards.
The tiny allocations from r30478 broke buflib, since it was assumed that the only shrinkable allocation (the audiobuffer) is the very last allocation.
The tiny allocations however fit into the reserve buffer for new handles, breaking the above assumption, and they can't shrink to make room for handles.

Now, move any allocations before audiobuf (or shrink audiobuf like before) to make room for handles. This also unifies some duplicated code.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30486 a1c6a512-1295-4272-9138-f99709370657
2011-09-09 13:33:22 +00:00
Thomas Martitz
daaae99c1c Remove unecessary casting
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30470 a1c6a512-1295-4272-9138-f99709370657
2011-09-07 23:20:12 +00:00
Thomas Martitz
5296af838c Buflib: Clarification about invalid handles
* Enhance allocation function comments to better state the return value and what an invalid value is
* Change clients to check for "< 0" instead of "<= 0" or "== 0"
* Return -1 or -2 depending on the exact failure in buflib_alloc_ex.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30469 a1c6a512-1295-4272-9138-f99709370657
2011-09-07 23:16:29 +00:00
Thomas Martitz
0c4c81620f Fix h100 red and other warnings.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30384 a1c6a512-1295-4272-9138-f99709370657
2011-08-30 14:32:16 +00:00
Thomas Martitz
baa070cca6 GSoC/Buflib: Enable compaction in buflib.
This enables the ability to allocate (and free) memory dynamically
without fragmentation, through compaction. This means allocations can move
and fragmentation be reduced. Most changes are preparing Rockbox for this,
which many times means adding a move callback which can temporarily disable
movement when the corresponding code is in a critical section.

For now, the audio buffer allocation has a central role, because it's the one
having allocated most. This buffer is able to shrink itself, for which it
needs to stop playback for a very short moment. For this,
audio_buffer_available() returns the size of the audio buffer which can
possibly be used by other allocations because the audio buffer can shrink.

lastfm scrobbling and timestretch can now be toggled at runtime without
requiring a reboot.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30381 a1c6a512-1295-4272-9138-f99709370657
2011-08-30 14:01:45 +00:00