* Ephemeral state variables
*/
u_char status; /* peer status */
+ u_char new_status; /* under-construction status */
u_char reach; /* reachability register */
int flash; /* protocol error test tally bits */
u_long epoch; /* reference epoch */
* Values for peer.flags
*/
#define FLAG_CONFIG 0x0001 /* association was configured */
-#define FLAG_PREEMPT 0x0002 /* preemptable association */
+#define FLAG_PREEMPT 0x0002 /* preemptable association */
#define FLAG_AUTHENTIC 0x0004 /* last message was authentic */
#define FLAG_REFCLOCK 0x0008 /* this is actually a reference clock */
-#define FLAG_SYSPEER 0x0010 /* system peer */
-#define FLAG_PREFER 0x0020 /* prefer peer */
-#define FLAG_BURST 0x0040 /* burst mode */
-#define FLAG_PPS 0x0080 /* steered by PPS */
-#define FLAG_IBURST 0x0100 /* initial burst mode */
-#define FLAG_NOSELECT 0x0200 /* never select */
-#define FLAG_TRUE 0x0400 /* force truechimer */
-#define FLAG_SKEY 0x0800 /* autokey authentication */
+#define FLAG_PREFER 0x0020 /* prefer peer */
+#define FLAG_BURST 0x0040 /* burst mode */
+#define FLAG_PPS 0x0080 /* steered by PPS */
+#define FLAG_IBURST 0x0100 /* initial burst mode */
+#define FLAG_NOSELECT 0x0200 /* never select */
+#define FLAG_TRUE 0x0400 /* force truechimer */
+#define FLAG_SKEY 0x0800 /* autokey authentication */
#define FLAG_XLEAVE 0x1000 /* interleaved protocol */
#define FLAG_XB 0x2000 /* interleaved broadcast */
#define FLAG_XBOGUS 0x4000 /* interleaved bogus packet */
double sys_mindisp = MINDISPERSE; /* minimum distance (s) */
double sys_maxdist = MAXDISTANCE; /* selection threshold */
double sys_jitter; /* system jitter */
-u_long sys_epoch; /* last clock update time */
+u_long sys_epoch; /* last clock update time */
static double sys_clockhop; /* clockhop threshold */
int leap_tai; /* TAI at next next leap */
u_long leap_sec; /* next scheduled leap from file */
/*
* A sample consists of the offset, delay, dispersion and epoch
* of arrival. The offset and delay are determined by the on-
- * wire protcol. The dispersion grows from the last outbound
+ * wire protocol. The dispersion grows from the last outbound
* packet to the arrival of this one increased by the sum of the
* peer precision and the system precision as required by the
* error budget. First, shift the new arrival into the shift
* save the offset, delay and jitter. Note the jitter must not
* be less than the precision.
*/
- if (m == 0)
+ if (m == 0) {
+ clock_select();
return;
+ }
etemp = fabs(peer->offset - peer->filter_offset[k]);
peer->offset = peer->filter_offset[k];
for (n = 0; n < NTP_HASH_SIZE; n++) {
for (peer = peer_hash[n]; peer != NULL; peer =
peer->next) {
- peer->flags &= ~FLAG_SYSPEER;
- peer->status = CTL_PST_SEL_REJECT;
+ peer->new_status = CTL_PST_SEL_REJECT;
/*
* Leave the island immediately if the peer is
* The following are special cases. We deal
* with them later.
*/
- switch (peer->refclktype) {
- case REFCLK_LOCALCLOCK:
- if (typelocal == NULL &&
- !(peer->flags & FLAG_PREFER))
- typelocal = peer;
- continue;
-
- case REFCLK_ACTS:
- if (typeacts == NULL &&
- !(peer->flags & FLAG_PREFER))
- typeacts = peer;
- continue;
+ if (!(peer->flags & FLAG_PREFER)) {
+ switch (peer->refclktype) {
+ case REFCLK_LOCALCLOCK:
+ if (typelocal == NULL)
+ typelocal = peer;
+ continue;
+
+ case REFCLK_ACTS:
+ if (typeacts == NULL)
+ typeacts = peer;
+ continue;
+ }
}
#endif /* REFCLOCK */
* island, but does not yet have the immunity
* idol.
*/
- peer->status = CTL_PST_SEL_SANE;
+ peer->new_status = CTL_PST_SEL_SANE;
peer_list[nlist++] = peer;
/*
*
* Here, nlist is the number of candidates and allow is the
* number of falsetickers. Upon exit, the truechimers are the
- * susvivors with offsets not less than low and not greater than
+ * survivors with offsets not less than low and not greater than
* high. There may be none of them.
*/
low = 1e9;
#ifdef REFCLOCK
/*
- * Elegible PPS peers must survive the intersection
+ * Eligible PPS peers must survive the intersection
* algorithm. Use the first one found, but don't
* include any of them in the cluster population.
*/
} else if (typelocal != NULL) {
peer_list[0] = typelocal;
nlist = 1;
- }
+ } else
#endif /* REFCLOCK */
if (typeorphan != NULL) {
peer_list[0] = typeorphan;
* Mark the candidates at this point as truechimers.
*/
for (i = 0; i < nlist; i++) {
- peer_list[i]->status = CTL_PST_SEL_SELCAND;
+ peer_list[i]->new_status = CTL_PST_SEL_SELCAND;
#ifdef DEBUG
if (debug > 1)
printf("select: survivor %s %f\n",
ntoa(&peer_list[k]->srcadr), g, d);
#endif
if (nlist > sys_maxclock)
- peer_list[k]->status = CTL_PST_SEL_EXCESS;
+ peer_list[k]->new_status = CTL_PST_SEL_EXCESS;
for (j = k + 1; j < nlist; j++) {
peer_list[j - 1] = peer_list[j];
synch[j - 1] = synch[j];
for (i = 0; i < nlist; i++) {
peer = peer_list[i];
peer->unreach = 0;
- peer->status = CTL_PST_SEL_SYNCCAND;
+ peer->new_status = CTL_PST_SEL_SYNCCAND;
sys_survivors++;
if (peer->leap == LEAP_ADDSECOND) {
if (peer->flags & FLAG_REFCLOCK)
*/
if (typesystem != NULL) {
if (sys_prefer == NULL) {
- typesystem->status = CTL_PST_SEL_SYSPEER;
+ typesystem->new_status = CTL_PST_SEL_SYSPEER;
clock_combine(peer_list, sys_survivors);
sys_jitter = SQRT(SQUARE(typesystem->jitter) +
SQUARE(sys_jitter) + SQUARE(seljitter));
} else {
typesystem = sys_prefer;
sys_clockhop = 0;
- typesystem->status = CTL_PST_SEL_SYSPEER;
+ typesystem->new_status = CTL_PST_SEL_SYSPEER;
sys_offset = typesystem->offset;
sys_jitter = typesystem->jitter;
}
NULL || (typesystem == NULL && sys_minsane == 0))))) {
typesystem = typepps;
sys_clockhop = 0;
- typesystem->status = CTL_PST_SEL_PPS;
+ typesystem->new_status = CTL_PST_SEL_PPS;
sys_offset = typesystem->offset;
sys_jitter = typesystem->jitter;
#ifdef DEBUG
if (osys_peer != NULL)
report_event(EVNT_NOPEER, NULL, NULL);
sys_peer = NULL;
+ for (n = 0; n < NTP_HASH_SIZE; n++)
+ for (peer = peer_hash[n]; peer != NULL; peer =
+ peer->next)
+ peer->status = peer->new_status;
return;
}
/*
* We have found the alpha male. Wind the clock.
*/
- if (osys_peer != typesystem)
+ if (osys_peer != typesystem)
report_event(PEVNT_NEWPEER, typesystem, NULL);
- typesystem->flags |= FLAG_SYSPEER;
+ for (n = 0; n < NTP_HASH_SIZE; n++)
+ for (peer = peer_hash[n]; peer != NULL; peer =
+ peer->next)
+ peer->status = peer->new_status;
clock_update(typesystem);
}
*/
static DOUBLE ppm_per_adjust_unit = 0.0;
+/*
+ * wintickadj emulates the functionality provided by unix tickadj,
+ * providing a baseline clock correction if needed to get the
+ * clock within a few hundred PPM of correct frequency.
+ */
+static long wintickadj;
+
/*
* performance counter frequency observations
*/
/* only adjust the clock if adjustment changes */
+ TimeAdjustment += wintickadj;
if (last_Adj != TimeAdjustment) {
last_Adj = TimeAdjustment;
DPRINTF(1, ("SetSystemTimeAdjustment(%+ld)\n", TimeAdjustment));
LARGE_INTEGER Freq;
FT_ULL initial_hectonanosecs;
FT_ULL next_hectonanosecs;
+ double adjppm;
+ double rawadj;
+ char * pch;
if (winnt_time_initialized)
return;
(LONGLONG)os_clock_precision / 1e4,
ppm_per_adjust_unit);
+ pch = getenv("NTPD_TICKADJ_PPM");
+ if (pch != NULL && 1 == sscanf(pch, "%lf", &adjppm)) {
+ rawadj = adjppm / ppm_per_adjust_unit;
+ rawadj += (rawadj < 0)
+ ? -0.5
+ : 0.5;
+ wintickadj = (long)rawadj;
+ msyslog(LOG_INFO,
+ "Using NTPD_TICKADJ_PPM %+g ppm (%+ld)",
+ adjppm, wintickadj);
+ }
+
winnt_time_initialized = TRUE;
choose_interp_counter();