Skip to content

Commit

Permalink
Use periodic timer for TX SYNC timeout.
Browse files Browse the repository at this point in the history
In order to obtain a precise TX SYNC frequency we need to use a periodic
timer facility instead to reconfigure the timer on every expiration.

The solution consists to configure the it_interval field of the
itimerspec structure (see timerfd_create(2) man page) only when the port
goes into Master role and avoiding to call timerfd_settime() on timer
expiration.
  • Loading branch information
comio committed Jul 6, 2023
1 parent 4e0e7f9 commit 6084501
Showing 1 changed file with 12 additions and 3 deletions.
15 changes: 12 additions & 3 deletions port.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ struct fdarray *port_fda(struct port *port)
return &port->fda;
}

int set_tmo_log(int fd, unsigned int scale, int log_seconds)
static int set_tmo_log_periodic(int fd, unsigned int scale, int log_seconds, bool periodic)
{
struct itimerspec tmo = {
{0, 0}, {0, 0}
Expand All @@ -255,9 +255,19 @@ int set_tmo_log(int fd, unsigned int scale, int log_seconds)
} else
tmo.it_value.tv_sec = scale * (1 << log_seconds);

if (periodic) {
tmo.it_interval.tv_nsec = tmo.it_value.tv_nsec;
tmo.it_interval.tv_sec = tmo.it_value.tv_sec;
}

return timerfd_settime(fd, 0, &tmo, NULL);
}

int set_tmo_log(int fd, unsigned int scale, int log_seconds)
{
return set_tmo_log_periodic(fd, scale, log_seconds, false);
}

int set_tmo_lin(int fd, int seconds)
{
struct itimerspec tmo = {
Expand Down Expand Up @@ -1297,7 +1307,7 @@ int port_set_sync_rx_tmo(struct port *p)

static int port_set_sync_tx_tmo(struct port *p)
{
return set_tmo_log(p->fda.fd[FD_SYNC_TX_TIMER], 1, p->logSyncInterval);
return set_tmo_log_periodic(p->fda.fd[FD_SYNC_TX_TIMER], 1, p->logSyncInterval, true);
}

void port_show_transition(struct port *p, enum port_state next,
Expand Down Expand Up @@ -2936,7 +2946,6 @@ static enum fsm_event bc_event(struct port *p, int fd_index)
case FD_SYNC_TX_TIMER:
pr_debug("%s: master sync timeout", p->log_name);
timerfd_flush(p, fd, "master sync timeout");
port_set_sync_tx_tmo(p);
p->service_stats.master_sync_timeout++;
return port_tx_sync(p, NULL, p->seqnum.sync++) ?
EV_FAULT_DETECTED : EV_NONE;
Expand Down

0 comments on commit 6084501

Please sign in to comment.