[chrony-dev] [PATCH] Support multiple extpps refclocks on a single PHC device |
[ Thread Index |
Date Index
| More chrony.tuxfamily.org/chrony-dev Archives
]
- To: chrony-dev@xxxxxxxxxxxxxxxxxxxx
- Subject: [chrony-dev] [PATCH] Support multiple extpps refclocks on a single PHC device
- From: Matt Corallo <ntp-lists@xxxxxxxxxxxxxxx>
- Date: Sun, 19 Feb 2023 21:23:38 -0800
- Dkim-signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mattcorallo.com; s=1676869262; h=Subject:From:To:From:Subject:To:Cc:Cc: Reply-To:In-Reply-To:References; bh=mPA0MnBj+BORggyn4qlAAa9LfJ8Yh1lw4604vUXkU7o=; b=AnlN1Q/UwO5vdNUw/X77X0ejBV WSY0Qi7zsw9nmP60VPo+prlwiXNy3vFlHJi0kXQP9p8wXzvO5i/Y2vu7cAfn2cMnJJcae0KfjtNlf DVOK8Mh2rkU7Ag4Z6BU9wB4NJ2tg3t1rTaKkgkRdpW7GpjxceI9EX9nsl73mYTRP8p2u9TWmqn+Lz gMByH9o5UUWPLcrZ9+FqQGgPqlnGDDyFUgxZAgcWGZPX9CakhIz0cUTlFMfOAzQXTXnezxUO5rrla 9aLZbFvIJ09A03dtYzuHhqDyPF6NtnKSPHKU+fhCbN9N6H22E5JcLkMMxOZOvh7pCbKIIZ9mlQYJV TjRp8B8w==;
- Dkim-signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=clients.mail.as397444.net; s=1676869263; h=Subject:From:To:From:Subject:To: Cc:Cc:Reply-To:In-Reply-To:References; bh=mPA0MnBj+BORggyn4qlAAa9LfJ8Yh1lw4604vUXkU7o=; b=Sk2QLrvxBrXuoduNcPoFMIRPlR phaqsKGuv73Zpr7lop8XSuemh9QTDBlGWgb+mbVa6YQjCHYFjwD3A1dcGKpjt8JTt4r56OC1/ZiZv osgjHlzzyHK29OkLl+Ilr+o5Dx7EwdLQCH6v/qqfipm3HTqWvF1MGU4xLirABRR/SpbKBdehOPB4z 1mwcsyI3m9PfB4dmZe42XmELijLc/25zC7P/k8F9CcqMjvEocllvq8K6TP5u9w2YF1zGIEthTkth5 Hncu9Uum0i53zMII48RjlrEy0WbZnSDvxBf16pBwT32ws+Sql1tUoYvi6brqfaBqiZ00771Ja0zp2 4lzhOsSQ==;
On Linux, an extpps pin on a PHC device firing will only be read
once. If there are multiple sockets to that PHC device (even across
channels), the event will only be read by the first reader to get
to the kernel.
This poses a problem for chrony - if we have two PHC extpps
refclocks both reading from the same device, we'll only get a
sample if the refclock listening on the right channel happens to be
the one that gets the sample. To avoid this, we have to queue up
samples with a mismatched channel, which we do here in a simple
static buffer, scanning for missed samples when the PHC driver is
polled.
---
refclock_phc.c | 78 ++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 70 insertions(+), 8 deletions(-)
diff --git a/refclock_phc.c b/refclock_phc.c
index e0e206e..10b942d 100644
--- a/refclock_phc.c
+++ b/refclock_phc.c
@@ -42,6 +42,19 @@
#include "sched.h"
#include "sys_linux.h"
+#include <pthread.h>
+struct phc_unknown_channel_data {
+ char valid;
+ int channel;
+ const char *path;
+ struct timespec phc_ts;
+};
+
+#define UNKNOWN_CHAN_BUF_SZ 32
+static struct phc_unknown_channel_data unknown_chan_buf[UNKNOWN_CHAN_BUF_SZ];
+static pthread_mutex_t unknown_chan_buf_mtx = PTHREAD_MUTEX_INITIALIZER;
+static char unknown_chan_buf_initd = 0;
+
struct phc_instance {
int fd;
int mode;
@@ -49,6 +62,7 @@ struct phc_instance {
int extpps;
int pin;
int channel;
+ char *path;
HCL_Instance clock;
};
@@ -75,6 +89,9 @@ static int phc_initialise(RCL_Instance instance)
phc->nocrossts = RCL_GetDriverOption(instance, "nocrossts") ? 1 : 0;
phc->extpps = RCL_GetDriverOption(instance, "extpps") ? 1 : 0;
+ phc->path = Malloc(strlen(path));
+ strcpy(phc->path, path);
+
phc->clock = HCL_CreateInstance(0, 16, UTI_Log2ToDouble(RCL_GetDriverPoll(instance)),
RCL_GetPrecision(instance));
@@ -109,17 +126,40 @@ static void phc_finalise(RCL_Instance instance)
SYS_Linux_SetPHCExtTimestamping(phc->fd, phc->pin, phc->channel, 0, 0, 0);
}
+ pthread_mutex_lock(&unknown_chan_buf_mtx);
+ for (int i = 0; i < UNKNOWN_CHAN_BUF_SZ; i++) {
+ if (unknown_chan_buf[i].path == phc->path) {
+ unknown_chan_buf[i].valid = 0;
+ }
+ }
+ pthread_mutex_unlock(&unknown_chan_buf_mtx);
+
HCL_DestroyInstance(phc->clock);
close(phc->fd);
+ Free(phc->path);
Free(phc);
}
+static void handle_ext_pulse(RCL_Instance instance, struct timespec phc_ts)
+{
+ struct phc_instance *phc;
+ struct timespec local_ts;
+ double local_err;
+
+ phc = RCL_GetDriverData(instance);
+
+ if (!HCL_CookTime(phc->clock, &phc_ts, &local_ts, &local_err))
+ return;
+
+ RCL_AddCookedPulse(instance, &local_ts, 1.0e-9 * local_ts.tv_nsec, local_err,
+ UTI_DiffTimespecsToDouble(&phc_ts, &local_ts));
+}
+
static void read_ext_pulse(int fd, int event, void *anything)
{
RCL_Instance instance;
struct phc_instance *phc;
- struct timespec phc_ts, local_ts;
- double local_err;
+ struct timespec phc_ts;
int channel;
instance = anything;
@@ -130,14 +170,23 @@ static void read_ext_pulse(int fd, int event, void *anything)
if (channel != phc->channel) {
DEBUG_LOG("Unexpected extts channel %d\n", channel);
+ pthread_mutex_lock(&unknown_chan_buf_mtx);
+ if (!unknown_chan_buf_initd) {
+ for (int i = 0; i < UNKNOWN_CHAN_BUF_SZ; i++) unknown_chan_buf[i].valid = 0;
+ unknown_chan_buf_initd = 1;
+ }
+ int wrpos = phc_ts.tv_nsec % UNKNOWN_CHAN_BUF_SZ;
+ for (int i = 0; i < UNKNOWN_CHAN_BUF_SZ; i++) {
+ if (!unknown_chan_buf[i].valid) wrpos = i;
+ }
+ unknown_chan_buf[wrpos].channel = channel;
+ unknown_chan_buf[wrpos].path = phc->path;
+ unknown_chan_buf[wrpos].phc_ts = phc_ts;
+ unknown_chan_buf[wrpos].valid = 1;
+ pthread_mutex_unlock(&unknown_chan_buf_mtx);
return;
}
-
- if (!HCL_CookTime(phc->clock, &phc_ts, &local_ts, &local_err))
- return;
-
- RCL_AddCookedPulse(instance, &local_ts, 1.0e-9 * local_ts.tv_nsec, local_err,
- UTI_DiffTimespecsToDouble(&phc_ts, &local_ts));
+ handle_ext_pulse(instance, phc_ts);
}
#define PHC_READINGS 25
@@ -162,6 +211,19 @@ static int phc_poll(RCL_Instance instance)
LCL_CookTime(&sys_ts, &local_ts, &local_err);
HCL_AccumulateSample(phc->clock, &phc_ts, &local_ts, phc_err + local_err);
+ pthread_mutex_lock(&unknown_chan_buf_mtx);
+ if (!unknown_chan_buf_initd) {
+ for (int i = 0; i < UNKNOWN_CHAN_BUF_SZ; i++) unknown_chan_buf[i].valid = 0;
+ unknown_chan_buf_initd = 1;
+ }
+ for (int i = 0; i < UNKNOWN_CHAN_BUF_SZ; i++) {
+ if (!unknown_chan_buf[i].valid) continue;
+ if (unknown_chan_buf[i].channel != phc->channel) continue;
+ if (strcmp(unknown_chan_buf[i].path, phc->path)) continue;
+ handle_ext_pulse(instance, unknown_chan_buf[i].phc_ts);
+ }
+ pthread_mutex_unlock(&unknown_chan_buf_mtx);
+
if (phc->extpps)
return 0;
--
2.39.1
--
To unsubscribe email chrony-dev-request@xxxxxxxxxxxxxxxxxxxx with "unsubscribe" in the subject.
For help email chrony-dev-request@xxxxxxxxxxxxxxxxxxxx with "help" in the subject.
Trouble? Email listmaster@xxxxxxxxxxxxxxxxxxxx.