From 385754c2d00ba3f4c74a22f55d4756e101f215b1 Mon Sep 17 00:00:00 2001 From: eunhhu Date: Wed, 30 Sep 2026 03:17:59 +0100 Subject: Wait on the monotonic clock everywhere a deadline is waited for Review 004's timer fix (103) counted the deadlines on the monotonic clock, but the owner still slept until a wall-clock time: with the clock set back an hour a node's timers would stop for that hour. So would a wire's pause between tries, and a lone commit after a group would wait an hour for the others to join it. The test's LD_PRELOAD moves only what the process reads, so there each wait ended at once instead, and the timers went on ticking while the owner spun a core. core/wait.h makes conditions that wait on the monotonic clock (pthread_condattr_setclock; macOS keeps the wall clock) and deadlines on it. The owner's waits, the wire's pauses and the group commit's gathering use them. clock-back.so can now move the clock forward too (CLOCK_SHIFT_S), and check.py server_clocks moves it an hour each way under a node with a timer and a wire to a port no one listens on, and under a document server whose three threads commit together, then one alone. Before: back, 159 % CPU and 50,886 tries in 1.2 s; forward, 1 tick, 1 try, and a lone commit that never ended. After: 59 ticks, 0 % CPU, 4 tries and a lone commit of 2.6 ms, both ways. --- serve/deliver.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'serve/deliver.c') diff --git a/serve/deliver.c b/serve/deliver.c index 68c5f14..511a2cf 100644 --- a/serve/deliver.c +++ b/serve/deliver.c @@ -1,5 +1,6 @@ #define _POSIX_C_SOURCE 200809L #include "deliver.h" +#include "wait.h" #include "seal.h" #include "message-json.h" #include "module-text.h" @@ -222,7 +223,7 @@ PureWire *pure_wire_open(const PureModule *m, const char *output, const char *ur w->tls = tls; w->answer_input = -1; pthread_mutex_init(&w->lock, NULL); - pthread_cond_init(&w->changed, NULL); + pure_cond_monotonic(&w->changed); return w; } @@ -738,11 +739,7 @@ static void *deliver(void *context) { } pause_ms = outcome != AGAIN ? LONGEST_PAUSE_MS : pause_ms ? 2 * pause_ms : FIRST_PAUSE_MS; if (pause_ms > LONGEST_PAUSE_MS) pause_ms = LONGEST_PAUSE_MS; - struct timespec until; - clock_gettime(CLOCK_REALTIME, &until); - until.tv_sec += pause_ms / 1000; - until.tv_nsec += (pause_ms % 1000) * 1000000; - if (until.tv_nsec >= 1000000000) { ++until.tv_sec; until.tv_nsec -= 1000000000; } + struct timespec until = pure_wait_until(pause_ms * 1000000LL); while (!w->stopping && pthread_cond_timedwait(&w->changed, &w->lock, &until) == 0) {} } pthread_mutex_unlock(&w->lock); -- cgit v1.2.3