task_movie: a recording waits for a state load from the main thread

The record task only waits for an in-flight state load to retire, which
happens on the main thread, so it runs there and looks once per check.
bsv_replay_init_test starts a recording on the threaded queue with a
load in flight.
This commit is contained in:
LibretroAdmin authored and libretroadmin committed 2026-10-14 21:39:51 +02:00
1 parent ad2d961e10
commit 4134eace32
2 files changed
+69 -1

No files matched your search

@@ -127,6 +127,8 @@
#include <streams/interface_stream.h>
#include <file/file_path.h>
#include <queues/task_queue.h>
#include <rthreads/rthreads.h>
#include <retro_timers.h>
#include <encodings/rzstd.h>
#include "../../../configuration.h"
@@ -192,7 +194,21 @@ bool runloop_key_event_is_frontend(void)
input_driver_state_t *input_state_get_ptr(void) { return &input_st; }
/* the replay is over: the frontend's call for it, on the state above */
void bsv_movie_set_end(void) { input_st.bsv_movie_state.flags |= BSV_FLAG_MOVIE_END; }
bool content_load_state_in_progress(void *data) { (void)data; return false; }
/* A state load in flight, and who asks about it: the record task waits
* for the load to retire, which happens on the main thread. */
static int load_pending = 0;
static uintptr_t main_tid = 0;
static unsigned load_asks = 0;
static unsigned load_asks_off_main = 0;
bool content_load_state_in_progress(void *data)
{
(void)data;
if (main_tid && sthread_get_current_thread_id() != main_tid)
__atomic_fetch_add(&load_asks_off_main, 1, __ATOMIC_RELAXED);
else
load_asks++;
return __atomic_load_n(&load_pending, __ATOMIC_RELAXED) != 0;
}
void input_keyboard_event(bool down, unsigned code, uint32_t character,
uint16_t mod, unsigned device) { (void)down; (void)code; (void)character; (void)mod; (void)device; }
@@ -346,6 +362,54 @@ static void truncate_file(const char *path, int64_t len)
/* ---- lanes ----------------------------------------------------------- */
/* On the threaded queue, a recording started while a state load is in
* flight waits for it from the main thread, once per check, and starts
* once the load is through. */
static void lane_record_waits_for_load(const char *path)
{
unsigned i;
reset_counters();
settings.bools.savestate_file_compression = false;
fill_state(1);
task_queue_deinit();
task_queue_init(true, NULL);
main_tid = sthread_get_current_thread_id();
load_asks = 0;
__atomic_store_n(&load_asks_off_main, 0, __ATOMIC_RELAXED);
__atomic_store_n(&load_pending, 1, __ATOMIC_RELAXED);
CHECK(movie_start_record(&input_st, (char*)path), "start_record");
for (i = 0; i < 20; i++)
{
task_queue_check();
retro_sleep(1);
}
CHECK(__atomic_load_n(&load_asks_off_main, __ATOMIC_RELAXED) == 0,
"the record task asked about the load off the main thread %u times",
__atomic_load_n(&load_asks_off_main, __ATOMIC_RELAXED));
CHECK(load_asks <= 21, "asked about the load %u times in 20 checks",
load_asks);
CHECK(!(input_st.bsv_movie_state.flags & BSV_FLAG_MOVIE_RECORDING),
"recording before the load went through");
__atomic_store_n(&load_pending, 0, __ATOMIC_RELAXED);
for (i = 0; i < 20
&& !(input_st.bsv_movie_state.flags & BSV_FLAG_MOVIE_RECORDING); i++)
{
task_queue_check();
retro_sleep(1);
}
CHECK(input_st.bsv_movie_state.flags & BSV_FLAG_MOVIE_RECORDING,
"recording did not start once the load went through");
CHECK(movie_stop(&input_st), "halt");
task_queue_deinit();
task_queue_init(false, NULL);
main_tid = 0;
lane_done("record_waits_for_load", NULL);
}
static void lane_roundtrip(const char *path, bool compress)
{
uint8_t start[STATE_SIZE];
@@ -1396,6 +1460,7 @@ int main(int argc, char **argv)
lane_v1_short_state();
lane_short_block();
lane_write_oom();
lane_record_waits_for_load(path);
filestream_delete(path);
task_queue_deinit();
+3
View File
@@ -582,6 +582,9 @@ bool movie_start_record_notify(input_driver_state_t *input_st, char *path,
task->type = TASK_TYPE_NONE;
task->state = state;
task->handler = task_moviectl_record_handler;
/* It waits for a state load to retire, which happens on the main
* thread, so it looks from there, once per check. */
task->flags |= RETRO_TASK_FLG_MAIN_THREAD;
task->callback = moviectl_start_record_cb;
task->user_data = user_data;