refclock_nmea.c merge cleanup thanks to Juergen Perlinger.
Use mutex with Lamport checks in get_systime() on Windows, which
unlike portable ntpd uses the routine across threads.
bk: 4f447780WcagGVkhY7Nx3Nz2XtBGWg
+* [Bug 2148] ntpd 4.2.7p258 segfault with 0x0100000 bit in NMEA mode.
+* refclock_nmea.c merge cleanup thanks to Juergen Perlinger.
(4.2.7p258) 2012/02/21 Released by Harlan Stenn <stenn@ntp.org>
* [Bug 2140] Rework of Windows I/O completion port handling to avoid
garbling serial input in UNIX line discipline emulation.
#define DEBUG_INVARIANT(x) INVARIANT(x)
#define DEBUG_ENSURE(x) ENSURE(x)
# else
-#define DEBUG_REQUIRE(x) (void)(x)
-#define DEBUG_INSIST(x) (void)(x)
-#define DEBUG_INVARIANT(x) (void)(x)
-#define DEBUG_ENSURE(x) (void)(x)
+#define DEBUG_REQUIRE(x) do {} while (FALSE)
+#define DEBUG_INSIST(x) do {} while (FALSE)
+#define DEBUG_INVARIANT(x) do {} while (FALSE)
+#define DEBUG_ENSURE(x) do {} while (FALSE)
# endif
#endif /* NTP_ASSERT_H */
extern void mfp_mul (int32 *, u_int32 *, int32, u_int32, int32, u_int32);
extern void set_sys_fuzz (double);
+extern void init_systime (void);
extern void get_systime (l_fp *);
extern int step_systime (double);
extern int adj_systime (double);
*/
typedef void (*time_stepped_callback)(void);
extern time_stepped_callback step_callback;
+
+/*
+ * Multi-thread locking for get_systime()
+ *
+ * On most systems, get_systime() is used solely by the main ntpd
+ * thread, but on Windows it's also used by the dedicated I/O thread.
+ * The [Bug 2037] changes to get_systime() have it keep state between
+ * calls to ensure time moves in only one direction, which means its
+ * use on Windows needs to be protected against simultaneous execution
+ * to avoid falsely detecting Lamport violations by ensuring only one
+ * thread at a time is in get_systime().
+ */
+#ifdef SYS_WINNT
+extern CRITICAL_SECTION get_systime_cs;
+# define INIT_GET_SYSTIME_CRITSEC() \
+ InitializeCriticalSection(&get_systime_cs)
+# define ENTER_GET_SYSTIME_CRITSEC() \
+ EnterCriticalSection(&get_systime_cs)
+# define LEAVE_GET_SYSTIME_CRITSEC() \
+ LeaveCriticalSection(&get_systime_cs)
+#else /* !SYS_WINNT follows */
+# define INIT_GET_SYSTIME_CRITSEC() \
+ do {} while (FALSE)
+# define ENTER_GET_SYSTIME_CRITSEC() \
+ do {} while (FALSE)
+# define LEAVE_GET_SYSTIME_CRITSEC() \
+ do {} while (FALSE)
+#endif
+
#endif /* NTP_FP_H */
#include <isc/net.h>
#include <isc/result.h>
+
+#include "ntp_fp.h"
#include "ntp_stdlib.h"
#include "lib_strbuf.h"
+
/*
* Storage declarations
*/
int ipv6_works;
int lib_inited;
+
/*
* initialization routine. Might be needed if the code is ROMized.
*/
return;
ipv4_works = (ISC_R_SUCCESS == isc_net_probeipv4());
ipv6_works = (ISC_R_SUCCESS == isc_net_probeipv6());
+ init_systime();
lib_inited = TRUE;
}
#ifndef SIM
static int lamport_violated; /* clock was stepped back */
+#endif /* !SIM */
+
+#ifdef DEBUG
+static int systime_init_done;
+# define DONE_SYSTIME_INIT() systime_init_done = TRUE
+#else
+# define DONE_SYSTIME_INIT() do {} while (FALSE)
#endif
+#ifdef SYS_WINNT
+CRITICAL_SECTION get_systime_cs;
+#endif
+
void
set_sys_fuzz(
}
+void
+init_systime(void)
+{
+ INIT_GET_SYSTIME_CRITSEC();
+ DONE_SYSTIME_INIT();
+}
+
+
#ifndef SIM /* ntpsim.c has get_systime() and friends for sim */
static inline void
{
static struct timespec ts_prev; /* prior os time */
static l_fp lfp_prev; /* prior result */
+ static double dfuzz_prev; /* prior fuzz */
struct timespec ts; /* seconds and nanoseconds */
struct timespec ts_min; /* earliest permissible */
struct timespec ts_lam; /* lamport fictional increment */
l_fp lfpdelta;
get_ostime(&ts);
+ DEBUG_REQUIRE(systime_init_done);
+ ENTER_GET_SYSTIME_CRITSEC();
/*
* After default_get_precision() has set a nonzero sys_fuzz,
msyslog(LOG_ERR, "ts_min %s ts_prev %s ts %s",
tspectoa(ts_min), tspectoa(ts_prev_log),
tspectoa(ts));
- msyslog(LOG_ERR, "sys_fuzz %ld nsec, this fuzz %.9f",
- sys_fuzz_nsec, dfuzz);
+ msyslog(LOG_ERR, "sys_fuzz %ld nsec, this fuzz %.9f, prior %.9f",
+ sys_fuzz_nsec, dfuzz, dfuzz_prev);
lfpdelta = lfp_prev;
L_SUB(&lfpdelta, &result);
LFPTOD(&lfpdelta, ddelta);
}
}
lfp_prev = result;
+ dfuzz_prev = dfuzz;
if (lamport_violated)
lamport_violated = FALSE;
+ LEAVE_GET_SYSTIME_CRITSEC();
*now = result;
}
break;
case CP_TTL:
- if (p->ttl)
+#ifdef REFCLOCK
+ if (p->flags & FLAG_REFCLOCK) {
+ ctl_putuint(peer_var[id].text, p->ttl);
+ break;
+ }
+#endif
+ if (p->ttl > 0 && p->ttl < COUNTOF(sys_ttl))
ctl_putint(peer_var[id].text,
sys_ttl[p->ttl]);
break;
*tsptr = rbufp->recv_time;
DPRINTF(2, ("refclock_gtlin: fd %d time %s timecode %d %s\n",
rbufp->fd, ulfptoa(&rbufp->recv_time, 6), dlen,
- lineptr));
+ (dlen != 0)
+ ? lineptr
+ : ""));
return (dlen);
}
} while (0); /* 'loop' once */
# endif /* HAVE_WORKING_FORK */
+ init_lib();
# ifdef SYS_WINNT
/*
* Start interpolation thread, must occur before first
init_restrict();
init_mon();
init_timer();
- init_lib();
init_request();
init_control();
init_peer();
tally;
/* per sentence checksum seen flag */
u_char cksum_type[NMEA_ARRAY_SIZE];
- int total_nmea; /* clockstats sentence counts */
- int good_nmea;
- int bad_nmea;
- int filter_nmea;
- int pps_used;
} nmea_unit;
/*
pp->a_lastcode[rd_lencode] = '\0';
pp->lastrec = rd_timestamp;
- if (pp->leap == LEAP_NOTINSYNC) {
- up->bad_nmea++;
- return;
- }
-
- /* Text looks OK. */
- up->good_nmea++;
-
#ifdef HAVE_PPSAPI
/*
* If we have PPS running, we try to associate the sentence
lpo->DCDSTime = lpo->RecvTime;
lpo->flTsDCDS = 1;
DPRINTF(2, ("fd %d DCD PPS at %s\n", rio->fd,
- lfptoa(&lpo->RecvTime, 6)));
+ ulfptoa(&lpo->RecvTime, 6)));
}
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
+ init_lib();
+
// Some tests makes use of extra parameters passed to the tests
// executable. Save these params as static members of the base class.
if (argc > 1) {
#include <gtest/gtest.h>
+extern "C" {
+#include "ntp_stdlib.h"
+}
class ntptest : public ::testing::Test {
public: