impl-node: improve driver activation counter calculation

Don't schedule nodes that didn't receive us as the driver node yet
because they will not be able to signal us when they complete and leave
us xrun.

Also only count the nodes that we will actually schedule and expect a
signal from, set this in the pending activation counter. This can be
less when some nodes are still starting or receiving the driver
activation record.

This eleminates some errors when adding and removing nodes.

See #4182
This commit is contained in:
Wim Taymans 2024-08-08 15:20:38 +02:00
parent 338e32e57c
commit 89bf8b8566

View file

@ -2080,6 +2080,7 @@ again:
all_ready = sync_type == SYNC_CHECK; all_ready = sync_type == SYNC_CHECK;
update_sync = !all_ready; update_sync = !all_ready;
target_sync = sync_type == SYNC_START ? true : false; target_sync = sync_type == SYNC_START ? true : false;
pending = 0;
spa_list_for_each(t, &driver->rt.target_list, link) { spa_list_for_each(t, &driver->rt.target_list, link) {
struct pw_node_activation *ta = t->activation; struct pw_node_activation *ta = t->activation;
@ -2088,6 +2089,10 @@ again:
ta->driver_id = driver->info.id; ta->driver_id = driver->info.id;
retry_status: retry_status:
pw_node_activation_state_reset(&ta->state[0]); pw_node_activation_state_reset(&ta->state[0]);
if (ta->active_driver_id != ta->driver_id)
continue;
/* we don't change the state of inactive nodes and don't use them /* we don't change the state of inactive nodes and don't use them
* for reposition. The pending will be at least 1 and they might * for reposition. The pending will be at least 1 and they might
* get decremented to 0 but since the status is inactive, we don't * get decremented to 0 but since the status is inactive, we don't
@ -2101,6 +2106,8 @@ retry_status:
if (SPA_UNLIKELY(!SPA_ATOMIC_CAS(ta->status, old_status, PW_NODE_ACTIVATION_NOT_TRIGGERED))) if (SPA_UNLIKELY(!SPA_ATOMIC_CAS(ta->status, old_status, PW_NODE_ACTIVATION_NOT_TRIGGERED)))
goto retry_status; goto retry_status;
pending++;
if (old_status == PW_NODE_ACTIVATION_TRIGGERED || if (old_status == PW_NODE_ACTIVATION_TRIGGERED ||
old_status == PW_NODE_ACTIVATION_AWAKE) { old_status == PW_NODE_ACTIVATION_AWAKE) {
update_xrun_stats(ta, 1, nsec / 1000, 0); update_xrun_stats(ta, 1, nsec / 1000, 0);
@ -2139,6 +2146,7 @@ retry_status:
reposition_target = NULL; reposition_target = NULL;
goto again; goto again;
} }
state->pending = pending;
update_position(node, all_ready, nsec); update_position(node, all_ready, nsec);