alsa: setup sources from the data thread

For IRQ based scheduling we might otherwise be woken up after we only
added one of the fds to the poll loop and then we get an error when we
try to update it afterwards. Instead, add the fds from the data thread
to get things nicely in sync.
This commit is contained in:
Wim Taymans 2023-03-29 12:21:23 +02:00
parent 8c264d2dcb
commit 354836075d

View file

@ -2542,9 +2542,7 @@ static void alsa_wakeup_event(struct spa_source *source)
spa_log_trace_fp(state->log, "Woken up with no work to do");
return;
}
}
if (SPA_LIKELY(state->started && !state->disable_tsched)) {
} else if (SPA_LIKELY(state->started)) {
if (SPA_UNLIKELY((res = spa_system_timerfd_read(state->data_system,
state->timerfd, &expire)) < 0)) {
/* we can get here when the timer is changed since the last
@ -2640,11 +2638,9 @@ static int setup_sources(struct state *state)
struct timespec now;
int res;
if (!state->disable_tsched) {
if ((res = spa_system_clock_gettime(state->data_system, CLOCK_MONOTONIC, &now)) < 0)
return res;
state->next_time = SPA_TIMESPEC_TO_NSEC(&now);
}
if ((res = spa_system_clock_gettime(state->data_system, CLOCK_MONOTONIC, &now)) < 0)
return res;
state->next_time = SPA_TIMESPEC_TO_NSEC(&now);
if (state->following) {
/* Disable wakeups from this node */
@ -2671,6 +2667,19 @@ static int setup_sources(struct state *state)
return 0;
}
static int do_setup_sources(struct spa_loop *loop,
bool async,
uint32_t seq,
const void *data,
size_t size,
void *user_data)
{
struct state *state = user_data;
spa_dll_init(&state->dll);
setup_sources(state);
return 0;
}
int spa_alsa_start(struct state *state)
{
int err;
@ -2753,26 +2762,13 @@ int spa_alsa_start(struct state *state)
else if ((err = do_start(state)) < 0)
return err;
setup_sources(state);
spa_loop_invoke(state->data_loop, do_setup_sources, 0, NULL, 0, true, state);
state->started = true;
return 0;
}
static int do_reassign_follower(struct spa_loop *loop,
bool async,
uint32_t seq,
const void *data,
size_t size,
void *user_data)
{
struct state *state = user_data;
spa_dll_init(&state->dll);
setup_sources(state);
return 0;
}
int spa_alsa_reassign_follower(struct state *state)
{
bool following, freewheel;
@ -2784,7 +2780,7 @@ int spa_alsa_reassign_follower(struct state *state)
if (following != state->following) {
spa_log_debug(state->log, "%p: reassign follower %d->%d", state, state->following, following);
state->following = following;
spa_loop_invoke(state->data_loop, do_reassign_follower, 0, NULL, 0, true, state);
spa_loop_invoke(state->data_loop, do_setup_sources, 0, NULL, 0, true, state);
}
setup_matching(state);
@ -2819,7 +2815,6 @@ static int do_remove_source(struct spa_loop *loop,
} else {
clear_period_sources(state);
}
return 0;
}