During a timer handling we should avoid to call timerfd_settime() on a
different timer because this call will invalidate the file descriptor,
resulting in a EGAIN when the other timer code will performe the read().

The ANNOUNCE and RX SYNC timer code just doesn't follow this rule. The
solution is to split the rearm code.
---
 e2e_tc.c | 26 ++++++++++++++++--------
 p2p_tc.c | 26 ++++++++++++++++--------
 port.c   | 60 ++++++++++++++++++++++++++++++++------------------------
 3 files changed, 70 insertions(+), 42 deletions(-)

diff --git a/e2e_tc.c b/e2e_tc.c
index 43c69e9..c7cfd9e 100644
--- a/e2e_tc.c
+++ b/e2e_tc.c
@@ -74,6 +74,15 @@ void e2e_dispatch(struct port *p, enum fsm_event event, int 
mdiff)
        };
 }
 
+static enum fsm_event e2e_announce_sync_rx_timeout_action(struct port *p)
+{
+       if (p->best) {
+               fc_clear(p->best);
+       }
+       port_set_announce_tmo(p);
+       return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES;
+}
+
 enum fsm_event e2e_event(struct port *p, int fd_index)
 {
        int cnt, fd = p->fda.fd[fd_index];
@@ -82,15 +91,16 @@ enum fsm_event e2e_event(struct port *p, int fd_index)
 
        switch (fd_index) {
        case FD_ANNOUNCE_TIMER:
+               pr_debug("%s: announce timeout", p->log_name);
+               timerfd_flush(p, fd, "announce");
+
+               return e2e_announce_sync_rx_timeout_action(p);
+
        case FD_SYNC_RX_TIMER:
-               pr_debug("%s: %s timeout", p->log_name,
-                        fd_index == FD_SYNC_RX_TIMER ? "rx sync" : "announce");
-               timerfd_flush(p, fd, fd_index == FD_SYNC_RX_TIMER ? "rx sync" : 
"announce");
-               if (p->best) {
-                       fc_clear(p->best);
-               }
-               port_set_announce_tmo(p);
-               return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES;
+               pr_debug("%s: rx sync timeout", p->log_name);
+               timerfd_flush(p, fd, "rx sync");
+
+               return e2e_announce_sync_rx_timeout_action(p);
 
        case FD_DELAY_TIMER:
                pr_debug("%s: delay timeout", p->log_name);
diff --git a/p2p_tc.c b/p2p_tc.c
index 55a4b1c..0d6d68b 100644
--- a/p2p_tc.c
+++ b/p2p_tc.c
@@ -90,6 +90,15 @@ void p2p_dispatch(struct port *p, enum fsm_event event, int 
mdiff)
        };
 }
 
+static enum fsm_event p2p_announce_sync_rx_timeout_action(struct port *p)
+{
+       if (p->best) {
+               fc_clear(p->best);
+       }
+       port_set_announce_tmo(p);
+       return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES;
+}
+
 enum fsm_event p2p_event(struct port *p, int fd_index)
 {
        int cnt, fd = p->fda.fd[fd_index];
@@ -98,15 +107,16 @@ enum fsm_event p2p_event(struct port *p, int fd_index)
 
        switch (fd_index) {
        case FD_ANNOUNCE_TIMER:
+               pr_debug("%s: announce timeout", p->log_name);
+               timerfd_flush(p, fd, "announce");
+
+               return p2p_announce_sync_rx_timeout_action(p);
+
        case FD_SYNC_RX_TIMER:
-               pr_debug("%s: %s timeout", p->log_name,
-                        fd_index == FD_SYNC_RX_TIMER ? "rx sync" : "announce");
-               timerfd_flush(p, fd, fd_index == FD_SYNC_RX_TIMER ? "rx sync" : 
"announce");
-               if (p->best) {
-                       fc_clear(p->best);
-               }
-               port_set_announce_tmo(p);
-               return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES;
+               pr_debug("%s: rx sync timeout", p->log_name);
+               timerfd_flush(p, fd, "rx sync");
+
+               return p2p_announce_sync_rx_timeout_action(p);
 
        case FD_DELAY_TIMER:
                pr_debug("%s: delay timeout", p->log_name);
diff --git a/port.c b/port.c
index e38f244..cc558eb 100644
--- a/port.c
+++ b/port.c
@@ -2842,6 +2842,24 @@ enum fsm_event port_event(struct port *p, int fd_index)
        return p->event(p, fd_index);
 }
 
+static enum fsm_event bc_announce_sync_rx_timeout_action(struct port *p)
+{
+       if (p->best) {
+               fc_clear(p->best);
+       }
+
+       delay_req_prune(p);
+       if (clock_slave_only(p->clock) && p->delayMechanism != DM_P2P &&
+               port_renew_transport(p)) {
+               return EV_FAULT_DETECTED;
+       }
+
+       if (p->inhibit_announce) {
+               return EV_NONE;
+       }
+       return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES;
+}
+
 static enum fsm_event bc_event(struct port *p, int fd_index)
 {
        enum fsm_event event = EV_NONE;
@@ -2850,20 +2868,25 @@ static enum fsm_event bc_event(struct port *p, int 
fd_index)
 
        switch (fd_index) {
        case FD_ANNOUNCE_TIMER:
-       case FD_SYNC_RX_TIMER:
-               pr_debug("%s: %s timeout", p->log_name,
-                        fd_index == FD_SYNC_RX_TIMER ? "rx sync" : "announce");
-               timerfd_flush(p, fd, fd_index == FD_SYNC_RX_TIMER ? "rx sync" : 
"announce");
-               if (p->best) {
-                       fc_clear(p->best);
-               }
+               pr_debug("%s: announce timeout", p->log_name);
+               timerfd_flush(p, fd, "announce");
 
-               if (fd_index == FD_SYNC_RX_TIMER) {
-                       p->service_stats.sync_timeout++;
+               p->service_stats.announce_timeout++;
+               
+               if (p->inhibit_announce) {
+                       port_clr_tmo(p->fda.fd[FD_ANNOUNCE_TIMER]);
                } else {
-                       p->service_stats.announce_timeout++;
+                       port_set_announce_tmo(p);
                }
 
+               return bc_announce_sync_rx_timeout_action(p);
+
+       case FD_SYNC_RX_TIMER:
+               pr_debug("%s: rx sync timeout", p->log_name);
+               timerfd_flush(p, fd, "rx sync");
+
+               p->service_stats.sync_timeout++;
+
                /*
                 * Clear out the event returned by poll(). It is only cleared
                 * in port_*_transition(). But, when BMCA == 'noop', there is no
@@ -2873,22 +2896,7 @@ static enum fsm_event bc_event(struct port *p, int 
fd_index)
                        port_clr_tmo(p->fda.fd[FD_SYNC_RX_TIMER]);
                }
 
-               if (p->inhibit_announce) {
-                       port_clr_tmo(p->fda.fd[FD_ANNOUNCE_TIMER]);
-               } else {
-                       port_set_announce_tmo(p);
-               }
-
-               delay_req_prune(p);
-               if (clock_slave_only(p->clock) && p->delayMechanism != DM_P2P &&
-                   port_renew_transport(p)) {
-                       return EV_FAULT_DETECTED;
-               }
-
-               if (p->inhibit_announce) {
-                       return EV_NONE;
-               }
-               return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES;
+               return bc_announce_sync_rx_timeout_action(p);
 
        case FD_DELAY_TIMER:
                pr_debug("%s: delay timeout", p->log_name);
-- 
2.40.0



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to