mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
tasks: the Bluetooth scan does not spin at the end of its window
The queue runs a parked task up to half a millisecond early, so the scan's last wait, under a millisecond, was run again at once, over and over until the window was out. What is left within a millisecond of the end is no longer waited. The scan test stands in for the driver's new done call, and pins that a driver done early ends the scan before the window.
This commit is contained in:
1 parent
6153138ea9
commit
ee359e3cd9
3 files changed
+38
-13
No files matched your search
@@ -1267,10 +1267,11 @@ jobs:
|
||||
# The Bluetooth scan task on the real threaded task queue,
|
||||
# with the discovery window shortened. The scan used to wait
|
||||
# out the window inside one handler call, holding the task
|
||||
# thread; it now begins, reschedules itself for the end of
|
||||
# the window, and ends. Pins that begin and end run once each
|
||||
# a window apart, that another task runs during the window,
|
||||
# and that the callback fires.
|
||||
# thread; it now begins, is parked, looks every poll whether
|
||||
# the driver is done, and ends. Pins that begin and end run
|
||||
# once each a window apart, that another task runs during the
|
||||
# window, that the callback fires, and that a driver done
|
||||
# early ends the scan then.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 \
|
||||
timeout 60 ./bluetooth_scan_test
|
||||
|
||||
@@ -4,16 +4,17 @@
|
||||
* The scan ran inside one handler call and the drivers waited out the
|
||||
* ten-second discovery window in it - bluez in a sleep, bluetoothctl in
|
||||
* a blocking "scan on" - holding the one task thread, and every task
|
||||
* queued behind it, for the whole window. It is now two steps: begin,
|
||||
* then the task reschedules itself for the end of the window and the
|
||||
* queue runs other tasks meanwhile.
|
||||
* queued behind it, for the whole window. It now begins, is parked and
|
||||
* looks every poll whether the driver is done, and the queue runs
|
||||
* other tasks meanwhile.
|
||||
*
|
||||
* The contract this pins, with the window shortened to 300 ms:
|
||||
*
|
||||
* begin, then end -> once each, a window apart
|
||||
* during the window -> another task runs at once
|
||||
* the callback -> fires after end, with the task done
|
||||
* the end of the window -> a pass or two, not a run of them
|
||||
* the window -> a pass a poll, not a run of them
|
||||
* a driver done early -> the scan ends then, not at the window
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -50,6 +51,11 @@ void driver_bluetooth_scan_end(void)
|
||||
{ end_at = mono_ms(); retro_atomic_fetch_add_int(&ends, 1); }
|
||||
const char *msg_hash_to_str(enum msg_hash_enums msg) { return "msg"; }
|
||||
|
||||
/* the driver says it has found all it will */
|
||||
static retro_atomic_int_t driver_done = RETRO_ATOMIC_INT_INITIALIZER(0);
|
||||
bool driver_bluetooth_scan_done(void)
|
||||
{ return retro_atomic_load_acquire_int(&driver_done) != 0; }
|
||||
|
||||
/* ---- the task under test's neighbours ---- */
|
||||
|
||||
static retro_atomic_int_t other_ran = RETRO_ATOMIC_INT_INITIALIZER(0);
|
||||
@@ -123,10 +129,26 @@ int main(void)
|
||||
"a window after it began");
|
||||
check(retro_atomic_load_acquire_int(&scan_done), "the scan's callback fires");
|
||||
check(retro_atomic_load_acquire_int(&begins) == 1, "and it began only once");
|
||||
/* The queue may start the end of the window a little early; the
|
||||
* scan waits out the rest parked, not in a run of passes. */
|
||||
check(retro_atomic_load_acquire_int(&scan_passes) <= 4,
|
||||
"the window ends in a pass or two");
|
||||
/* a pass a poll through the window, parked between them */
|
||||
check(retro_atomic_load_acquire_int(&scan_passes)
|
||||
<= BLUETOOTH_SCAN_WINDOW_US / BLUETOOTH_SCAN_POLL_US + 3,
|
||||
"the window passes in a pass a poll");
|
||||
|
||||
/* a driver that has found all it will 100 ms in: ended then */
|
||||
retro_atomic_store_release_int(&scan_done, 0);
|
||||
check(task_push_bluetooth_scan(scan_cb), "a second scan is pushed");
|
||||
for (i = 0; i < 1000 && retro_atomic_load_acquire_int(&begins) < 2; i++)
|
||||
usleep(1000);
|
||||
usleep(100000);
|
||||
retro_atomic_store_release_int(&driver_done, 1);
|
||||
for (i = 0; i < 3000 && !retro_atomic_load_acquire_int(&scan_done); i++)
|
||||
{
|
||||
task_queue_check();
|
||||
usleep(1000);
|
||||
}
|
||||
check(retro_atomic_load_acquire_int(&ends) == 2
|
||||
&& end_at - begin_at < 280,
|
||||
"a driver done early ends the scan before the window");
|
||||
|
||||
task_queue_deinit();
|
||||
|
||||
|
||||
@@ -54,7 +54,9 @@ static void task_bluetooth_scan_handler(retro_task_t *task)
|
||||
&& !driver_bluetooth_scan_done())
|
||||
{
|
||||
retro_time_t now = cpu_features_get_time_usec();
|
||||
if (now < task_bluetooth_scan_deadline)
|
||||
/* the queue runs a parked task up to half a millisecond early:
|
||||
* what is left within a millisecond of the end is not waited */
|
||||
if (now + 1000 < task_bluetooth_scan_deadline)
|
||||
{
|
||||
retro_time_t wait = task_bluetooth_scan_deadline - now;
|
||||
if (wait > BLUETOOTH_SCAN_POLL_US)
|
||||
|
||||
Reference in new issue
Block a user