impl-node: improve node activation

Only activate the nodes when it was not-triggered, do this check with an
atomic compare-and-swap so that we only activate a node once.

We might be able to use this later to make sure that we resume the
untriggered peer nodes when we remove a node from the graph.
This commit is contained in:
Wim Taymans 2024-04-04 21:17:51 +02:00
parent 9cb4d820d5
commit 74de723ecc
2 changed files with 29 additions and 24 deletions

View file

@ -1888,13 +1888,16 @@ static inline void signal_sync(struct client *c)
state->pending, state->required); state->pending, state->required);
if (pw_node_activation_state_dec(state)) { if (pw_node_activation_state_dec(state)) {
l->activation->status = PW_NODE_ACTIVATION_TRIGGERED; if (SPA_ATOMIC_CAS(l->activation->status,
l->activation->signal_time = nsec; PW_NODE_ACTIVATION_NOT_TRIGGERED,
PW_NODE_ACTIVATION_TRIGGERED)) {
l->activation->signal_time = nsec;
pw_log_trace_fp("%p: signal %p %p", c, l, state); pw_log_trace_fp("%p: signal %p %p", c, l, state);
if (SPA_UNLIKELY(write(l->signalfd, &cmd, sizeof(cmd)) != sizeof(cmd))) if (SPA_UNLIKELY(write(l->signalfd, &cmd, sizeof(cmd)) != sizeof(cmd)))
pw_log_warn("%p: write failed %m", c); pw_log_warn("%p: write failed %m", c);
}
} }
} }
} }

View file

@ -1210,10 +1210,17 @@ static inline uint64_t get_time_ns(struct spa_system *system)
return SPA_TIMESPEC_TO_NSEC(&ts); return SPA_TIMESPEC_TO_NSEC(&ts);
} }
static inline void wake_target(struct pw_node_target *t) static inline void wake_target(struct pw_node_target *t, uint64_t nsec)
{ {
if (SPA_UNLIKELY(spa_system_eventfd_write(t->system, t->fd, 1) < 0)) struct pw_node_activation *a = t->activation;
pw_log_warn("%p: write failed %m", t->node);
if (SPA_ATOMIC_CAS(a->status,
PW_NODE_ACTIVATION_NOT_TRIGGERED,
PW_NODE_ACTIVATION_TRIGGERED)) {
a->signal_time = nsec;
if (SPA_UNLIKELY(spa_system_eventfd_write(t->system, t->fd, 1) < 0))
pw_log_warn("%p: write failed %m", t->node);
}
} }
/* called from data-loop decrement the dependency counter of the target and when /* called from data-loop decrement the dependency counter of the target and when
@ -1226,22 +1233,20 @@ static inline void trigger_target(struct pw_node_target *t, uint64_t nsec)
pw_log_trace_fp("%p: (%s-%u) state:%p pending:%d/%d", t->node, pw_log_trace_fp("%p: (%s-%u) state:%p pending:%d/%d", t->node,
t->name, t->id, state, state->pending, state->required); t->name, t->id, state, state->pending, state->required);
if (pw_node_activation_state_dec(state)) { if (pw_node_activation_state_dec(state))
a->status = PW_NODE_ACTIVATION_TRIGGERED; wake_target(t, nsec);
a->signal_time = nsec;
wake_target(t);
}
} }
/* called from data-loop when all the targets of a node need to be triggered */ /* called from data-loop when all the targets of a node need to be triggered */
static inline int trigger_targets(struct pw_impl_node *this, int status, uint64_t nsec) static inline int trigger_targets(struct pw_node_target *t, int status, uint64_t nsec)
{ {
struct pw_node_target *t; struct pw_node_target *ta;
pw_log_trace_fp("%p: %s trigger targets %"PRIu64, this, this->name, nsec); pw_log_trace_fp("%p: (%s-%u) trigger targets %"PRIu64,
t->node, t->name, t->id, nsec);
spa_list_for_each(t, &this->rt.target_list, link) spa_list_for_each(ta, &t->node->rt.target_list, link)
trigger_target(t, nsec); trigger_target(ta, nsec);
return 0; return 0;
} }
@ -1323,7 +1328,7 @@ static inline int process_node(void *data)
/* we don't need to trigger targets when the node was driving the /* we don't need to trigger targets when the node was driving the
* graph because that means we finished the graph. */ * graph because that means we finished the graph. */
if (SPA_LIKELY(!this->driving)) { if (SPA_LIKELY(!this->driving)) {
trigger_targets(this, status, nsec); trigger_targets(&this->rt.target, status, nsec);
} else { } else {
/* calculate CPU time when finished */ /* calculate CPU time when finished */
a->signal_time = this->driver_start; a->signal_time = this->driver_start;
@ -1852,7 +1857,7 @@ static int node_ready(void *data, int status)
" pending %d/%d", node->name, node->info.id, " pending %d/%d", node->name, node->info.id,
state, a->position.clock.duration, state, a->position.clock.duration,
pending, state->required); pending, state->required);
wake_target(&node->rt.target); wake_target(&node->rt.target, nsec);
check_states(node, nsec); check_states(node, nsec);
pw_impl_node_rt_emit_incomplete(node); pw_impl_node_rt_emit_incomplete(node);
} }
@ -1912,9 +1917,6 @@ again:
a->prev_signal_time = a->signal_time; a->prev_signal_time = a->signal_time;
node->driver_start = nsec; node->driver_start = nsec;
a->status = PW_NODE_ACTIVATION_TRIGGERED;
a->signal_time = nsec;
a->sync_timeout = SPA_MIN(min_timeout, DEFAULT_SYNC_TIMEOUT); a->sync_timeout = SPA_MIN(min_timeout, DEFAULT_SYNC_TIMEOUT);
if (SPA_UNLIKELY(reposition_target != NULL)) { if (SPA_UNLIKELY(reposition_target != NULL)) {
@ -1946,7 +1948,7 @@ again:
spa_node_process_fast(p->mix); spa_node_process_fast(p->mix);
} }
/* now signal all the nodes we drive */ /* now signal all the nodes we drive */
return trigger_targets(node, status, nsec); return trigger_targets(&node->rt.target, status, nsec);
} }
static int node_reuse_buffer(void *data, uint32_t port_id, uint32_t buffer_id) static int node_reuse_buffer(void *data, uint32_t port_id, uint32_t buffer_id)