itersolve: Don't call trapq_check_sentinels() from itersolve_generate_steps()

Commit a89694ac changed the code to run itersolve_generate_steps()
from multiple threads simultaneously.  However,
trapq_check_sentinels() can modify the shared trapq object.  So,
calling it from multiple threads could introduce a race condition.

Move the call to trapq_check_sentinels() to steppersyncmgr_gen_steps()
to avoid the issue.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor
2025-09-24 18:52:10 -04:00
parent 1da2e39b85
commit 3c01f71d9e
2 changed files with 12 additions and 1 deletions

View File

@@ -151,7 +151,6 @@ itersolve_generate_steps(struct stepper_kinematics *sk, struct stepcompress *sc
sk->last_flush_time = flush_time;
if (!sk->tq)
return 0;
trapq_check_sentinels(sk->tq);
struct move *m = list_first_entry(&sk->tq->moves, struct move, node);
while (last_flush_time >= m->print_time + m->move_t)
m = list_next_entry(m, node);

View File

@@ -21,6 +21,7 @@
#include "serialqueue.h" // struct queue_message
#include "stepcompress.h" // stepcompress_flush
#include "steppersync.h" // steppersync_alloc
#include "trapq.h" // trapq_check_sentinels
/****************************************************************
@@ -397,6 +398,17 @@ steppersyncmgr_gen_steps(struct steppersyncmgr *ssm, double flush_time
, double gen_steps_time, double clear_history_time)
{
struct steppersync *ss;
// Prepare trapqs for step generation
list_for_each_entry(ss, &ssm->ss_list, ssm_node) {
struct syncemitter *se;
list_for_each_entry(se, &ss->se_list, ss_node) {
if (!se->sc || !se->sk)
continue;
struct trapq *tq = itersolve_get_trapq(se->sk);
if (tq)
trapq_check_sentinels(tq);
}
}
// Start step generation threads
list_for_each_entry(ss, &ssm->ss_list, ssm_node) {
uint64_t flush_clock = clock_from_time(&ss->ce, flush_time);