From 59d7cd613783ba2522814f046148083b16d83440 Mon Sep 17 00:00:00 2001 From: Mike Purvis Date: Wed, 25 Jun 2025 11:43:16 -0400 Subject: [PATCH] Changes from Jan for sleep_monotonic --- src/dep/net.c | 80 +++++++++++++-------------------- src/dep/ntpengine/ntpdcontrol.c | 1 + src/dep/ptpd_dep.h | 1 + src/dep/startup.c | 4 +- src/dep/sys.c | 17 +++++++ src/protocol.c | 6 +-- src/signaling.c | 2 +- 7 files changed, 57 insertions(+), 54 deletions(-) diff --git a/src/dep/net.c b/src/dep/net.c index 7e185728..b5f619ac 100644 --- a/src/dep/net.c +++ b/src/dep/net.c @@ -693,65 +693,49 @@ getTxTimestamp(NetPath* netPath,TimeInternal* timeStamp) { ssize_t length; fd_set tmpSet; struct timeval timeOut = {0,0}; - int val = 1; + /* int val = 1; */ int i = 0; + int rc; if(netPath->txTimestampFailure) goto failure; FD_ZERO(&tmpSet); FD_SET(netPath->eventSock, &tmpSet); - if(select(netPath->eventSock + 1, &tmpSet, NULL, NULL, &timeOut) > 0) { - if (FD_ISSET(netPath->eventSock, &tmpSet)) { + do { + if ((rc = select(netPath->eventSock + 1, &tmpSet, NULL, NULL, &timeOut)) > 0) { + if (FD_ISSET(netPath->eventSock, &tmpSet)) { - length = netRecvEvent(G_ptpClock->msgIbuf, timeStamp, - netPath, MSG_ERRQUEUE); - if (length > 0) { - DBG("getTxTimestamp: Grabbed sent msg via errqueue: %d bytes, at %d.%d\n", length, timeStamp->seconds, timeStamp->nanoseconds); - return TRUE; - } else if (length < 0) { - DBG("getTxTimestamp: Failed to poll error queue for SO_TIMESTAMPING transmit time\n"); - G_ptpClock->counters.messageRecvErrors++; - } else if (length == 0) { - DBG("getTxTimestamp: Received no data from TX error queue\n"); - } - } - } - - /* we're desperate here, aren't we... */ - for(i = 0; i < 3; i++) { - length = netRecvEvent(G_ptpClock->msgIbuf, timeStamp, netPath, MSG_ERRQUEUE); - if(length > 0) { - DBG("getTxTimestamp: SO_TIMESTAMPING - delayed TX timestamp caught\n"); + length = netRecvEvent(G_ptpClock->msgIbuf, timeStamp, + netPath, MSG_ERRQUEUE); + if (length > 0) { + DBG("getTxTimestamp: Grabbed sent msg via errqueue: %d bytes, at %d.%d\n", length, timeStamp->seconds, timeStamp->nanoseconds); return TRUE; + } else if (length < 0) { + DBG("getTxTimestamp: Failed to poll error queue for SO_TIMESTAMPING transmit time\n"); + G_ptpClock->counters.messageRecvErrors++; + } else if (length == 0) { + DBG("getTxTimestamp: Received no data from TX error queue\n"); + } } - usleep(10); - } - - /* try for the last time: sleep and poll the error queue, if nothing, consider SO_TIMESTAMPING inoperable */ - usleep(LATE_TXTIMESTAMP_US); - - length = netRecvEvent(G_ptpClock->msgIbuf, timeStamp, netPath, MSG_ERRQUEUE); - - if(length > 0) { - DBG("getTxTimestamp: SO_TIMESTAMPING - even more delayed TX timestamp caught\n"); - return TRUE; - } else { - DBG("getTxTimestamp: SO_TIMESTAMPING - TX timestamp retry failed - will use loop from now on\n"); - } - -failure: - DBG("net.c: SO_TIMESTAMPING TX software timestamp failure - reverting to SO_TIMESTAMPNS\n"); - /* unset SO_TIMESTAMPING first! otherwise we get an always-exiting select! */ - val = 0; - if(setsockopt(netPath->eventSock, SOL_SOCKET, SO_TIMESTAMPING, &val, sizeof(int)) < 0) { - DBG("getTxTimestamp: failed to unset SO_TIMESTAMPING"); - } - val = 1; - if(setsockopt(netPath->eventSock, SOL_SOCKET, SO_TIMESTAMPNS, &val, sizeof(int)) < 0) { - DBG("getTxTimestamp: failed to revert to SO_TIMESTAMPNS"); + } else { + sleep_monotonic(100); + } + } while (rc == -1 && errno == EINTR); + + /* wait for tx stamp */ + for (i = 0; i < 2000; i++) { + sleep_monotonic(500); + length = netRecvEvent(G_ptpClock->msgIbuf, timeStamp, netPath, MSG_ERRQUEUE); + if (length > 0) { + DBG("getTxTimestamp: SO_TIMESTAMPING - delayed TX timestamp caught\n"); + return TRUE; + } } + DBG("getTxTimestamp: SO_TIMESTAMPING - TX timestamp retry failed"); + failure: + return FALSE; } #endif /* SO_TIMESTAMPING */ @@ -2290,7 +2274,7 @@ netRefreshIGMP(NetPath * netPath, const RunTimeOpts * rtOpts, PtpClock * ptpCloc } /* suspend process 100 milliseconds, to make sure the kernel sends the IGMP_leave properly */ - usleep(100*1000); + sleep_monotonic(100000000); if (!netInitMulticast(netPath, rtOpts)) { return FALSE; diff --git a/src/dep/ntpengine/ntpdcontrol.c b/src/dep/ntpengine/ntpdcontrol.c index 0c83adb1..428cae7a 100644 --- a/src/dep/ntpengine/ntpdcontrol.c +++ b/src/dep/ntpengine/ntpdcontrol.c @@ -663,6 +663,7 @@ NTPDCquery( DBG("NTPDCquery(): select EINTR caught"); retries--; res = 1; + sleep_monotonic(1500); continue; } DBG("NTPDCquery(): select() error - not EINTR: %s\n", strerror(errno)); diff --git a/src/dep/ptpd_dep.h b/src/dep/ptpd_dep.h index 10663afb..c6fb6735 100644 --- a/src/dep/ptpd_dep.h +++ b/src/dep/ptpd_dep.h @@ -457,6 +457,7 @@ void displayStatus(PtpClock *ptpClock, const char *prefixMessage); void displayPortIdentity(PortIdentity *port, const char *prefixMessage); int snprint_PortIdentity(char *s, int max_len, const PortIdentity *id); Boolean nanoSleep(TimeInternal*); +int sleep_monotonic(int nanoseconds); void getTime(TimeInternal*); void getTimeMonotonic(TimeInternal*); void setTime(TimeInternal*); diff --git a/src/dep/startup.c b/src/dep/startup.c index a9011736..57505ceb 100644 --- a/src/dep/startup.c +++ b/src/dep/startup.c @@ -879,11 +879,11 @@ ptpdStartup(int argc, char **argv, Integer16 * ret, RunTimeOpts * rtOpts) * On some systems this happened after we tried re-acquiring * the lock, so the lock would fail. Hence, we wait. */ - for (i = 0; i < 1000000; i++) { + for (i = 0; i < 1000; i++) { /* Once we've been reaped by init, parent PID will be 1 */ if(getppid() == 1) break; - usleep(1); + sleep_monotonic(1000000); } } diff --git a/src/dep/sys.c b/src/dep/sys.c index 31553b84..258d84f1 100644 --- a/src/dep/sys.c +++ b/src/dep/sys.c @@ -1408,6 +1408,23 @@ nanoSleep(TimeInternal * t) return TRUE; } +int +sleep_monotonic(int nanoseconds) +{ + int rc; + struct timespec request, remain; + request.tv_sec = 0; + request.tv_nsec = nanoseconds; + + while ((rc = clock_nanosleep(CLOCK_MONOTONIC, 0, &request, &remain)) == EINTR) { + /* restart sleep for the remaining time */ + request.tv_nsec = remain.tv_nsec; + } + + return rc; +} + + #ifdef __QNXNTO__ static const struct sigevent* timerIntHandler(void* data, int id) { diff --git a/src/protocol.c b/src/protocol.c index 1514add2..2f614d3e 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -247,9 +247,9 @@ protocol(RunTimeOpts *rtOpts, PtpClock *ptpClock) * that is keep processing signals. If init failed, wait for n seconds * until next retry, do not exit. Wait in chunks so SIGALRM can interrupt. */ - if(ptpClock->initFailure) { - usleep(10000); - ptpClock->initFailureTimeout--; + if (ptpClock->initFailure) { + sleep_monotonic(10000000); + ptpClock->initFailureTimeout--; } if(!ptpClock->initFailure || ptpClock->initFailureTimeout <= 0) { diff --git a/src/signaling.c b/src/signaling.c index ca341a33..730d30a0 100644 --- a/src/signaling.c +++ b/src/signaling.c @@ -1022,7 +1022,7 @@ cancelNodeGrants(UnicastGrantTable *nodeTable, const RunTimeOpts *rtOpts, PtpClo if(grantData->granted) { cancelUnicastTransmission(grantData, rtOpts, ptpClock); /* sleep 250 to 500 us so that we don't flood the node */ - usleep(250+round(getRand()*250)); + sleep_monotonic((250 + (rand() % 250)) * 1000); } }