commit b4c146daa086436807abcd75157bd9d0a44971cb Author: Miroslav Lichvar Date: Thu Aug 28 15:14:01 2025 +0200 ts2phc: Better handle missing pulses with multiple sinks. The ts2phc_pps_sink_poll() function waits until it has collected pulses for all active sinks, or a timeout of 2 seconds between events is reached. If a sink missed a pulse (e.g. after a port state change and switching PPS signal direction in the external PPS mode) and the next pulse of that sink came before pulses of the other sinks, it was mixed with events of the previous pulse and the measured offset had an error of 1/rate seconds. To avoid mixing events corresponding to different pulses, adjust the poll() timeout so that it waits only up to a third of the pulse period after the first received event. (Rebased to 4.4) Reviewed-by: Jacob Keller Signed-off-by: Miroslav Lichvar diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c index 9076de9..72d8ea4 100644 --- a/ts2phc_pps_sink.c +++ b/ts2phc_pps_sink.c @@ -381,10 +381,11 @@ void ts2phc_pps_sink_cleanup(struct ts2phc_private *priv) int ts2phc_pps_sink_poll(struct ts2phc_private *priv) { struct ts2phc_sink_array *polling_array = priv->polling_array; + bool first_poll = true, ignore_any = false; bool all_sinks_have_events = false; - bool ignore_any = false; + struct timespec first_ts = {0}, ts; + int cnt, timeout; unsigned int i; - int cnt; for (i = 0; i < priv->n_sinks; i++) polling_array->collected_events[i] = 0; @@ -395,7 +396,22 @@ int ts2phc_pps_sink_poll(struct ts2phc_private *priv) if (!is_running()) return 0; - cnt = poll(polling_array->pfd, priv->n_sinks, 2000); + /* + * Collect only events within a third of the pulse period to + * avoid mixing events corresponding to different pulses. + */ + if (first_poll) { + timeout = 2000; + } else { + clock_gettime(CLOCK_MONOTONIC, &ts); + timeout = 333; + timeout -= (ts.tv_sec - first_ts.tv_sec) * 1000 + + (ts.tv_nsec - first_ts.tv_nsec) / 1000000; + if (timeout < 0) + timeout = 0; + } + + cnt = poll(polling_array->pfd, priv->n_sinks, timeout); if (cnt < 0) { if (errno == EINTR) { return 0; @@ -408,6 +424,11 @@ int ts2phc_pps_sink_poll(struct ts2phc_private *priv) return 0; } + if (first_poll) { + clock_gettime(CLOCK_MONOTONIC, &first_ts); + first_poll = false; + } + for (i = 0; i < priv->n_sinks; i++) { if (polling_array->pfd[i].revents & POLLERR) { sink = polling_array->sink[i];