#define REQ_LOCAL2 56
#define N_REQUEST_TYPES 57
-/* Structure used to exchange timevals independent on size of time_t */
+/* Structure used to exchange timespecs independent of time_t size */
typedef struct {
uint32_t tv_sec_high;
uint32_t tv_sec_low;
uint32_t tv_nsec;
-} Timeval;
+} Timespec;
/* This is used in tv_sec_high for 32-bit timestamps */
#define TV_NOHIGHSEC 0x7fffffff
} REQ_Modify_Makestep;
typedef struct {
- Timeval ts;
+ Timespec ts;
int32_t EOR;
} REQ_Logon;
typedef struct {
- Timeval ts;
+ Timespec ts;
int32_t EOR;
} REQ_Settime;
IPAddr ip_addr;
uint16_t stratum;
uint16_t leap_status;
- Timeval ref_time;
+ Timespec ref_time;
Float current_correction;
Float last_offset;
Float rms_offset;
} RPY_Sourcestats;
typedef struct {
- Timeval ref_time;
+ Timespec ref_time;
uint16_t n_samples;
uint16_t n_runs;
uint32_t span_seconds;
#define MAX_MANUAL_LIST_SAMPLES 16
typedef struct {
- Timeval when;
+ Timespec when;
Float slewed_offset;
Float orig_offset;
Float residual;
unsigned long long_uinteger;
unsigned int uinteger;
int integer;
- struct timeval *tv;
+ struct timespec *ts;
struct tm *tm;
double dbl;
else
print_nanoseconds(dbl);
break;
- case 'T': /* timeval as date and time in UTC */
- tv = va_arg(ap, struct timeval *);
- tm = gmtime(&tv->tv_sec);
+ case 'T': /* timespec as date and time in UTC */
+ ts = va_arg(ap, struct timespec *);
+ tm = gmtime(&ts->tv_sec);
if (!tm)
break;
strftime(buf, sizeof (buf), "%a %b %d %T %Y", tm);
long_uinteger = va_arg(ap, unsigned long);
printf("%*lu", width, long_uinteger);
break;
- case 'V': /* timeval as seconds since epoch */
- tv = va_arg(ap, struct timeval *);
- printf("%s", UTI_TimevalToString(tv));
+ case 'V': /* timespec as seconds since epoch */
+ ts = va_arg(ap, struct timespec *);
+ printf("%s", UTI_TimespecToString(ts));
break;
/* Classic printf specifiers */
IPAddr ip_addr;
uint32_t ref_id;
char name[50];
- struct timeval ref_time;
+ struct timespec ref_time;
const char *leap_status;
request.command = htons(REQ_TRACKING);
break;
}
- UTI_TimevalNetworkToHost(&reply.data.tracking.ref_time, &ref_time);
+ UTI_TimespecNetworkToHost(&reply.data.tracking.ref_time, &ref_time);
print_report("Reference ID : %R (%s)\n"
"Stratum : %u\n"
{
CMD_Request request;
CMD_Reply reply;
- struct timeval ref_time;
+ struct timespec ref_time;
request.command = htons(REQ_RTCREPORT);
if (!request_reply(&request, &reply, RPY_RTC, 0))
return 0;
- UTI_TimevalNetworkToHost(&reply.data.rtc.ref_time, &ref_time);
+ UTI_TimespecNetworkToHost(&reply.data.rtc.ref_time, &ref_time);
print_report("RTC ref time (UTC) : %T\n"
"Number of samples : %u\n"
CMD_Reply reply;
uint32_t i, n_samples;
RPY_ManualListSample *sample;
- struct timeval when;
+ struct timespec when;
request.command = htons(REQ_MANUAL_LIST);
if (!request_reply(&request, &reply, RPY_MANUAL_LIST, 0))
for (i = 0; i < n_samples; i++) {
sample = &reply.data.manual_list.samples[i];
- UTI_TimevalNetworkToHost(&sample->when, &when);
+ UTI_TimespecNetworkToHost(&sample->when, &when);
print_report("%2d %s %10.2f %10.2f %10.2f\n",
i, UTI_TimeToLogForm(when.tv_sec),
static int
process_cmd_settime(char *line)
{
- struct timeval ts;
+ struct timespec ts;
time_t now, new_time;
CMD_Request request;
CMD_Reply reply;
printf("510 - Could not parse date string\n");
} else {
ts.tv_sec = new_time;
- ts.tv_usec = 0;
- UTI_TimevalHostToNetwork(&ts, &request.data.settime.ts);
+ ts.tv_nsec = 0;
+ UTI_TimespecHostToNetwork(&ts, &request.data.settime.ts);
request.command = htons(REQ_SETTIME);
if (request_reply(&request, &reply, RPY_MANUAL_TIMESTAMP, 1)) {
offset_cs = ntohl(reply.data.manual_timestamp.centiseconds);
/* ================================================== */
static uint32_t
-get_ts_from_timeval(struct timeval *tv)
+get_ts_from_timespec(struct timespec *ts)
{
- uint32_t sec = tv->tv_sec, usec = tv->tv_usec;
+ uint32_t sec = ts->tv_sec, nsec = ts->tv_nsec;
- return sec << TS_FRAC | (4295U * usec - (usec >> 5)) >> (32 - TS_FRAC);
+ /* This is fast and accurate enough */
+ return sec << TS_FRAC | (140740U * (nsec >> 15)) >> (32 - TS_FRAC);
}
/* ================================================== */
static void
-update_record(struct timeval *now, uint32_t *last_hit, uint32_t *hits,
+update_record(struct timespec *now, uint32_t *last_hit, uint32_t *hits,
uint16_t *tokens, uint32_t max_tokens, int token_shift, int8_t *rate)
{
uint32_t interval, now_ts, prev_hit, new_tokens;
int interval2;
- now_ts = get_ts_from_timeval(now);
+ now_ts = get_ts_from_timespec(now);
prev_hit = *last_hit;
*last_hit = now_ts;
/* ================================================== */
int
-CLG_LogNTPAccess(IPAddr *client, struct timeval *now)
+CLG_LogNTPAccess(IPAddr *client, struct timespec *now)
{
Record *record;
/* ================================================== */
int
-CLG_LogCommandAccess(IPAddr *client, struct timeval *now)
+CLG_LogCommandAccess(IPAddr *client, struct timespec *now)
{
Record *record;
/* ================================================== */
int
-CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report, struct timeval *now)
+CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report, struct timespec *now)
{
Record *record;
uint32_t now_ts;
if (record->ip_addr.family == IPADDR_UNSPEC)
return 0;
- now_ts = get_ts_from_timeval(now);
+ now_ts = get_ts_from_timespec(now);
report->ip_addr = record->ip_addr;
report->ntp_hits = record->ntp_hits;
extern void CLG_Initialise(void);
extern void CLG_Finalise(void);
-extern int CLG_LogNTPAccess(IPAddr *client, struct timeval *now);
-extern int CLG_LogCommandAccess(IPAddr *client, struct timeval *now);
+extern int CLG_LogNTPAccess(IPAddr *client, struct timespec *now);
+extern int CLG_LogCommandAccess(IPAddr *client, struct timespec *now);
extern int CLG_LimitNTPResponseRate(int index);
extern int CLG_LimitCommandResponseRate(int index);
/* And some reporting functions, for use by chronyc. */
extern int CLG_GetNumberOfIndices(void);
-extern int CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report, struct timeval *now);
+extern int CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report, struct timespec *now);
extern void CLG_GetServerStatsReport(RPT_ServerStatsReport *report);
#endif /* GOT_CLIENTLOG_H */
static void
handle_settime(CMD_Request *rx_message, CMD_Reply *tx_message)
{
- struct timeval ts;
+ struct timespec ts;
long offset_cs;
double dfreq_ppm, new_afreq_ppm;
- UTI_TimevalNetworkToHost(&rx_message->data.settime.ts, &ts);
+ UTI_TimespecNetworkToHost(&rx_message->data.settime.ts, &ts);
if (!MNL_IsEnabled()) {
tx_message->status = htons(STT_NOTENABLED);
} else if (MNL_AcceptTimestamp(&ts, &offset_cs, &dfreq_ppm, &new_afreq_ppm)) {
handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
{
RPT_SourceReport report;
- struct timeval now_corr;
+ struct timespec now_corr;
/* Get data */
SCH_GetLastEventTime(&now_corr, NULL, NULL);
UTI_IPHostToNetwork(&rpt.ip_addr, &tx_message->data.tracking.ip_addr);
tx_message->data.tracking.stratum = htons(rpt.stratum);
tx_message->data.tracking.leap_status = htons(rpt.leap_status);
- UTI_TimevalHostToNetwork(&rpt.ref_time, &tx_message->data.tracking.ref_time);
+ UTI_TimespecHostToNetwork(&rpt.ref_time, &tx_message->data.tracking.ref_time);
tx_message->data.tracking.current_correction = UTI_FloatHostToNetwork(rpt.current_correction);
tx_message->data.tracking.last_offset = UTI_FloatHostToNetwork(rpt.last_offset);
tx_message->data.tracking.rms_offset = UTI_FloatHostToNetwork(rpt.rms_offset);
handle_smoothing(CMD_Request *rx_message, CMD_Reply *tx_message)
{
RPT_SmoothingReport report;
- struct timeval now;
+ struct timespec now;
SCH_GetLastEventTime(&now, NULL, NULL);
static void
handle_smoothtime(CMD_Request *rx_message, CMD_Reply *tx_message)
{
- struct timeval now;
+ struct timespec now;
int option;
if (!SMT_IsEnabled()) {
{
int status;
RPT_SourcestatsReport report;
- struct timeval now_corr;
+ struct timespec now_corr;
SCH_GetLastEventTime(&now_corr, NULL, NULL);
status = SRC_ReportSourcestats(ntohl(rx_message->data.sourcestats.index),
status = RTC_GetReport(&report);
if (status) {
tx_message->reply = htons(RPY_RTC);
- UTI_TimevalHostToNetwork(&report.ref_time, &tx_message->data.rtc.ref_time);
+ UTI_TimespecHostToNetwork(&report.ref_time, &tx_message->data.rtc.ref_time);
tx_message->data.rtc.n_samples = htons(report.n_samples);
tx_message->data.rtc.n_runs = htons(report.n_runs);
tx_message->data.rtc.span_seconds = htonl(report.span_seconds);
RPY_ClientAccesses_Client *client;
int n_indices;
uint32_t i, j, req_first_index, req_n_clients;
- struct timeval now;
+ struct timespec now;
SCH_GetLastEventTime(&now, NULL, NULL);
tx_message->data.manual_list.n_samples = htonl(n_samples);
for (i=0; i<n_samples; i++) {
sample = &tx_message->data.manual_list.samples[i];
- UTI_TimevalHostToNetwork(&report[i].when, &sample->when);
+ UTI_TimespecHostToNetwork(&report[i].when, &sample->when);
sample->slewed_offset = UTI_FloatHostToNetwork(report[i].slewed_offset);
sample->orig_offset = UTI_FloatHostToNetwork(report[i].orig_offset);
sample->residual = UTI_FloatHostToNetwork(report[i].residual);
socklen_t from_length;
IPAddr remote_ip;
unsigned short remote_port, rx_command;
- struct timeval now, cooked_now;
+ struct timespec now, cooked_now;
rx_message_length = sizeof(rx_message);
from_length = sizeof(where_from);
determine_hash_delay(uint32_t key_id)
{
NTP_Packet pkt;
- struct timeval before, after;
- unsigned long usecs, min_usecs=0;
- int i;
+ struct timespec before, after;
+ double diff, min_diff;
+ int i, nsecs;
for (i = 0; i < 10; i++) {
LCL_ReadRawTime(&before);
(unsigned char *)&pkt.auth_data, sizeof (pkt.auth_data));
LCL_ReadRawTime(&after);
- usecs = (after.tv_sec - before.tv_sec) * 1000000 + (after.tv_usec - before.tv_usec);
+ UTI_DiffTimespecsToDouble(&diff, &after, &before);
- if (i == 0 || usecs < min_usecs) {
- min_usecs = usecs;
- }
+ if (i == 0 || min_diff > diff)
+ min_diff = diff;
}
/* Add on a bit extra to allow for copying, conversions etc */
- min_usecs += min_usecs >> 4;
+ nsecs = 1.0625e9 * min_diff;
- DEBUG_LOG(LOGF_Keys, "authentication delay for key %"PRIu32": %ld useconds", key_id, min_usecs);
+ DEBUG_LOG(LOGF_Keys, "authentication delay for key %"PRIu32": %d nsecs", key_id, nsecs);
- return min_usecs;
+ return nsecs;
}
/* ================================================== */
under 1s of busy waiting. */
#define NITERS 100
+#define NSEC_PER_SEC 1000000000
+
static void
calculate_sys_precision(void)
{
- struct timeval tv, old_tv;
- int dusec, best_dusec;
- int iters;
+ struct timespec ts, old_ts;
+ int iters, diff, best;
+
+ LCL_ReadRawTime(&old_ts);
- gettimeofday(&old_tv, NULL);
- best_dusec = 1000000; /* Assume we must be better than a second */
+ /* Assume we must be better than a second */
+ best = NSEC_PER_SEC;
iters = 0;
+
do {
- gettimeofday(&tv, NULL);
- dusec = 1000000*(tv.tv_sec - old_tv.tv_sec) + (tv.tv_usec - old_tv.tv_usec);
- old_tv = tv;
- if (dusec > 0) {
- if (dusec < best_dusec) {
- best_dusec = dusec;
- }
+ LCL_ReadRawTime(&ts);
+
+ diff = NSEC_PER_SEC * (ts.tv_sec - old_ts.tv_sec) + (ts.tv_nsec - old_ts.tv_nsec);
+
+ old_ts = ts;
+ if (diff > 0) {
+ if (diff < best)
+ best = diff;
iters++;
}
} while (iters < NITERS);
- assert(best_dusec > 0);
+ assert(best > 0);
- precision_quantum = best_dusec * 1.0e-6;
+ precision_quantum = 1.0e-9 * best;
/* Get rounded log2 value of the measured precision */
precision_log = 0;
- while (best_dusec < 707107) {
+ while (best < 707106781) {
precision_log--;
- best_dusec *= 2;
+ best *= 2;
}
DEBUG_LOG(LOGF_Local, "Clock precision %.9f (%d)", precision_quantum, precision_log);
/* ================================================== */
static void
-invoke_parameter_change_handlers(struct timeval *raw, struct timeval *cooked,
+invoke_parameter_change_handlers(struct timespec *raw, struct timespec *cooked,
double dfreq, double doffset,
LCL_ChangeType change_type)
{
I can't think of a Unix system where it would not be */
void
-LCL_ReadRawTime(struct timeval *result)
+LCL_ReadRawTime(struct timespec *ts)
{
- if (gettimeofday(result, NULL) < 0) {
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL) < 0) {
LOG_FATAL(LOGF_Local, "gettimeofday() failed");
}
+
+ UTI_TimevalToTimespec(&tv, ts);
}
/* ================================================== */
void
-LCL_ReadCookedTime(struct timeval *result, double *err)
+LCL_ReadCookedTime(struct timespec *result, double *err)
{
- struct timeval raw;
+ struct timespec raw;
LCL_ReadRawTime(&raw);
LCL_CookTime(&raw, result, err);
/* ================================================== */
void
-LCL_CookTime(struct timeval *raw, struct timeval *cooked, double *err)
+LCL_CookTime(struct timespec *raw, struct timespec *cooked, double *err)
{
double correction;
LCL_GetOffsetCorrection(raw, &correction, err);
- UTI_AddDoubleToTimeval(raw, correction, cooked);
+ UTI_AddDoubleToTimespec(raw, correction, cooked);
}
/* ================================================== */
void
-LCL_GetOffsetCorrection(struct timeval *raw, double *correction, double *err)
+LCL_GetOffsetCorrection(struct timespec *raw, double *correction, double *err)
{
/* Call system specific driver to get correction */
(*drv_offset_convert)(raw, correction, err);
/* ================================================== */
static int
-check_offset(struct timeval *now, double offset)
+check_offset(struct timespec *now, double offset)
{
/* Check if the time will be still sane with accumulated offset */
if (UTI_IsTimeOffsetSane(now, -offset))
void
LCL_SetAbsoluteFrequency(double afreq_ppm)
{
- struct timeval raw, cooked;
+ struct timespec raw, cooked;
double dfreq;
afreq_ppm = clamp_freq(afreq_ppm);
void
LCL_AccumulateDeltaFrequency(double dfreq)
{
- struct timeval raw, cooked;
+ struct timespec raw, cooked;
double old_freq_ppm;
old_freq_ppm = current_freq_ppm;
void
LCL_AccumulateOffset(double offset, double corr_rate)
{
- struct timeval raw, cooked;
+ struct timespec raw, cooked;
/* In this case, the cooked time to be passed to the notify clients
has to be the cooked time BEFORE the change was made */
int
LCL_ApplyStepOffset(double offset)
{
- struct timeval raw, cooked;
+ struct timespec raw, cooked;
/* In this case, the cooked time to be passed to the notify clients
has to be the cooked time BEFORE the change was made */
/* ================================================== */
void
-LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
+LCL_NotifyExternalTimeStep(struct timespec *raw, struct timespec *cooked,
double offset, double dispersion)
{
/* Dispatch to all handlers */
void
LCL_NotifyLeap(int leap)
{
- struct timeval raw, cooked;
+ struct timespec raw, cooked;
LCL_ReadRawTime(&raw);
LCL_CookTime(&raw, &cooked, NULL);
void
LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate)
{
- struct timeval raw, cooked;
+ struct timespec raw, cooked;
double old_freq_ppm;
LCL_ReadRawTime(&raw);
int
LCL_MakeStep(void)
{
- struct timeval raw;
+ struct timespec raw;
double correction;
LCL_ReadRawTime(&raw);
/* Read the system clock. This is analogous to gettimeofday(),
but with the timezone information ignored */
-extern void LCL_ReadRawTime(struct timeval *);
+extern void LCL_ReadRawTime(struct timespec *ts);
/* Read the system clock, corrected according to all accumulated
drifts and uncompensated offsets.
adjtime()-like interface to correct offsets, and to adjust the
frequency), we must correct the raw time to get this value */
-extern void LCL_ReadCookedTime(struct timeval *t, double *err);
+extern void LCL_ReadCookedTime(struct timespec *ts, double *err);
/* Convert raw time to cooked. */
-extern void LCL_CookTime(struct timeval *raw, struct timeval *cooked, double *err);
+extern void LCL_CookTime(struct timespec *raw, struct timespec *cooked, double *err);
/* Read the current offset between the system clock and true time
(i.e. 'cooked' - 'raw') (in seconds). */
-extern void LCL_GetOffsetCorrection(struct timeval *raw, double *correction, double *err);
+extern void LCL_GetOffsetCorrection(struct timespec *raw, double *correction, double *err);
/* Type of routines that may be invoked as callbacks when there is a
change to the frequency or offset.
} LCL_ChangeType;
typedef void (*LCL_ParameterChangeHandler)
- (struct timeval *raw, struct timeval *cooked,
+ (struct timespec *raw, struct timespec *cooked,
double dfreq,
double doffset,
LCL_ChangeType change_type,
/* Routine to invoke notify handlers on an unexpected time jump
in system clock */
-extern void LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
+extern void LCL_NotifyExternalTimeStep(struct timespec *raw, struct timespec *cooked,
double offset, double dispersion);
/* Routine to invoke notify handlers on leap second when the system clock
/* System driver to convert a raw time to an adjusted (cooked) time.
The number of seconds returned in 'corr' have to be added to the
raw time to get the corrected time */
-typedef void (*lcl_OffsetCorrectionDriver)(struct timeval *raw, double *corr, double *err);
+typedef void (*lcl_OffsetCorrectionDriver)(struct timespec *raw, double *corr, double *err);
/* System driver to schedule leap second */
typedef void (*lcl_SetLeapDriver)(int leap);
/* More recent samples at highest indices */
typedef struct {
- struct timeval when; /* This is our 'cooked' time */
+ struct timespec when; /* This is our 'cooked' time */
double orig_offset; /*+ Not modified by slew samples */
double offset; /*+ if we are fast of the supplied reference */
double residual; /*+ regression residual (sign convention given by
/* ================================================== */
static void
-slew_samples(struct timeval *raw,
- struct timeval *cooked,
+slew_samples(struct timespec *raw,
+ struct timespec *cooked,
double dfreq,
double doffset,
LCL_ChangeType change_type,
/* ================================================== */
static void
-estimate_and_set_system(struct timeval *now, int offset_provided, double offset, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm)
+estimate_and_set_system(struct timespec *now, int offset_provided, double offset, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm)
{
double agos[MAX_SAMPLES], offsets[MAX_SAMPLES];
double b0, b1;
if (n_samples > 1) {
for (i=0; i<n_samples; i++) {
- UTI_DiffTimevalsToDouble(&agos[i], &samples[n_samples-1].when, &samples[i].when);
+ UTI_DiffTimespecsToDouble(&agos[i], &samples[n_samples - 1].when, &samples[i].when);
offsets[i] = samples[i].offset;
}
/* ================================================== */
int
-MNL_AcceptTimestamp(struct timeval *ts, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm)
+MNL_AcceptTimestamp(struct timespec *ts, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm)
{
- struct timeval now;
+ struct timespec now;
double offset, diff;
int i;
return 0;
if (n_samples) {
- UTI_DiffTimevalsToDouble(&diff, &now, &samples[n_samples - 1].when);
+ UTI_DiffTimespecsToDouble(&diff, &now, &samples[n_samples - 1].when);
if (diff < MIN_SAMPLE_SEPARATION)
return 0;
}
- UTI_DiffTimevalsToDouble(&offset, &now, ts);
+ UTI_DiffTimespecsToDouble(&offset, &now, ts);
/* Check if buffer full up */
if (n_samples == MAX_SAMPLES) {
/* ================================================== */
static void
-slew_samples(struct timeval *raw,
- struct timeval *cooked,
+slew_samples(struct timespec *raw,
+ struct timespec *cooked,
double dfreq,
double doffset,
LCL_ChangeType change_type,
}
for (i=0; i<n_samples; i++) {
- UTI_AdjustTimeval(&samples[i].when, cooked, &samples[i].when, &delta_time,
+ UTI_AdjustTimespec(&samples[i].when, cooked, &samples[i].when, &delta_time,
dfreq, doffset);
samples[i].offset += delta_time;
}
MNL_DeleteSample(int index)
{
int i;
- struct timeval now;
+ struct timespec now;
if ((index < 0) || (index >= n_samples)) {
return 0;
extern void MNL_Initialise(void);
extern void MNL_Finalise(void);
-extern int MNL_AcceptTimestamp(struct timeval *ts, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm);
+extern int MNL_AcceptTimestamp(struct timespec *ts, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm);
extern void MNL_Enable(void);
extern void MNL_Disable(void);
parameters for the current reference. (It must be stored
relative to local time to permit frequency and offset adjustments
to be made when we trim the local clock). */
- struct timeval local_rx;
+ struct timespec local_rx;
/* Local timestamp when we last transmitted a packet to the source.
We store two versions. The first is in NTP format, and is used
to validate the next received packet from the source.
Additionally, this is corrected to bring it into line with the
- current reference. The second is in timeval format, and is kept
+ current reference. The second is in timespec format, and is kept
relative to the local clock. We modify this in accordance with
local clock frequency/offset changes, and use this for computing
statistics about the source when a return packet arrives. */
NTP_int64 local_ntp_tx;
- struct timeval local_tx;
+ struct timespec local_tx;
/* The instance record in the main source management module. This
performs the statistical analysis on the samples we generate */
static void
do_time_checks(void)
{
- struct timeval now;
+ struct timespec now;
time_t warning_advance = 3600 * 24 * 365 * 10; /* 10 years */
#ifdef HAVE_LONG_TIME_T
/* Check that time before NTP_ERA_SPLIT underflows correctly */
- struct timeval tv1 = {NTP_ERA_SPLIT, 1}, tv2 = {NTP_ERA_SPLIT - 1, 1};
- NTP_int64 ntv1, ntv2;
+ struct timespec ts1 = {NTP_ERA_SPLIT, 1}, ts2 = {NTP_ERA_SPLIT - 1, 1};
+ NTP_int64 nts1, nts2;
int r;
- UTI_TimevalToInt64(&tv1, &ntv1, NULL);
- UTI_TimevalToInt64(&tv2, &ntv2, NULL);
- UTI_Int64ToTimeval(&ntv1, &tv1);
- UTI_Int64ToTimeval(&ntv2, &tv2);
+ UTI_TimespecToInt64(&ts1, &nts1, NULL);
+ UTI_TimespecToInt64(&ts2, &nts2, NULL);
+ UTI_Int64ToTimespec(&nts1, &ts1);
+ UTI_Int64ToTimespec(&nts2, &ts2);
- r = tv1.tv_sec == NTP_ERA_SPLIT &&
- tv1.tv_sec + (1ULL << 32) - 1 == tv2.tv_sec;
+ r = ts1.tv_sec == NTP_ERA_SPLIT &&
+ ts1.tv_sec + (1ULL << 32) - 1 == ts2.tv_sec;
assert(r);
LCL_ReadRawTime(&now);
- if (tv2.tv_sec - now.tv_sec < warning_advance)
+ if (ts2.tv_sec - now.tv_sec < warning_advance)
LOG(LOGS_WARN, LOGF_NtpCore, "Assumed NTP time ends at %s!",
- UTI_TimeToLogForm(tv2.tv_sec));
+ UTI_TimeToLogForm(ts2.tv_sec));
#else
LCL_ReadRawTime(&now);
if (now.tv_sec > 0x7fffffff - warning_advance)
start_initial_timeout(NCR_Instance inst)
{
double delay, last_tx;
- struct timeval now;
+ struct timespec now;
if (!inst->tx_timeout_id) {
/* This will be the first transmission after mode change */
the interval between packets at least as long as the current polling
interval */
SCH_GetLastEventTime(&now, NULL, NULL);
- UTI_DiffTimevalsToDouble(&last_tx, &now, &inst->local_tx);
+ UTI_DiffTimespecsToDouble(&last_tx, &now, &inst->local_tx);
if (last_tx < 0.0)
last_tx = 0.0;
delay = get_transmit_delay(inst, 0, 0.0) - last_tx;
result->tx_suspended = 1;
result->opmode = params->online ? MD_ONLINE : MD_OFFLINE;
result->local_poll = result->minpoll;
- result->local_tx.tv_sec = 0;
- result->local_tx.tv_usec = 0;
+ UTI_ZeroTimespec(&result->local_tx);
NCR_ResetInstance(result);
instance->remote_orig.hi = 0;
instance->remote_orig.lo = 0;
- instance->local_rx.tv_sec = 0;
- instance->local_rx.tv_usec = 0;
instance->local_ntp_tx.hi = 0;
instance->local_ntp_tx.lo = 0;
+ UTI_ZeroTimespec(&instance->local_rx);
if (instance->local_poll != instance->minpoll) {
instance->local_poll = instance->minpoll;
int auth_mode, /* The authentication mode */
uint32_t key_id, /* The authentication key ID */
NTP_int64 *orig_ts, /* Originate timestamp (from received packet) */
- struct timeval *local_rx, /* Local time request packet was received */
- struct timeval *local_tx, /* RESULT : Time this reply
+ struct timespec *local_rx, /* Local time request packet was received */
+ struct timespec *local_tx, /* RESULT : Time this reply
is sent as local time, or
NULL if don't want to
know */
{
NTP_Packet message;
int auth_len, length, ret, precision;
- struct timeval local_receive, local_transmit;
+ struct timespec local_receive, local_transmit;
NTP_int64 ts_fuzz;
/* Parameters read from reference module */
int are_we_synchronised, our_stratum, smooth_time;
NTP_Leap leap_status;
uint32_t our_ref_id;
- struct timeval our_ref_time;
+ struct timespec our_ref_time;
double our_root_delay, our_root_dispersion, smooth_offset;
/* Don't reply with version higher than ours */
/* Don't reveal local time or state of the clock in client packets */
precision = 32;
leap_status = our_stratum = our_ref_id = 0;
- our_ref_time.tv_sec = our_ref_time.tv_usec = 0;
our_root_delay = our_root_dispersion = 0.0;
+ UTI_ZeroTimespec(&our_ref_time);
} else {
/* This is accurate enough and cheaper than calling LCL_ReadCookedTime.
A more accurate timestamp will be taken later in this function. */
if (smooth_time) {
our_ref_id = NTP_REFID_SMOOTH;
- UTI_AddDoubleToTimeval(&our_ref_time, smooth_offset, &our_ref_time);
- UTI_AddDoubleToTimeval(local_rx, smooth_offset, &local_receive);
+ UTI_AddDoubleToTimespec(&our_ref_time, smooth_offset, &our_ref_time);
+ UTI_AddDoubleToTimespec(local_rx, smooth_offset, &local_receive);
} else {
local_receive = *local_rx;
}
/* Now fill in timestamps */
- UTI_TimevalToInt64(&our_ref_time, &message.reference_ts, NULL);
+ UTI_TimespecToInt64(&our_ref_time, &message.reference_ts, NULL);
/* Originate - this comes from the last packet the source sent us */
message.originate_ts = *orig_ts;
This timestamp will have been adjusted so that it will now look to
the source like we have been running on our latest estimate of
frequency all along */
- UTI_TimevalToInt64(&local_receive, &message.receive_ts, &ts_fuzz);
+ UTI_TimespecToInt64(&local_receive, &message.receive_ts, &ts_fuzz);
/* Prepare random bits which will be added to the transmit timestamp. */
UTI_GetInt64Fuzz(&ts_fuzz, precision);
LCL_ReadCookedTime(&local_transmit, NULL);
if (smooth_time)
- UTI_AddDoubleToTimeval(&local_transmit, smooth_offset, &local_transmit);
+ UTI_AddDoubleToTimespec(&local_transmit, smooth_offset, &local_transmit);
length = NTP_NORMAL_PACKET_LENGTH;
if (auth_mode == AUTH_SYMMETRIC || auth_mode == AUTH_MSSNTP) {
/* Pre-compensate the transmit time by approx. how long it will
take to generate the authentication data. */
- local_transmit.tv_usec += auth_mode == AUTH_SYMMETRIC ?
+ local_transmit.tv_nsec += auth_mode == AUTH_SYMMETRIC ?
KEY_GetAuthDelay(key_id) : NSD_GetAuthDelay(key_id);
- UTI_NormaliseTimeval(&local_transmit);
- UTI_TimevalToInt64(&local_transmit, &message.transmit_ts, &ts_fuzz);
+ UTI_NormaliseTimespec(&local_transmit);
+ UTI_TimespecToInt64(&local_transmit, &message.transmit_ts, &ts_fuzz);
if (auth_mode == AUTH_SYMMETRIC) {
auth_len = KEY_GenerateAuth(key_id, (unsigned char *) &message,
return NSD_SignAndSendPacket(key_id, &message, where_to, from, length);
}
} else {
- UTI_TimevalToInt64(&local_transmit, &message.transmit_ts, &ts_fuzz);
+ UTI_TimespecToInt64(&local_transmit, &message.transmit_ts, &ts_fuzz);
}
ret = NIO_SendPacket(&message, where_to, from, length);
/* ================================================== */
static int
-receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Instance inst, NTP_Local_Address *local_addr, int length)
+receive_packet(NTP_Packet *message, struct timespec *now, double now_err, NCR_Instance inst, NTP_Local_Address *local_addr, int length)
{
int pkt_leap;
uint32_t pkt_refid, pkt_key_id;
the same as either the transmit or receive time. The difference comes
in symmetric active mode, when the receive may come minutes after the
transmit, and this time will be midway between the two */
- struct timeval sample_time;
+ struct timespec sample_time;
/* The estimated offset in seconds, a positive value indicates that the local
clock is SLOW of the remote source and a negative value indicates that the
/* The skew and estimated frequency offset relative to the remote source */
double skew, source_freq_lo, source_freq_hi;
- /* These are the timeval equivalents of the remote epochs */
- struct timeval remote_receive_tv, remote_transmit_tv;
- struct timeval local_average, remote_average;
+ /* These are the timespec equivalents of the remote epochs */
+ struct timespec remote_receive, remote_transmit;
+ struct timespec local_average, remote_average;
double local_interval, remote_interval;
/* RFC 5905 packet tests */
pkt_root_delay = UTI_Int32ToDouble(message->root_delay);
pkt_root_dispersion = UTI_Int32ToDouble(message->root_dispersion);
- UTI_Int64ToTimeval(&message->receive_ts, &remote_receive_tv);
- UTI_Int64ToTimeval(&message->transmit_ts, &remote_transmit_tv);
+ UTI_Int64ToTimespec(&message->receive_ts, &remote_receive);
+ UTI_Int64ToTimespec(&message->transmit_ts, &remote_transmit);
/* Check if the packet is valid per RFC 5905, section 8.
The test values are 1 when passed and 0 when failed. */
SRC_GetFrequencyRange(inst->source, &source_freq_lo, &source_freq_hi);
- UTI_AverageDiffTimevals(&remote_receive_tv, &remote_transmit_tv,
- &remote_average, &remote_interval);
+ UTI_AverageDiffTimespecs(&remote_receive, &remote_transmit,
+ &remote_average, &remote_interval);
- UTI_AverageDiffTimevals(&inst->local_tx, now,
- &local_average, &local_interval);
+ UTI_AverageDiffTimespecs(&inst->local_tx, now,
+ &local_average, &local_interval);
/* In our case, we work out 'delay' as the worst case delay,
assuming worst case frequency error between us and the other
/* Calculate offset. Following the NTP definition, this is negative
if we are fast of the remote source. */
- UTI_DiffTimevalsToDouble(&offset, &remote_average, &local_average);
+ UTI_DiffTimespecsToDouble(&offset, &remote_average, &local_average);
/* Apply configured correction */
offset += inst->offset_correction;
int
NCR_ProcessKnown
(NTP_Packet *message, /* the received message */
- struct timeval *now, /* timestamp at time of receipt */
+ struct timespec *now, /* timestamp at time of receipt */
double now_err,
NCR_Instance inst, /* the instance record for this peer/server */
NTP_Local_Address *local_addr, /* the receiving address */
void
NCR_ProcessUnknown
(NTP_Packet *message, /* the received message */
- struct timeval *now, /* timestamp at time of receipt */
+ struct timespec *now, /* timestamp at time of receipt */
double now_err, /* assumed error in the timestamp */
NTP_Remote_Address *remote_addr,
NTP_Local_Address *local_addr,
/* ================================================== */
void
-NCR_SlewTimes(NCR_Instance inst, struct timeval *when, double dfreq, double doffset)
+NCR_SlewTimes(NCR_Instance inst, struct timespec *when, double dfreq, double doffset)
{
double delta;
- if (inst->local_rx.tv_sec || inst->local_rx.tv_usec)
- UTI_AdjustTimeval(&inst->local_rx, when, &inst->local_rx, &delta, dfreq, doffset);
- if (inst->local_tx.tv_sec || inst->local_tx.tv_usec)
- UTI_AdjustTimeval(&inst->local_tx, when, &inst->local_tx, &delta, dfreq, doffset);
+ if (inst->local_rx.tv_sec || inst->local_rx.tv_nsec)
+ UTI_AdjustTimespec(&inst->local_rx, when, &inst->local_rx, &delta, dfreq, doffset);
+ if (inst->local_tx.tv_sec || inst->local_tx.tv_nsec)
+ UTI_AdjustTimespec(&inst->local_tx, when, &inst->local_tx, &delta, dfreq, doffset);
}
/* ================================================== */
/* ================================================== */
void
-NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *now)
+NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timespec *now)
{
report->poll = inst->local_poll;
{
BroadcastDestination *destination;
NTP_int64 orig_ts;
- struct timeval recv_ts;
+ struct timespec recv_ts;
destination = ARR_GetElement(broadcasts, (long)arg);
orig_ts.hi = 0;
orig_ts.lo = 0;
- recv_ts.tv_sec = 0;
- recv_ts.tv_usec = 0;
+ UTI_ZeroTimespec(&recv_ts);
transmit_packet(MODE_BROADCAST, 6 /* FIXME: should this be log2(interval)? */,
NTP_VERSION, 0, 0, &orig_ts, &recv_ts, NULL, NULL,
/* This routine is called when a new packet arrives off the network,
and it relates to a source we have an ongoing protocol exchange with */
-extern int NCR_ProcessKnown(NTP_Packet *message, struct timeval *now, double now_err, NCR_Instance data, NTP_Local_Address *local_addr, int length);
+extern int NCR_ProcessKnown(NTP_Packet *message, struct timespec *now, double now_err, NCR_Instance data, NTP_Local_Address *local_addr, int length);
/* This routine is called when a new packet arrives off the network,
and we do not recognize its source */
-extern void NCR_ProcessUnknown(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length);
+extern void NCR_ProcessUnknown(NTP_Packet *message, struct timespec *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length);
/* Slew receive and transmit times in instance records */
-extern void NCR_SlewTimes(NCR_Instance inst, struct timeval *when, double dfreq, double doffset);
+extern void NCR_SlewTimes(NCR_Instance inst, struct timespec *when, double dfreq, double doffset);
/* Take a particular source online (i.e. start sampling it) */
extern void NCR_TakeSourceOnline(NCR_Instance inst);
extern void NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n_total_samples);
-extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *now);
+extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timespec *now);
extern int NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
extern int NCR_CheckAccessRestriction(IPAddr *ip_addr);
NTP_Remote_Address remote_addr;
NTP_Local_Address local_addr;
struct cmsghdr *cmsg;
- struct timeval now;
+ struct timespec now;
double now_err;
SCH_GetLastEventTime(&now, &now_err, NULL);
#ifdef SO_TIMESTAMP
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) {
struct timeval tv;
+ struct timespec ts;
memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
- LCL_CookTime(&tv, &now, &now_err);
+ UTI_TimevalToTimespec(&tv, &ts);
+ LCL_CookTime(&ts, &now, &now_err);
}
#endif
}
int sent;
int received;
int request_length;
- struct timeval request_tv;
+ struct timespec request_ts;
SigndRequest request;
SigndResponse response;
} SignInstance;
static void
process_response(SignInstance *inst)
{
- struct timeval tv;
+ struct timespec ts;
double delay;
if (ntohs(inst->request.packet_id) != ntohl(inst->response.packet_id)) {
return;
}
- SCH_GetLastEventTime(NULL, NULL, &tv);
- UTI_DiffTimevalsToDouble(&delay, &tv, &inst->request_tv);
+ SCH_GetLastEventTime(NULL, NULL, &ts);
+ UTI_DiffTimespecsToDouble(&delay, &ts, &inst->request_ts);
DEBUG_LOG(LOGF_NtpSignd, "Signing succeeded (delay %f)", delay);
assert(inst->sent < inst->request_length);
if (!inst->sent)
- SCH_GetLastEventTime(NULL, NULL, &inst->request_tv);
+ SCH_GetLastEventTime(NULL, NULL, &inst->request_ts);
s = send(sock_fd, (char *)&inst->request + inst->sent,
inst->request_length - inst->sent, 0);
extern int NSD_GetAuthDelay(uint32_t key_id)
{
- return auth_delay * 1.0e6;
+ return 1.0e9 * auth_delay;
}
/* ================================================== */
static void clean_source_record(SourceRecord *record);
static void
-slew_sources(struct timeval *raw,
- struct timeval *cooked,
+slew_sources(struct timespec *raw,
+ struct timespec *cooked,
double dfreq,
double doffset,
LCL_ChangeType change_type,
void
NSR_HandleBadSource(IPAddr *address)
{
- static struct timeval last_replacement;
- struct timeval now;
+ static struct timespec last_replacement;
+ struct timespec now;
NTP_Remote_Address remote_addr;
SourceRecord *record;
int slot, found;
/* Don't resolve names too frequently */
SCH_GetLastEventTime(NULL, NULL, &now);
- UTI_DiffTimevalsToDouble(&diff, &now, &last_replacement);
+ UTI_DiffTimespecsToDouble(&diff, &now, &last_replacement);
if (fabs(diff) < RESOLVE_INTERVAL_UNIT * (1 << MIN_REPLACEMENT_INTERVAL)) {
DEBUG_LOG(LOGF_NtpSources, "replacement postponed");
return;
/* This routine is called by ntp_io when a new packet arrives off the network,
possibly with an authentication tail */
void
-NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length)
+NSR_ProcessReceive(NTP_Packet *message, struct timespec *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length)
{
SourceRecord *record;
struct SourcePool *pool;
/* ================================================== */
static void
-slew_sources(struct timeval *raw,
- struct timeval *cooked,
+slew_sources(struct timespec *raw,
+ struct timespec *cooked,
double dfreq,
double doffset,
LCL_ChangeType change_type,
identify the source record. */
void
-NSR_ReportSource(RPT_SourceReport *report, struct timeval *now)
+NSR_ReportSource(RPT_SourceReport *report, struct timespec *now)
{
NTP_Remote_Address rem_addr;
int slot, found;
extern uint32_t NSR_GetLocalRefid(IPAddr *address);
/* This routine is called by ntp_io when a new packet arrives off the network */
-extern void NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length);
+extern void NSR_ProcessReceive(NTP_Packet *message, struct timespec *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length);
/* Initialisation function */
extern void NSR_Initialise(void);
extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, IPAddr *mask, IPAddr *address);
-extern void NSR_ReportSource(RPT_SourceReport *report, struct timeval *now);
+extern void NSR_ReportSource(RPT_SourceReport *report, struct timespec *now);
extern void NSR_GetActivityReport(RPT_ActivityReport *report);
struct FilterSample {
double offset;
double dispersion;
- struct timeval sample_time;
+ struct timespec sample_time;
};
struct MedianFilter {
static LOG_FileID logfileid;
-static int valid_sample_time(RCL_Instance instance, struct timeval *tv);
-static int pps_stratum(RCL_Instance instance, struct timeval *tv);
+static int valid_sample_time(RCL_Instance instance, struct timespec *ts);
+static int pps_stratum(RCL_Instance instance, struct timespec *ts);
static void poll_timeout(void *arg);
-static void slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq,
+static void slew_samples(struct timespec *raw, struct timespec *cooked, double dfreq,
double doffset, LCL_ChangeType change_type, void *anything);
static void add_dispersion(double dispersion, void *anything);
-static void log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion);
+static void log_sample(RCL_Instance instance, struct timespec *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion);
static void filter_init(struct MedianFilter *filter, int length, double max_dispersion);
static void filter_fini(struct MedianFilter *filter);
static void filter_reset(struct MedianFilter *filter);
static double filter_get_avg_sample_dispersion(struct MedianFilter *filter);
-static void filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset, double dispersion);
-static int filter_get_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion);
+static void filter_add_sample(struct MedianFilter *filter, struct timespec *sample_time, double offset, double dispersion);
+static int filter_get_last_sample(struct MedianFilter *filter, struct timespec *sample_time, double *offset, double *dispersion);
static int filter_select_samples(struct MedianFilter *filter);
-static int filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion);
-static void filter_slew_samples(struct MedianFilter *filter, struct timeval *when, double dfreq, double doffset);
+static int filter_get_sample(struct MedianFilter *filter, struct timespec *sample_time, double *offset, double *dispersion);
+static void filter_slew_samples(struct MedianFilter *filter, struct timespec *when, double dfreq, double doffset);
static void filter_add_dispersion(struct MedianFilter *filter, double dispersion);
static RCL_Instance
}
void
-RCL_ReportSource(RPT_SourceReport *report, struct timeval *now)
+RCL_ReportSource(RPT_SourceReport *report, struct timespec *now)
{
unsigned int i;
uint32_t ref_id;
}
int
-RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, int leap)
+RCL_AddSample(RCL_Instance instance, struct timespec *sample_time, double offset, int leap)
{
double correction, dispersion;
- struct timeval cooked_time;
+ struct timespec cooked_time;
LCL_GetOffsetCorrection(sample_time, &correction, &dispersion);
- UTI_AddDoubleToTimeval(sample_time, correction, &cooked_time);
+ UTI_AddDoubleToTimespec(sample_time, correction, &cooked_time);
dispersion += instance->precision;
/* Make sure the timestamp and offset provided by the driver are sane */
}
int
-RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
+RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second)
{
double correction, dispersion, offset;
- struct timeval cooked_time;
+ struct timespec cooked_time;
int rate;
NTP_Leap leap;
leap = LEAP_Normal;
LCL_GetOffsetCorrection(pulse_time, &correction, &dispersion);
- UTI_AddDoubleToTimeval(pulse_time, correction, &cooked_time);
+ UTI_AddDoubleToTimespec(pulse_time, correction, &cooked_time);
dispersion += instance->precision;
if (!UTI_IsTimeOffsetSane(pulse_time, 0.0) ||
if (instance->lock_ref != -1) {
RCL_Instance lock_refclock;
- struct timeval ref_sample_time;
+ struct timespec ref_sample_time;
double sample_diff, ref_offset, ref_dispersion, shift;
lock_refclock = get_refclock(instance->lock_ref);
ref_dispersion += filter_get_avg_sample_dispersion(&lock_refclock->filter);
- UTI_DiffTimevalsToDouble(&sample_diff, &cooked_time, &ref_sample_time);
+ UTI_DiffTimespecsToDouble(&sample_diff, &cooked_time, &ref_sample_time);
if (fabs(sample_diff) >= 2.0 / rate) {
DEBUG_LOG(LOGF_Refclock, "refclock pulse ignored samplediff=%.9f",
sample_diff);
DEBUG_LOG(LOGF_Refclock, "refclock pulse second=%.9f offset=%.9f offdiff=%.9f samplediff=%.9f",
second, offset, ref_offset - offset, sample_diff);
} else {
- struct timeval ref_time;
+ struct timespec ref_time;
int is_synchronised, stratum;
double root_delay, root_dispersion, distance;
uint32_t ref_id;
}
static int
-valid_sample_time(RCL_Instance instance, struct timeval *tv)
+valid_sample_time(RCL_Instance instance, struct timespec *ts)
{
- struct timeval raw_time;
+ struct timespec raw_time;
double diff;
LCL_ReadRawTime(&raw_time);
- UTI_DiffTimevalsToDouble(&diff, &raw_time, tv);
+ UTI_DiffTimespecsToDouble(&diff, &raw_time, ts);
if (diff < 0.0 || diff > UTI_Log2ToDouble(instance->poll + 1)) {
- DEBUG_LOG(LOGF_Refclock, "%s refclock sample not valid age=%.6f tv=%s",
- UTI_RefidToString(instance->ref_id), diff, UTI_TimevalToString(tv));
+ DEBUG_LOG(LOGF_Refclock, "%s refclock sample not valid age=%.6f ts=%s",
+ UTI_RefidToString(instance->ref_id), diff, UTI_TimespecToString(ts));
return 0;
}
return 1;
}
static int
-pps_stratum(RCL_Instance instance, struct timeval *tv)
+pps_stratum(RCL_Instance instance, struct timespec *ts)
{
- struct timeval ref_time;
+ struct timespec ref_time;
int is_synchronised, stratum;
unsigned int i;
double root_delay, root_dispersion;
uint32_t ref_id;
RCL_Instance refclock;
- REF_GetReferenceParams(tv, &is_synchronised, &leap, &stratum,
+ REF_GetReferenceParams(ts, &is_synchronised, &leap, &stratum,
&ref_id, &ref_time, &root_delay, &root_dispersion);
/* Don't change our stratum if the local reference is active
if (!(inst->driver->poll && inst->driver_polled < (1 << (inst->poll - inst->driver_poll)))) {
double offset, dispersion;
- struct timeval sample_time;
+ struct timespec sample_time;
int sample_ok, stratum;
sample_ok = filter_get_sample(&inst->filter, &sample_time, &offset, &dispersion);
}
static void
-slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq,
+slew_samples(struct timespec *raw, struct timespec *cooked, double dfreq,
double doffset, LCL_ChangeType change_type, void *anything)
{
unsigned int i;
}
static void
-log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion)
+log_sample(RCL_Instance instance, struct timespec *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion)
{
char sync_stats[4] = {'N', '+', '-', '?'};
if (!filtered) {
LOG_FileWrite(logfileid, "%s.%06d %-5s %3d %1c %1d %13.6e %13.6e %10.3e",
UTI_TimeToLogForm(sample_time->tv_sec),
- (int)sample_time->tv_usec,
+ (int)sample_time->tv_nsec / 1000,
UTI_RefidToString(instance->ref_id),
instance->driver_polled,
sync_stats[instance->leap_status],
} else {
LOG_FileWrite(logfileid, "%s.%06d %-5s - %1c - - %13.6e %10.3e",
UTI_TimeToLogForm(sample_time->tv_sec),
- (int)sample_time->tv_usec,
+ (int)sample_time->tv_nsec / 1000,
UTI_RefidToString(instance->ref_id),
sync_stats[instance->leap_status],
cooked_offset,
}
static void
-filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset, double dispersion)
+filter_add_sample(struct MedianFilter *filter, struct timespec *sample_time, double offset, double dispersion)
{
filter->index++;
filter->index %= filter->length;
filter->samples[filter->index].dispersion = dispersion;
DEBUG_LOG(LOGF_Refclock, "filter sample %d t=%s offset=%.9f dispersion=%.9f",
- filter->index, UTI_TimevalToString(sample_time), offset, dispersion);
+ filter->index, UTI_TimespecToString(sample_time), offset, dispersion);
}
static int
-filter_get_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion)
+filter_get_last_sample(struct MedianFilter *filter, struct timespec *sample_time, double *offset, double *dispersion)
{
if (filter->last < 0)
return 0;
}
static int
-filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion)
+filter_get_sample(struct MedianFilter *filter, struct timespec *sample_time, double *offset, double *dispersion)
{
struct FilterSample *s, *ls;
int i, n, dof;
for (i = 0; i < n; i++) {
s = &filter->samples[filter->selected[i]];
- UTI_DiffTimevalsToDouble(&filter->x_data[i], &s->sample_time, &ls->sample_time);
+ UTI_DiffTimespecsToDouble(&filter->x_data[i], &s->sample_time, &ls->sample_time);
filter->y_data[i] = s->offset;
filter->w_data[i] = s->dispersion;
}
if (d < e)
d = e;
- UTI_AddDoubleToTimeval(&ls->sample_time, x, sample_time);
+ UTI_AddDoubleToTimespec(&ls->sample_time, x, sample_time);
*offset = y;
*dispersion = d;
}
static void
-filter_slew_samples(struct MedianFilter *filter, struct timeval *when, double dfreq, double doffset)
+filter_slew_samples(struct MedianFilter *filter, struct timespec *when, double dfreq, double doffset)
{
int i;
double delta_time;
- struct timeval *sample;
+ struct timespec *sample;
for (i = 0; i < filter->used; i++) {
sample = &filter->samples[i].sample_time;
- UTI_AdjustTimeval(sample, when, sample, &delta_time, dfreq, doffset);
+ UTI_AdjustTimespec(sample, when, sample, &delta_time, dfreq, doffset);
filter->samples[i].offset -= delta_time;
}
}
extern void RCL_Finalise(void);
extern int RCL_AddRefclock(RefclockParameters *params);
extern void RCL_StartRefclocks(void);
-extern void RCL_ReportSource(RPT_SourceReport *report, struct timeval *now);
+extern void RCL_ReportSource(RPT_SourceReport *report, struct timespec *now);
/* functions used by drivers */
extern void RCL_SetDriverData(RCL_Instance instance, void *data);
extern void *RCL_GetDriverData(RCL_Instance instance);
extern char *RCL_GetDriverParameter(RCL_Instance instance);
extern char *RCL_GetDriverOption(RCL_Instance instance, char *name);
-extern int RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, int leap);
-extern int RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second);
+extern int RCL_AddSample(RCL_Instance instance, struct timespec *sample_time, double offset, int leap);
+extern int RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second);
#endif
struct timespec sys_ts2;
};
-static double diff_ts(struct timespec *ts1, struct timespec *ts2)
-{
- return (ts1->tv_sec - ts2->tv_sec) + (ts1->tv_nsec - ts2->tv_nsec) / 1e9;
-}
-
static int read_phc_ioctl(struct phc_reading *readings, int phc_fd, int n)
{
#if defined(PTP_SYS_OFFSET) && NUM_READINGS <= PTP_MAX_SAMPLES
static int phc_poll(RCL_Instance instance)
{
struct phc_reading readings[NUM_READINGS];
- struct timeval tv;
double offset = 0.0, delay, best_delay = 0.0;
int i, phc_fd, best;
/* Find the fastest reading */
for (i = 0; i < NUM_READINGS; i++) {
- delay = diff_ts(&readings[i].sys_ts2, &readings[i].sys_ts1);
+ UTI_DiffTimespecsToDouble(&delay, &readings[i].sys_ts2, &readings[i].sys_ts1);
if (!i || best_delay > delay) {
best = i;
}
}
- offset = diff_ts(&readings[best].phc_ts, &readings[best].sys_ts2) + best_delay / 2.0;
- tv.tv_sec = readings[best].sys_ts2.tv_sec;
- tv.tv_usec = readings[best].sys_ts2.tv_nsec / 1000;
+ UTI_DiffTimespecsToDouble(&offset, &readings[best].phc_ts, &readings[best].sys_ts2);
+ offset += best_delay / 2.0;
DEBUG_LOG(LOGF_Refclock, "PHC offset: %+.9f delay: %.9f", offset, best_delay);
- return RCL_AddSample(instance, &tv, offset, LEAP_Normal);
+ return RCL_AddSample(instance, &readings[best].sys_ts2, offset, LEAP_Normal);
}
RefclockDriver RCL_PHC_driver = {
{
struct pps_instance *pps;
struct timespec ts;
- struct timeval tv;
pps_info_t pps_info;
pps_seq_t seq;
}
pps->last_seq = seq;
- tv.tv_sec = ts.tv_sec;
- tv.tv_usec = ts.tv_nsec / 1000;
- return RCL_AddPulse(instance, &tv, ts.tv_nsec / 1e9);
+ return RCL_AddPulse(instance, &ts, 1.0e-9 * ts.tv_nsec);
}
RefclockDriver RCL_PPS_driver = {
static int shm_poll(RCL_Instance instance)
{
- struct timeval tv;
+ struct timespec receive_ts, clock_ts;
struct shmTime t, *shm;
double offset;
shm->valid = 0;
- tv.tv_sec = t.receiveTimeStampSec;
- tv.tv_usec = t.receiveTimeStampUSec;
+ receive_ts.tv_sec = t.receiveTimeStampSec;
+ clock_ts.tv_sec = t.clockTimeStampSec;
- offset = t.clockTimeStampSec - t.receiveTimeStampSec;
if (t.clockTimeStampNSec / 1000 == t.clockTimeStampUSec &&
- t.receiveTimeStampNSec / 1000 == t.receiveTimeStampUSec)
- offset += (t.clockTimeStampNSec - t.receiveTimeStampNSec) * 1e-9;
- else
- offset += (t.clockTimeStampUSec - t.receiveTimeStampUSec) * 1e-6;
+ t.receiveTimeStampNSec / 1000 == t.receiveTimeStampUSec) {
+ receive_ts.tv_nsec = t.receiveTimeStampNSec;
+ clock_ts.tv_nsec = t.clockTimeStampNSec;
+ } else {
+ receive_ts.tv_nsec = 1000 * t.receiveTimeStampUSec;
+ clock_ts.tv_nsec = 1000 * t.clockTimeStampUSec;
+ }
+
+ UTI_NormaliseTimespec(&clock_ts);
+ UTI_NormaliseTimespec(&receive_ts);
+ UTI_DiffTimespecsToDouble(&offset, &clock_ts, &receive_ts);
- return RCL_AddSample(instance, &tv, offset, t.leap);
+ return RCL_AddSample(instance, &receive_ts, offset, t.leap);
}
RefclockDriver RCL_SHM_driver = {
static void read_sample(int sockfd, int event, void *anything)
{
struct sock_sample sample;
+ struct timespec ts;
RCL_Instance instance;
int s;
return;
}
+ UTI_TimevalToTimespec(&sample.tv, &ts);
+ UTI_NormaliseTimespec(&ts);
+
if (sample.pulse) {
- RCL_AddPulse(instance, &sample.tv, sample.offset);
+ RCL_AddPulse(instance, &ts, sample.offset);
} else {
- RCL_AddSample(instance, &sample.tv, sample.offset, sample.leap);
+ RCL_AddSample(instance, &ts, sample.offset, sample.leap);
}
}
static int our_stratum;
static uint32_t our_ref_id;
static IPAddr our_ref_ip;
-struct timeval our_ref_time;
+struct timespec our_ref_time;
static double our_skew;
static double our_residual_freq;
static double our_root_delay;
static SCH_TimeoutID fb_drift_timeout_id;
/* Timestamp of last reference update */
-static struct timeval last_ref_update;
+static struct timespec last_ref_update;
static double last_ref_update_interval;
/* ================================================== */
/* ================================================== */
static void
-handle_slew(struct timeval *raw,
- struct timeval *cooked,
+handle_slew(struct timespec *raw,
+ struct timespec *cooked,
double dfreq,
double doffset,
LCL_ChangeType change_type,
void *anything)
{
double delta;
- struct timeval now;
+ struct timespec now;
- UTI_AdjustTimeval(&our_ref_time, cooked, &our_ref_time, &delta, dfreq, doffset);
+ UTI_AdjustTimespec(&our_ref_time, cooked, &our_ref_time, &delta, dfreq, doffset);
if (change_type == LCL_ChangeUnknownStep) {
- last_ref_update.tv_sec = 0;
- last_ref_update.tv_usec = 0;
+ UTI_ZeroTimespec(&last_ref_update);
} else if (last_ref_update.tv_sec) {
- UTI_AdjustTimeval(&last_ref_update, cooked, &last_ref_update, &delta, dfreq, doffset);
+ UTI_AdjustTimespec(&last_ref_update, cooked, &last_ref_update, &delta, dfreq, doffset);
}
/* When the clock was stepped, check if that doesn't change our leap status
fb_drift_timeout_id = 0;
}
- last_ref_update.tv_sec = 0;
- last_ref_update.tv_usec = 0;
+ UTI_ZeroTimespec(&last_ref_update);
last_ref_update_interval = 0.0;
LCL_AddParameterChangeHandler(handle_slew, NULL);
/* ================================================== */
static void
-schedule_fb_drift(struct timeval *now)
+schedule_fb_drift(struct timespec *now)
{
int i, c, secs;
double unsynchronised;
- struct timeval when;
+ struct timespec when;
if (fb_drift_timeout_id)
return; /* already scheduled */
- UTI_DiffTimevalsToDouble(&unsynchronised, now, &last_ref_update);
+ UTI_DiffTimespecsToDouble(&unsynchronised, now, &last_ref_update);
for (c = secs = 0, i = fb_drift_min; i <= fb_drift_max; i++) {
secs = 1 << i;
if (i <= fb_drift_max) {
next_fb_drift = i;
- UTI_AddDoubleToTimeval(now, secs - unsynchronised, &when);
+ UTI_AddDoubleToTimespec(now, secs - unsynchronised, &when);
fb_drift_timeout_id = SCH_AddTimeout(&when, fb_drift_timeout, NULL);
DEBUG_LOG(LOGF_Reference, "Fallback drift %d scheduled", i);
}
static void
set_leap_timeout(time_t now)
{
- struct timeval when;
+ struct timespec when;
/* Stop old timer if there is one */
SCH_RemoveTimeout(leap_timeout_id);
will be corrected by the system, timeout slightly sooner to be sure it
will happen before the system correction. */
when.tv_sec = (now / (24 * 3600) + 1) * (24 * 3600);
- when.tv_usec = 0;
+ when.tv_nsec = 0;
if (our_leap_sec < 0)
when.tv_sec--;
if (leap_mode == REF_LeapModeSystem) {
when.tv_sec--;
- when.tv_usec = 500000;
+ when.tv_nsec = 500000000;
}
leap_timeout_id = SCH_AddTimeout(&when, leap_start_timeout, NULL);
/* ================================================== */
static void
-write_log(struct timeval *ref_time, char *ref, int stratum, NTP_Leap leap,
+write_log(struct timespec *ref_time, char *ref, int stratum, NTP_Leap leap,
double freq, double skew, double offset, int combined_sources,
double offset_sd, double uncorrected_offset)
{
int combined_sources,
uint32_t ref_id,
IPAddr *ref_ip,
- struct timeval *ref_time,
+ struct timespec *ref_time,
double offset,
double offset_sd,
double frequency,
double elapsed;
double correction_rate;
double uncorrected_offset, accumulate_offset, step_offset;
- struct timeval now, raw_now;
+ struct timespec now, raw_now;
assert(initialised);
LCL_ReadRawTime(&raw_now);
LCL_GetOffsetCorrection(&raw_now, &uncorrected_offset, NULL);
- UTI_AddDoubleToTimeval(&raw_now, uncorrected_offset, &now);
+ UTI_AddDoubleToTimespec(&raw_now, uncorrected_offset, &now);
- UTI_DiffTimevalsToDouble(&elapsed, &now, ref_time);
+ UTI_DiffTimespecsToDouble(&elapsed, &now, ref_time);
our_offset = offset + elapsed * frequency;
if (!is_offset_ok(our_offset))
our_root_dispersion = root_dispersion;
if (last_ref_update.tv_sec) {
- UTI_DiffTimevalsToDouble(&update_interval, &now, &last_ref_update);
+ UTI_DiffTimespecsToDouble(&update_interval, &now, &last_ref_update);
if (update_interval < 0.0)
update_interval = 0.0;
} else {
void
REF_SetManualReference
(
- struct timeval *ref_time,
+ struct timespec *ref_time,
double offset,
double frequency,
double skew
REF_SetUnsynchronised(void)
{
/* Variables required for logging to statistics log */
- struct timeval now, now_raw;
+ struct timespec now, now_raw;
double uncorrected_offset;
assert(initialised);
LCL_ReadRawTime(&now_raw);
LCL_GetOffsetCorrection(&now_raw, &uncorrected_offset, NULL);
- UTI_AddDoubleToTimeval(&now_raw, uncorrected_offset, &now);
+ UTI_AddDoubleToTimespec(&now_raw, uncorrected_offset, &now);
if (fb_drifts) {
schedule_fb_drift(&now);
void
REF_GetReferenceParams
(
- struct timeval *local_time,
+ struct timespec *local_time,
int *is_synchronised,
NTP_Leap *leap_status,
int *stratum,
uint32_t *ref_id,
- struct timeval *ref_time,
+ struct timespec *ref_time,
double *root_delay,
double *root_dispersion
)
assert(initialised);
if (are_we_synchronised) {
- UTI_DiffTimevalsToDouble(&elapsed, local_time, &our_ref_time);
+ UTI_DiffTimespecsToDouble(&elapsed, local_time, &our_ref_time);
dispersion = our_root_dispersion +
(our_skew + fabs(our_residual_freq) + LCL_GetMaxClockError()) * elapsed;
} else {
*leap_status = LEAP_Unsynchronised;
*stratum = NTP_MAX_STRATUM;
*ref_id = NTP_REFID_UNSYNC;
- ref_time->tv_sec = ref_time->tv_usec = 0;
+ UTI_ZeroTimespec(ref_time);
/* These values seem to be standard for a client, and
any peer or client of ours will ignore them anyway because
we don't claim to be synchronised */
int
REF_GetOurStratum(void)
{
- struct timeval now_cooked, ref_time;
+ struct timespec now_cooked, ref_time;
int synchronised, stratum;
NTP_Leap leap_status;
uint32_t ref_id;
int REF_IsLeapSecondClose(void)
{
- struct timeval now, now_raw;
+ struct timespec now, now_raw;
time_t t;
if (!our_leap_sec)
void
REF_GetTrackingReport(RPT_TrackingReport *rep)
{
- struct timeval now_raw, now_cooked;
+ struct timespec now_raw, now_cooked;
double correction;
int synchronised;
LCL_ReadRawTime(&now_raw);
LCL_GetOffsetCorrection(&now_raw, &correction, NULL);
- UTI_AddDoubleToTimeval(&now_raw, correction, &now_cooked);
+ UTI_AddDoubleToTimespec(&now_raw, correction, &now_cooked);
REF_GetReferenceParams(&now_cooked, &synchronised,
&rep->leap_status, &rep->stratum,
extern void REF_GetReferenceParams
(
- struct timeval *local_time,
+ struct timespec *local_time,
int *is_synchronised,
NTP_Leap *leap,
int *stratum,
uint32_t *ref_id,
- struct timeval *ref_time,
+ struct timespec *ref_time,
double *root_delay,
double *root_dispersion
);
int combined_sources,
uint32_t ref_id,
IPAddr *ref_ip,
- struct timeval *ref_time,
+ struct timespec *ref_time,
double offset,
double offset_sd,
double frequency,
extern void REF_SetManualReference
(
- struct timeval *ref_time,
+ struct timespec *ref_time,
double offset,
double frequency,
double skew
IPAddr ip_addr;
int stratum;
NTP_Leap leap_status;
- struct timeval ref_time;
+ struct timespec ref_time;
double current_correction;
double last_offset;
double rms_offset;
} RPT_SourcestatsReport;
typedef struct {
- struct timeval ref_time;
+ struct timespec ref_time;
unsigned short n_samples;
unsigned short n_runs;
unsigned long span_seconds;
} RPT_ServerStatsReport;
typedef struct {
- struct timeval when;
+ struct timespec when;
double slewed_offset;
double orig_offset;
double residual;
static void
apply_driftfile_time(time_t t)
{
- struct timeval now;
+ struct timespec now;
LCL_ReadCookedTime(&now, NULL);
static time_t rtc_ref;
-/* System clock (gettimeofday) samples associated with the above
- samples. */
-static struct timeval *system_times = NULL;
+/* System clock samples associated with the above samples. */
+static struct timespec *system_times = NULL;
/* Number of samples currently stored. */
static int n_samples;
memmove(rtc_sec, rtc_sec + new_first, n_to_save * sizeof(time_t));
memmove(rtc_trim, rtc_trim + new_first, n_to_save * sizeof(double));
- memmove(system_times, system_times + new_first, n_to_save * sizeof(struct timeval));
+ memmove(system_times, system_times + new_first, n_to_save * sizeof(struct timespec));
n_samples = n_to_save;
}
#define NEW_FIRST_WHEN_FULL 4
static void
-accumulate_sample(time_t rtc, struct timeval *sys)
+accumulate_sample(time_t rtc, struct timespec *sys)
{
if (n_samples == MAX_SAMPLES) {
for (i=0; i<n_samples; i++) {
rtc_rel[i] = rtc_trim[i] + (double)(rtc_sec[i] - rtc_ref);
offsets[i] = ((double) (rtc_ref - system_times[i].tv_sec) -
- (1.0e-6 * (double) system_times[i].tv_usec) +
+ (1.0e-9 * system_times[i].tv_nsec) +
rtc_rel[i]);
}
static void
slew_samples
-(struct timeval *raw, struct timeval *cooked,
+(struct timespec *raw, struct timespec *cooked,
double dfreq,
double doffset,
LCL_ChangeType change_type,
}
for (i=0; i<n_samples; i++) {
- UTI_AdjustTimeval(system_times + i, cooked, system_times + i, &delta_time,
+ UTI_AdjustTimespec(system_times + i, cooked, system_times + i, &delta_time,
dfreq, doffset);
}
{
rtc_sec = MallocArray(time_t, MAX_SAMPLES);
rtc_trim = MallocArray(double, MAX_SAMPLES);
- system_times = MallocArray(struct timeval, MAX_SAMPLES);
+ system_times = MallocArray(struct timespec, MAX_SAMPLES);
/* Setup details depending on configuration options */
setup_config();
/* ================================================== */
static void
-process_reading(time_t rtc_time, struct timeval *system_time)
+process_reading(time_t rtc_time, struct timespec *system_time)
{
double rtc_fast;
if (logfileid != -1) {
- rtc_fast = (double)(rtc_time - system_time->tv_sec) - 1.0e-6 * (double) system_time->tv_usec;
+ rtc_fast = (rtc_time - system_time->tv_sec) - 1.0e-9 * system_time->tv_nsec;
LOG_FileWrite(logfileid, "%s %14.6f %1d %14.6f %12.3f %2d %2d %4d",
UTI_TimeToLogForm(system_time->tv_sec),
{
int status;
unsigned long data;
- struct timeval sys_time;
+ struct timespec sys_time;
struct rtc_time rtc_raw;
struct tm rtc_tm;
time_t rtc_t;
goto turn_off_interrupt;
}
- /* Convert RTC time into a struct timeval */
+ /* Convert RTC time into a struct timespec */
rtc_tm.tm_sec = rtc_raw.tm_sec;
rtc_tm.tm_min = rtc_raw.tm_min;
rtc_tm.tm_hour = rtc_raw.tm_hour;
struct tm rtc_tm;
time_t rtc_t;
double accumulated_error, sys_offset;
- struct timeval new_sys_time, old_sys_time;
+ struct timespec new_sys_time, old_sys_time;
coefs_file_name = CNF_GetRtcFile();
new_sys_time.tv_sec = rtc_t;
/* Average error in the RTC reading */
- new_sys_time.tv_usec = 500000;
+ new_sys_time.tv_nsec = 500000000;
- UTI_AddDoubleToTimeval(&new_sys_time, -accumulated_error, &new_sys_time);
+ UTI_AddDoubleToTimespec(&new_sys_time, -accumulated_error, &new_sys_time);
if (new_sys_time.tv_sec < driftfile_time) {
LOG(LOGS_WARN, LOGF_RtcLinux, "RTC time before last driftfile modification (ignored)");
return 0;
}
- UTI_DiffTimevalsToDouble(&sys_offset, &old_sys_time, &new_sys_time);
+ UTI_DiffTimespecsToDouble(&sys_offset, &old_sys_time, &new_sys_time);
/* Set system time only if the step is larger than 1 second */
if (fabs(sys_offset) >= 1.0) {
RTC_Linux_GetReport(RPT_RTC_Report *report)
{
report->ref_time.tv_sec = coef_ref_time;
- report->ref_time.tv_usec = 0;
+ report->ref_time.tv_nsec = 0;
report->n_samples = n_samples;
report->n_runs = n_runs;
if (n_samples > 1) {
int
RTC_Linux_Trim(void)
{
- struct timeval now;
-
+ struct timespec now;
/* Remember the slope coefficient - we won't be able to determine a
good one in a few seconds when we determine the new offset! */
/* Estimate the offset in case writertc is called or chronyd
is terminated during rapid sampling */
- coef_seconds_fast = -now.tv_usec / 1e6 + 0.5;
+ coef_seconds_fast = -now.tv_nsec / 1.0e9 + 0.5;
coef_ref_time = now.tv_sec;
/* And start rapid sampling, interrupts on now */
static ARR_Instance file_handlers;
/* Timestamp when last select() returned */
-static struct timeval last_select_ts, last_select_ts_raw;
+static struct timespec last_select_ts, last_select_ts_raw;
static double last_select_ts_err;
/* ================================================== */
{
struct _TimerQueueEntry *next; /* Forward and back links in the list */
struct _TimerQueueEntry *prev;
- struct timeval tv; /* Local system time at which the
+ struct timespec ts; /* Local system time at which the
timeout is to expire. Clearly this
must be in terms of what the
operating system thinks of as
static TimerQueueEntry *tqe_free_list = NULL;
/* Timestamp when was last timeout dispatched for each class */
-static struct timeval last_class_dispatch[SCH_NumberOfClasses];
+static struct timespec last_class_dispatch[SCH_NumberOfClasses];
/* ================================================== */
/* ================================================== */
static void
-handle_slew(struct timeval *raw,
- struct timeval *cooked,
+handle_slew(struct timespec *raw,
+ struct timespec *cooked,
double dfreq,
double doffset,
LCL_ChangeType change_type,
/* ================================================== */
void
-SCH_GetLastEventTime(struct timeval *cooked, double *err, struct timeval *raw)
+SCH_GetLastEventTime(struct timespec *cooked, double *err, struct timespec *raw)
{
if (cooked) {
*cooked = last_select_ts;
/* ================================================== */
SCH_TimeoutID
-SCH_AddTimeout(struct timeval *tv, SCH_TimeoutHandler handler, SCH_ArbitraryArgument arg)
+SCH_AddTimeout(struct timespec *ts, SCH_TimeoutHandler handler, SCH_ArbitraryArgument arg)
{
TimerQueueEntry *new_tqe;
TimerQueueEntry *ptr;
new_tqe->id = get_new_tqe_id();
new_tqe->handler = handler;
new_tqe->arg = arg;
- new_tqe->tv = *tv;
+ new_tqe->ts = *ts;
new_tqe->class = SCH_ReservedTimeoutValue;
/* Now work out where to insert the new entry in the list */
for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) {
- if (UTI_CompareTimevals(&new_tqe->tv, &ptr->tv) == -1) {
+ if (UTI_CompareTimespecs(&new_tqe->ts, &ptr->ts) == -1) {
/* If the new entry comes before the current pointer location in
the list, we want to insert the new entry just before ptr. */
break;
SCH_TimeoutID
SCH_AddTimeoutByDelay(double delay, SCH_TimeoutHandler handler, SCH_ArbitraryArgument arg)
{
- struct timeval now, then;
+ struct timespec now, then;
assert(initialised);
assert(delay >= 0.0);
LCL_ReadRawTime(&now);
- UTI_AddDoubleToTimeval(&now, delay, &then);
- if (UTI_CompareTimevals(&now, &then) > 0) {
+ UTI_AddDoubleToTimespec(&now, delay, &then);
+ if (UTI_CompareTimespecs(&now, &then) > 0) {
LOG_FATAL(LOGF_Scheduler, "Timeout overflow");
}
{
TimerQueueEntry *new_tqe;
TimerQueueEntry *ptr;
- struct timeval now;
+ struct timespec now;
double diff, r;
double new_min_delay;
new_min_delay = min_delay;
/* Check the separation from the last dispatched timeout */
- UTI_DiffTimevalsToDouble(&diff, &now, &last_class_dispatch[class]);
+ UTI_DiffTimespecsToDouble(&diff, &now, &last_class_dispatch[class]);
if (diff < separation && diff >= 0.0 && diff + new_min_delay < separation) {
new_min_delay = separation - diff;
}
if necessary to keep at least the separation away */
for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) {
if (ptr->class == class) {
- UTI_DiffTimevalsToDouble(&diff, &ptr->tv, &now);
+ UTI_DiffTimespecsToDouble(&diff, &ptr->ts, &now);
if (new_min_delay > diff) {
if (new_min_delay - diff < separation) {
new_min_delay = diff + separation;
}
for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) {
- UTI_DiffTimevalsToDouble(&diff, &ptr->tv, &now);
+ UTI_DiffTimespecsToDouble(&diff, &ptr->ts, &now);
if (diff > new_min_delay) {
break;
}
new_tqe->id = get_new_tqe_id();
new_tqe->handler = handler;
new_tqe->arg = arg;
- UTI_AddDoubleToTimeval(&now, new_min_delay, &new_tqe->tv);
+ UTI_AddDoubleToTimespec(&now, new_min_delay, &new_tqe->ts);
new_tqe->class = class;
new_tqe->next = ptr;
completed). */
static void
-dispatch_timeouts(struct timeval *now) {
+dispatch_timeouts(struct timespec *now) {
TimerQueueEntry *ptr;
SCH_TimeoutHandler handler;
SCH_ArbitraryArgument arg;
LCL_ReadRawTime(now);
if (!(n_timer_queue_entries > 0 &&
- UTI_CompareTimevals(now, &(timer_queue.next->tv)) >= 0)) {
+ UTI_CompareTimespecs(now, &timer_queue.next->ts) >= 0)) {
break;
}
/* ================================================== */
static void
-handle_slew(struct timeval *raw,
- struct timeval *cooked,
+handle_slew(struct timespec *raw,
+ struct timespec *cooked,
double dfreq,
double doffset,
LCL_ChangeType change_type,
/* If a step change occurs, just shift all raw time stamps by the offset */
for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) {
- UTI_AddDoubleToTimeval(&ptr->tv, -doffset, &ptr->tv);
+ UTI_AddDoubleToTimespec(&ptr->ts, -doffset, &ptr->ts);
}
for (i = 0; i < SCH_NumberOfClasses; i++) {
- UTI_AddDoubleToTimeval(&last_class_dispatch[i], -doffset, &last_class_dispatch[i]);
+ UTI_AddDoubleToTimespec(&last_class_dispatch[i], -doffset, &last_class_dispatch[i]);
}
- UTI_AddDoubleToTimeval(&last_select_ts_raw, -doffset, &last_select_ts_raw);
+ UTI_AddDoubleToTimespec(&last_select_ts_raw, -doffset, &last_select_ts_raw);
}
- UTI_AdjustTimeval(&last_select_ts, cooked, &last_select_ts, &delta, dfreq, doffset);
+ UTI_AdjustTimespec(&last_select_ts, cooked, &last_select_ts, &delta, dfreq, doffset);
}
/* ================================================== */
#define JUMP_DETECT_THRESHOLD 10
static int
-check_current_time(struct timeval *prev_raw, struct timeval *raw, int timeout,
+check_current_time(struct timespec *prev_raw, struct timespec *raw, int timeout,
struct timeval *orig_select_tv,
struct timeval *rem_select_tv)
{
- struct timeval elapsed_min, elapsed_max;
+ struct timespec elapsed_min, elapsed_max, orig_select_ts, rem_select_ts;
double step, elapsed;
+ UTI_TimevalToTimespec(orig_select_tv, &orig_select_ts);
+
/* Get an estimate of the time spent waiting in the select() call. On some
systems (e.g. Linux) the timeout timeval is modified to return the
remaining time, use that information. */
if (timeout) {
- elapsed_max = elapsed_min = *orig_select_tv;
+ elapsed_max = elapsed_min = orig_select_ts;
} else if (rem_select_tv && rem_select_tv->tv_sec >= 0 &&
rem_select_tv->tv_sec <= orig_select_tv->tv_sec &&
(rem_select_tv->tv_sec != orig_select_tv->tv_sec ||
rem_select_tv->tv_usec != orig_select_tv->tv_usec)) {
- UTI_DiffTimevals(&elapsed_min, orig_select_tv, rem_select_tv);
+ UTI_TimevalToTimespec(rem_select_tv, &rem_select_ts);
+ UTI_DiffTimespecs(&elapsed_min, &orig_select_ts, &rem_select_ts);
elapsed_max = elapsed_min;
} else {
if (rem_select_tv)
- elapsed_max = *orig_select_tv;
+ elapsed_max = orig_select_ts;
else
- UTI_DiffTimevals(&elapsed_max, raw, prev_raw);
- elapsed_min.tv_sec = 0;
- elapsed_min.tv_usec = 0;
+ UTI_DiffTimespecs(&elapsed_max, raw, prev_raw);
+ UTI_ZeroTimespec(&elapsed_min);
}
if (last_select_ts_raw.tv_sec + elapsed_min.tv_sec >
return 1;
}
- UTI_DiffTimevalsToDouble(&step, &last_select_ts_raw, raw);
- UTI_TimevalToDouble(&elapsed_min, &elapsed);
+ UTI_DiffTimespecsToDouble(&step, &last_select_ts_raw, raw);
+ UTI_TimespecToDouble(&elapsed_min, &elapsed);
step += elapsed;
/* Cooked time may no longer be valid after dispatching the handlers */
fd_set read_fds, write_fds, *p_read_fds, *p_write_fds;
int status, errsv;
struct timeval tv, saved_tv, *ptv;
- struct timeval now, saved_now, cooked;
+ struct timespec ts, now, saved_now, cooked;
double err;
assert(initialised);
/* Check whether there is a timeout and set it up */
if (n_timer_queue_entries > 0) {
+ UTI_DiffTimespecs(&ts, &timer_queue.next->ts, &now);
+ assert(ts.tv_sec > 0 || ts.tv_nsec > 0);
- UTI_DiffTimevals(&tv, &(timer_queue.next->tv), &now);
+ UTI_TimespecToTimeval(&ts, &tv);
ptv = &tv;
- assert(tv.tv_sec > 0 || tv.tv_usec > 0);
saved_tv = tv;
-
} else {
ptv = NULL;
/* This is needed to fix a compiler warning */
extern void SCH_SetFileHandlerEvents(int fd, int events);
/* Get the time stamp taken after a file descriptor became ready or a timeout expired */
-extern void SCH_GetLastEventTime(struct timeval *cooked, double *err, struct timeval *raw);
+extern void SCH_GetLastEventTime(struct timespec *cooked, double *err, struct timespec *raw);
/* This queues a timeout to elapse at a given (raw) local time */
-extern SCH_TimeoutID SCH_AddTimeout(struct timeval *tv, SCH_TimeoutHandler, SCH_ArbitraryArgument);
+extern SCH_TimeoutID SCH_AddTimeout(struct timespec *ts, SCH_TimeoutHandler handler, SCH_ArbitraryArgument arg);
/* This queues a timeout to elapse at a given delta time relative to the current (raw) time */
extern SCH_TimeoutID SCH_AddTimeoutByDelay(double delay, SCH_TimeoutHandler, SCH_ArbitraryArgument);
/* Frequency offset, time offset and the time of the last smoothing update */
static double smooth_freq;
static double smooth_offset;
-static struct timeval last_update;
+static struct timespec last_update;
static void
-get_smoothing(struct timeval *now, double *poffset, double *pfreq,
+get_smoothing(struct timespec *now, double *poffset, double *pfreq,
double *pwander)
{
double elapsed, length, offset, freq, wander;
int i;
- UTI_DiffTimevalsToDouble(&elapsed, now, &last_update);
+ UTI_DiffTimespecsToDouble(&elapsed, now, &last_update);
offset = smooth_offset;
freq = smooth_freq;
}
static void
-update_smoothing(struct timeval *now, double offset, double freq)
+update_smoothing(struct timespec *now, double offset, double freq)
{
/* Don't accept offset/frequency until the clock has stabilized */
if (locked) {
}
static void
-handle_slew(struct timeval *raw, struct timeval *cooked, double dfreq,
+handle_slew(struct timespec *raw, struct timespec *cooked, double dfreq,
double doffset, LCL_ChangeType change_type, void *anything)
{
double delta;
update_smoothing(cooked, doffset, dfreq);
}
- UTI_AdjustTimeval(&last_update, cooked, &last_update, &delta, dfreq, doffset);
+ UTI_AdjustTimespec(&last_update, cooked, &last_update, &delta, dfreq, doffset);
}
void SMT_Initialise(void)
}
double
-SMT_GetOffset(struct timeval *now)
+SMT_GetOffset(struct timespec *now)
{
double offset, freq;
}
void
-SMT_Activate(struct timeval *now)
+SMT_Activate(struct timespec *now)
{
if (!enabled || !locked)
return;
}
void
-SMT_Reset(struct timeval *now)
+SMT_Reset(struct timespec *now)
{
int i;
}
void
-SMT_Leap(struct timeval *now, int leap)
+SMT_Leap(struct timespec *now, int leap)
{
/* When the leap-only mode is disabled, the leap second will be accumulated
in handle_slew() as a normal offset */
}
int
-SMT_GetSmoothingReport(RPT_SmoothingReport *report, struct timeval *now)
+SMT_GetSmoothingReport(RPT_SmoothingReport *report, struct timespec *now)
{
double length, elapsed;
int i;
report->freq_ppm *= -1.0e6;
report->wander_ppm *= -1.0e6;
- UTI_DiffTimevalsToDouble(&elapsed, now, &last_update);
+ UTI_DiffTimespecsToDouble(&elapsed, now, &last_update);
if (!locked && elapsed >= 0.0) {
for (i = 0, length = 0.0; i < NUM_STAGES; i++)
length += stages[i].length;
extern int SMT_IsEnabled(void);
-extern double SMT_GetOffset(struct timeval *now);
+extern double SMT_GetOffset(struct timespec *now);
-extern void SMT_Activate(struct timeval *now);
+extern void SMT_Activate(struct timespec *now);
-extern void SMT_Reset(struct timeval *now);
+extern void SMT_Reset(struct timespec *now);
-extern void SMT_Leap(struct timeval *now, int leap);
+extern void SMT_Leap(struct timespec *now, int leap);
-extern int SMT_GetSmoothingReport(RPT_SmoothingReport *report, struct timeval *now);
+extern int SMT_GetSmoothingReport(RPT_SmoothingReport *report, struct timespec *now);
#endif
/* Forward prototype */
static void
-slew_sources(struct timeval *raw, struct timeval *cooked, double dfreq,
+slew_sources(struct timespec *raw, struct timespec *cooked, double dfreq,
double doffset, LCL_ChangeType change_type, void *anything);
static void
add_dispersion(double dispersion, void *anything);
void SRC_AccumulateSample
(SRC_Instance inst,
- struct timeval *sample_time,
+ struct timespec *sample_time,
double offset,
double peer_delay,
double peer_dispersion,
inst->leap_status = leap_status;
DEBUG_LOG(LOGF_Sources, "ip=[%s] t=%s ofs=%f del=%f disp=%f str=%d",
- source_to_string(inst), UTI_TimevalToString(sample_time), -offset, root_delay, root_dispersion, stratum);
+ source_to_string(inst), UTI_TimespecToString(sample_time), -offset,
+ root_delay, root_dispersion, stratum);
if (REF_IsLeapSecondClose()) {
LOG(LOGS_INFO, LOGF_Sources, "Dropping sample around leap second");
/* ================================================== */
static int
-combine_sources(int n_sel_sources, struct timeval *ref_time, double *offset,
+combine_sources(int n_sel_sources, struct timespec *ref_time, double *offset,
double *offset_sd, double *frequency, double *skew)
{
- struct timeval src_ref_time;
+ struct timespec src_ref_time;
double src_offset, src_offset_sd, src_frequency, src_skew;
double src_root_delay, src_root_dispersion, sel_src_distance, elapsed;
double offset_weight, sum_offset_weight, sum_offset, sum2_offset_sd;
if (sources[index]->status == SRC_OK)
sources[index]->status = SRC_UNSELECTED;
- UTI_DiffTimevalsToDouble(&elapsed, ref_time, &src_ref_time);
+ UTI_DiffTimespecsToDouble(&elapsed, ref_time, &src_ref_time);
src_offset += elapsed * src_frequency;
offset_weight = 1.0 / sources[index]->sel_info.root_distance;
frequency_weight = 1.0 / src_skew;
SRC_SelectSource(SRC_Instance updated_inst)
{
struct SelectInfo *si;
- struct timeval now, ref_time;
+ struct timespec now, ref_time;
int i, j, j1, j2, index, sel_prefer, n_endpoints, n_sel_sources;
int n_badstats_sources, max_sel_reach, max_badstat_reach, sel_req_source;
int depth, best_depth, trust_depth, best_trust_depth;
/* ================================================== */
double
-SRC_PredictOffset(SRC_Instance inst, struct timeval *when)
+SRC_PredictOffset(SRC_Instance inst, struct timespec *when)
{
return SST_PredictOffset(inst->stats, when);
}
int
SRC_IsGoodSample(SRC_Instance inst, double offset, double delay,
- double max_delay_dev_ratio, double clock_error, struct timeval *when)
+ double max_delay_dev_ratio, double clock_error, struct timespec *when)
{
return SST_IsGoodSample(inst->stats, offset, delay, max_delay_dev_ratio,
clock_error, when);
the new regime. */
static void
-slew_sources(struct timeval *raw,
- struct timeval *cooked,
- double dfreq,
- double doffset,
- LCL_ChangeType change_type,
- void *anything)
+slew_sources(struct timespec *raw, struct timespec *cooked, double dfreq,
+ double doffset, LCL_ChangeType change_type, void *anything)
{
int i;
/* ================================================== */
int
-SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now)
+SRC_ReportSource(int index, RPT_SourceReport *report, struct timespec *now)
{
SRC_Instance src;
if ((index >= n_sources) || (index < 0)) {
/* ================================================== */
int
-SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report, struct timeval *now)
+SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report, struct timespec *now)
{
SRC_Instance src;
*/
-extern void SRC_AccumulateSample(SRC_Instance instance, struct timeval *sample_time, double offset, double peer_delay, double peer_dispersion, double root_delay, double root_dispersion, int stratum, NTP_Leap leap_status);
+extern void SRC_AccumulateSample(SRC_Instance instance, struct timespec *sample_time, double offset, double peer_delay, double peer_dispersion, double root_delay, double root_dispersion, int stratum, NTP_Leap leap_status);
/* This routine sets the source as receiving reachability updates */
extern void SRC_SetActive(SRC_Instance inst);
/* Predict the offset of the local clock relative to a given source at
a given local cooked time. Positive indicates local clock is FAST
relative to reference. */
-extern double SRC_PredictOffset(SRC_Instance inst, struct timeval *when);
+extern double SRC_PredictOffset(SRC_Instance inst, struct timespec *when);
/* Return the minimum peer delay amongst the previous samples
currently held in the register */
/* This routine determines if a new sample is good enough that it should be
accumulated */
-extern int SRC_IsGoodSample(SRC_Instance inst, double offset, double delay, double max_delay_dev_ratio, double clock_error, struct timeval *when);
+extern int SRC_IsGoodSample(SRC_Instance inst, double offset, double delay, double max_delay_dev_ratio, double clock_error, struct timespec *when);
extern void SRC_DumpSources(void);
extern int SRC_IsReachable(SRC_Instance inst);
extern int SRC_ReadNumberOfSources(void);
extern int SRC_ActiveSources(void);
-extern int SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now);
+extern int SRC_ReportSource(int index, RPT_SourceReport *report, struct timespec *now);
-extern int SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report, struct timeval *now);
+extern int SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report, struct timespec *now);
extern SRC_Type SRC_GetType(int index);
/* This is the estimated offset (+ve => local fast) at a particular time */
double estimated_offset;
double estimated_offset_sd;
- struct timeval offset_time;
+ struct timespec offset_time;
/* Number of runs of the same sign amongst the residuals */
int nruns;
/* This array contains the sample epochs, in terms of the local
clock. */
- struct timeval sample_times[MAX_SAMPLES * REGRESS_RUNS_RATIO];
+ struct timespec sample_times[MAX_SAMPLES * REGRESS_RUNS_RATIO];
/* This is an array of offsets, in seconds, corresponding to the
sample times. In this module, we use the convention that
inst->skew = 2000.0e-6;
inst->estimated_offset = 0.0;
inst->estimated_offset_sd = 86400.0; /* Assume it's at least within a day! */
- inst->offset_time.tv_sec = 0;
- inst->offset_time.tv_usec = 0;
+ UTI_ZeroTimespec(&inst->offset_time);
inst->variance = 16.0;
inst->nruns = 0;
inst->asymmetry_run = 0;
/* ================================================== */
void
-SST_AccumulateSample(SST_Stats inst, struct timeval *sample_time,
+SST_AccumulateSample(SST_Stats inst, struct timespec *sample_time,
double offset,
double peer_delay, double peer_dispersion,
double root_delay, double root_dispersion,
/* Make sure it's newer than the last sample */
if (inst->n_samples &&
- UTI_CompareTimevals(&inst->sample_times[inst->last_sample], sample_time) >= 0) {
+ UTI_CompareTimespecs(&inst->sample_times[inst->last_sample], sample_time) >= 0) {
LOG(LOGS_WARN, LOGF_SourceStats, "Out of order sample detected, discarding history for %s",
inst->ip_addr ? UTI_IPToString(inst->ip_addr) : UTI_RefidToString(inst->refid));
SST_ResetInstance(inst);
static void
convert_to_intervals(SST_Stats inst, double *times_back)
{
- struct timeval *newest_tv;
+ struct timespec *ts;
int i;
- newest_tv = &(inst->sample_times[inst->last_sample]);
+ ts = &inst->sample_times[inst->last_sample];
for (i = -inst->runs_samples; i < inst->n_samples; i++) {
/* The entries in times_back[] should end up negative */
- UTI_DiffTimevalsToDouble(×_back[i],
- &inst->sample_times[get_runsbuf_index(inst, i)], newest_tv);
+ UTI_DiffTimespecsToDouble(×_back[i],
+ &inst->sample_times[get_runsbuf_index(inst, i)], ts);
}
}
/* ================================================== */
void
-SST_GetSelectionData(SST_Stats inst, struct timeval *now,
+SST_GetSelectionData(SST_Stats inst, struct timespec *now,
int *stratum,
double *offset_lo_limit,
double *offset_hi_limit,
*stratum = inst->strata[get_buf_index(inst, inst->n_samples - 1)];
*variance = inst->variance;
- UTI_DiffTimevalsToDouble(&sample_elapsed, now, &inst->sample_times[i]);
+ UTI_DiffTimespecsToDouble(&sample_elapsed, now, &inst->sample_times[i]);
offset = inst->offsets[i] + sample_elapsed * inst->estimated_frequency;
*root_distance = 0.5 * inst->root_delays[j] +
inst->root_dispersions[j] + sample_elapsed * inst->skew;
double average_offset, elapsed;
int average_ok;
/* average_ok ignored for now */
- UTI_DiffTimevalsToDouble(&elapsed, now, &(inst->offset_time));
+ UTI_DiffTimespecsToDouble(&elapsed, now, &(inst->offset_time));
average_offset = inst->estimated_offset + inst->estimated_frequency * elapsed;
if (fabs(average_offset - offset) <=
inst->peer_dispersions[j] + 0.5 * inst->peer_delays[i]) {
#endif
i = get_runsbuf_index(inst, 0);
- UTI_DiffTimevalsToDouble(first_sample_ago, now, &inst->sample_times[i]);
+ UTI_DiffTimespecsToDouble(first_sample_ago, now, &inst->sample_times[i]);
i = get_runsbuf_index(inst, inst->n_samples - 1);
- UTI_DiffTimevalsToDouble(last_sample_ago, now, &inst->sample_times[i]);
+ UTI_DiffTimespecsToDouble(last_sample_ago, now, &inst->sample_times[i]);
*select_ok = inst->regression_ok;
/* ================================================== */
void
-SST_GetTrackingData(SST_Stats inst, struct timeval *ref_time,
+SST_GetTrackingData(SST_Stats inst, struct timespec *ref_time,
double *average_offset, double *offset_sd,
double *frequency, double *skew,
double *root_delay, double *root_dispersion)
*skew = inst->skew;
*root_delay = inst->root_delays[j];
- UTI_DiffTimevalsToDouble(&elapsed_sample, &inst->offset_time, &inst->sample_times[i]);
+ UTI_DiffTimespecsToDouble(&elapsed_sample, &inst->offset_time, &inst->sample_times[i]);
*root_dispersion = inst->root_dispersions[j] + inst->skew * elapsed_sample;
DEBUG_LOG(LOGF_SourceStats, "n=%d freq=%f (%.3fppm) skew=%f (%.3fppm) avoff=%f offsd=%f disp=%f",
/* ================================================== */
void
-SST_SlewSamples(SST_Stats inst, struct timeval *when, double dfreq, double doffset)
+SST_SlewSamples(SST_Stats inst, struct timespec *when, double dfreq, double doffset)
{
int m, i;
double delta_time;
- struct timeval *sample, prev;
+ struct timespec *sample, prev;
double prev_offset, prev_freq;
if (!inst->n_samples)
for (m = -inst->runs_samples; m < inst->n_samples; m++) {
i = get_runsbuf_index(inst, m);
- sample = &(inst->sample_times[i]);
+ sample = &inst->sample_times[i];
prev = *sample;
- UTI_AdjustTimeval(sample, when, sample, &delta_time, dfreq, doffset);
+ UTI_AdjustTimespec(sample, when, sample, &delta_time, dfreq, doffset);
inst->offsets[i] += delta_time;
}
prev = inst->offset_time;
prev_offset = inst->estimated_offset;
prev_freq = inst->estimated_frequency;
- UTI_AdjustTimeval(&(inst->offset_time), when, &(inst->offset_time),
+ UTI_AdjustTimespec(&inst->offset_time, when, &inst->offset_time,
&delta_time, dfreq, doffset);
inst->estimated_offset += delta_time;
inst->estimated_frequency = (inst->estimated_frequency - dfreq) / (1.0 - dfreq);
DEBUG_LOG(LOGF_SourceStats, "n=%d m=%d old_off_time=%s new=%s old_off=%f new_off=%f old_freq=%.3f new_freq=%.3f",
inst->n_samples, inst->runs_samples,
- UTI_TimevalToString(&prev), UTI_TimevalToString(&(inst->offset_time)),
+ UTI_TimespecToString(&prev), UTI_TimespecToString(&inst->offset_time),
prev_offset, inst->estimated_offset,
1.0e6 * prev_freq, 1.0e6 * inst->estimated_frequency);
}
/* ================================================== */
double
-SST_PredictOffset(SST_Stats inst, struct timeval *when)
+SST_PredictOffset(SST_Stats inst, struct timespec *when)
{
double elapsed;
return 0.0;
}
} else {
- UTI_DiffTimevalsToDouble(&elapsed, when, &inst->offset_time);
+ UTI_DiffTimespecsToDouble(&elapsed, when, &inst->offset_time);
return inst->estimated_offset + elapsed * inst->estimated_frequency;
}
int
SST_IsGoodSample(SST_Stats inst, double offset, double delay,
- double max_delay_dev_ratio, double clock_error, struct timeval *when)
+ double max_delay_dev_ratio, double clock_error, struct timespec *when)
{
double elapsed, allowed_increase, delay_increase;
if (inst->n_samples < 3)
return 1;
- UTI_DiffTimevalsToDouble(&elapsed, when, &inst->offset_time);
+ UTI_DiffTimespecsToDouble(&elapsed, when, &inst->offset_time);
/* Require that the ratio of the increase in delay from the minimum to the
standard deviation is less than max_delay_dev_ratio. In the allowed
fprintf(out, "%08lx %08lx %.6e %.6e %.6e %.6e %.6e %.6e %.6e %d\n",
(unsigned long) inst->sample_times[i].tv_sec,
- (unsigned long) inst->sample_times[i].tv_usec,
+ (unsigned long)inst->sample_times[i].tv_nsec / 1000,
inst->offsets[i],
inst->orig_offsets[j],
inst->peer_delays[i],
/* This is the branch taken if the read is SUCCESSFUL */
inst->sample_times[i].tv_sec = sec;
- inst->sample_times[i].tv_usec = usec;
+ inst->sample_times[i].tv_nsec = 1000 * usec;
+ UTI_NormaliseTimespec(&inst->sample_times[i]);
line_number++;
}
/* ================================================== */
void
-SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timeval *now)
+SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timespec *now)
{
int i, j;
- struct timeval ago;
+ struct timespec ago;
if (inst->n_samples > 0) {
i = get_runsbuf_index(inst, inst->n_samples - 1);
report->latest_meas_err = 0.5*inst->root_delays[j] + inst->root_dispersions[j];
report->stratum = inst->strata[j];
- UTI_DiffTimevals(&ago, now, &inst->sample_times[i]);
+ UTI_DiffTimespecs(&ago, now, &inst->sample_times[i]);
report->latest_meas_ago = ago.tv_sec;
} else {
report->latest_meas_ago = (uint32_t)-1;
/* ================================================== */
void
-SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report, struct timeval *now)
+SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report, struct timespec *now)
{
double dspan;
double elapsed, sample_elapsed;
if (inst->n_samples > 1) {
li = get_runsbuf_index(inst, inst->n_samples - 1);
lj = get_buf_index(inst, inst->n_samples - 1);
- UTI_DiffTimevalsToDouble(&dspan, &inst->sample_times[li],
+ UTI_DiffTimespecsToDouble(&dspan, &inst->sample_times[li],
&inst->sample_times[get_runsbuf_index(inst, 0)]);
report->span_seconds = (unsigned long) (dspan + 0.5);
if (inst->n_samples > 3) {
- UTI_DiffTimevalsToDouble(&elapsed, now, &inst->offset_time);
+ UTI_DiffTimespecsToDouble(&elapsed, now, &inst->offset_time);
bi = get_runsbuf_index(inst, inst->best_single_sample);
bj = get_buf_index(inst, inst->best_single_sample);
- UTI_DiffTimevalsToDouble(&sample_elapsed, now, &inst->sample_times[bi]);
+ UTI_DiffTimespecsToDouble(&sample_elapsed, now, &inst->sample_times[bi]);
report->est_offset = inst->estimated_offset + elapsed * inst->estimated_frequency;
report->est_offset_err = (inst->estimated_offset_sd +
sample_elapsed * inst->skew +
stratum is the stratum of the source from which the sample came.
*/
-extern void SST_AccumulateSample(SST_Stats inst, struct timeval *sample_time, double offset, double peer_delay, double peer_dispersion, double root_delay, double root_dispersion, int stratum);
+extern void SST_AccumulateSample(SST_Stats inst, struct timespec *sample_time, double offset, double peer_delay, double peer_dispersion, double root_delay, double root_dispersion, int stratum);
/* This function runs the linear regression operation on the data. It
finds the set of most recent samples that give the tightest
/* Get data needed for selection */
extern void
-SST_GetSelectionData(SST_Stats inst, struct timeval *now,
+SST_GetSelectionData(SST_Stats inst, struct timespec *now,
int *stratum,
double *offset_lo_limit,
double *offset_hi_limit,
/* Get data needed when setting up tracking on this source */
extern void
-SST_GetTrackingData(SST_Stats inst, struct timeval *ref_time,
+SST_GetTrackingData(SST_Stats inst, struct timespec *ref_time,
double *average_offset, double *offset_sd,
double *frequency, double *skew,
double *root_delay, double *root_dispersion);
*/
-extern void SST_SlewSamples(SST_Stats inst, struct timeval *when, double dfreq, double doffset);
+extern void SST_SlewSamples(SST_Stats inst, struct timespec *when, double dfreq, double doffset);
/* This routine is called when an indeterminate offset is introduced
into the local time. */
/* Predict the offset of the local clock relative to a given source at
a given local cooked time. Positive indicates local clock is FAST
relative to reference. */
-extern double SST_PredictOffset(SST_Stats inst, struct timeval *when);
+extern double SST_PredictOffset(SST_Stats inst, struct timespec *when);
/* Find the minimum round trip delay in the register */
extern double SST_MinRoundTripDelay(SST_Stats inst);
/* This routine determines if a new sample is good enough that it should be
accumulated */
extern int SST_IsGoodSample(SST_Stats inst, double offset, double delay,
- double max_delay_dev_ratio, double clock_error, struct timeval *when);
+ double max_delay_dev_ratio, double clock_error, struct timespec *when);
extern void SST_SaveToFile(SST_Stats inst, FILE *out);
extern int SST_LoadFromFile(SST_Stats inst, FILE *in);
-extern void SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timeval *now);
+extern void SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timespec *now);
-extern void SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report, struct timeval *now);
+extern void SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report, struct timespec *now);
extern int SST_Samples(SST_Stats inst);
}
void
-NSR_ReportSource(RPT_SourceReport *report, struct timeval *now)
+NSR_ReportSource(RPT_SourceReport *report, struct timespec *now)
{
memset(report, 0, sizeof (*report));
}
}
void
-RCL_ReportSource(RPT_SourceReport *report, struct timeval *now)
+RCL_ReportSource(RPT_SourceReport *report, struct timespec *now)
{
memset(report, 0, sizeof (*report));
}
static double slew_freq;
/* Time (raw) of last update of slewing frequency and offset */
-static struct timeval slew_start;
+static struct timespec slew_start;
/* Limits for the slew timeout */
#define MIN_SLEW_TIMEOUT 1.0
/* Adjust slew_start on clock step */
static void
-handle_step(struct timeval *raw, struct timeval *cooked, double dfreq,
+handle_step(struct timespec *raw, struct timespec *cooked, double dfreq,
double doffset, LCL_ChangeType change_type, void *anything)
{
if (change_type == LCL_ChangeUnknownStep) {
offset_register = 0.0;
update_slew();
} else if (change_type == LCL_ChangeStep) {
- UTI_AddDoubleToTimeval(&slew_start, -doffset, &slew_start);
+ UTI_AddDoubleToTimespec(&slew_start, -doffset, &slew_start);
}
}
/* ================================================== */
static void
-stop_fastslew(struct timeval *now)
+stop_fastslew(struct timespec *now)
{
double corr;
static void
update_slew(void)
{
- struct timeval now, end_of_slew;
+ struct timespec now, end_of_slew;
double old_slew_freq, total_freq, corr_freq, duration;
/* Remove currently running timeout */
LCL_ReadRawTime(&now);
/* Adjust the offset register by achieved slew */
- UTI_DiffTimevalsToDouble(&duration, &now, &slew_start);
+ UTI_DiffTimespecsToDouble(&duration, &now, &slew_start);
offset_register -= slew_freq * duration;
stop_fastslew(&now);
}
/* Restart timer for the next update */
- UTI_AddDoubleToTimeval(&now, duration, &end_of_slew);
+ UTI_AddDoubleToTimespec(&now, duration, &end_of_slew);
slew_timeout_id = SCH_AddTimeout(&end_of_slew, handle_end_of_slew, NULL);
slew_start = now;
/* Determine the correction to generate the cooked time for given raw time */
static void
-offset_convert(struct timeval *raw,
+offset_convert(struct timespec *raw,
double *corr, double *err)
{
double duration, fastslew_corr, fastslew_err;
- UTI_DiffTimevalsToDouble(&duration, raw, &slew_start);
+ UTI_DiffTimespecsToDouble(&duration, raw, &slew_start);
if (drv_get_offset_correction && fastslew_active) {
drv_get_offset_correction(raw, &fastslew_corr, &fastslew_err);
static int
apply_step_offset(double offset)
{
- struct timeval old_time, new_time;
+ struct timespec old_time, new_time;
+ struct timeval new_time_tv;
double err;
LCL_ReadRawTime(&old_time);
- UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
+ UTI_AddDoubleToTimespec(&old_time, -offset, &new_time);
+ UTI_TimespecToTimeval(&new_time, &new_time_tv);
- if (PRV_SetTime(&new_time, NULL) < 0) {
+ if (PRV_SetTime(&new_time_tv, NULL) < 0) {
DEBUG_LOG(LOGF_SysGeneric, "settimeofday() failed");
return 0;
}
LCL_ReadRawTime(&old_time);
- UTI_DiffTimevalsToDouble(&err, &old_time, &new_time);
+ UTI_DiffTimespecsToDouble(&err, &old_time, &new_time);
lcl_InvokeDispersionNotifyHandlers(fabs(err));
void
SYS_Generic_Finalise(void)
{
- struct timeval now;
+ struct timespec now;
/* Must *NOT* leave a slew running - clock could drift way off
if the daemon is not restarted */
#include "sys_macosx.h"
#include "conf.h"
+#include "local.h"
#include "localp.h"
#include "logging.h"
#include "sched.h"
/* This register contains the number of seconds by which the local
clock was estimated to be fast of reference time at the epoch when
- gettimeofday() returned T0 */
+ LCL_ReadRawTime() returned T0 */
static double offset_register;
/* This register contains the epoch to which the offset is referenced */
-static struct timeval T0;
+static struct timespec T0;
/* This register contains the current estimate of the system
frequency, in absolute (NOT ppm) */
static double drift_removal_interval;
static double current_drift_removal_interval;
-static struct timeval Tdrift;
+static struct timespec Tdrift;
/* weighting applied to error in calculating drift_removal_interval */
#define ERROR_WEIGHT (0.5)
/* RTC synchronisation - once an hour */
-static struct timeval last_rtc_sync;
+static struct timespec last_rtc_sync;
#define RTC_SYNC_INTERVAL (60 * 60.0)
/* ================================================== */
drift_removal_interval = DRIFT_REMOVAL_INTERVAL;
current_drift_removal_interval = DRIFT_REMOVAL_INTERVAL;
- if (gettimeofday(&T0, NULL) < 0) {
- LOG_FATAL(LOGF_SysMacOSX, "gettimeofday() failed");
- }
+ LCL_ReadRawTime(&T0);
Tdrift = T0;
last_rtc_sync = T0;
start_adjust(void)
{
struct timeval newadj, oldadj;
- struct timeval T1;
+ struct timespec T1;
double elapsed, accrued_error, predicted_error, drift_removal_elapsed;
double adjust_required;
double rounding_error;
double old_adjust_remaining;
/* Determine the amount of error built up since the last adjustment */
- if (gettimeofday(&T1, NULL) < 0) {
- LOG_FATAL(LOGF_SysMacOSX, "gettimeofday() failed");
- }
+ LCL_ReadRawTime(&T1);
- UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
+ UTI_DiffTimespecsToDouble(&elapsed, &T1, &T0);
accrued_error = elapsed * current_freq;
- UTI_DiffTimevalsToDouble(&drift_removal_elapsed, &T1, &Tdrift);
+ UTI_DiffTimespecsToDouble(&drift_removal_elapsed, &T1, &Tdrift);
/* To allow for the clock being stepped either forward or backwards, clamp
the elapsed time to bounds [ 0.0, current_drift_removal_interval ] */
static void
stop_adjust(void)
{
- struct timeval T1;
+ struct timespec T1;
struct timeval zeroadj, remadj;
double adjustment_remaining, adjustment_achieved;
double elapsed, elapsed_plus_adjust;
LOG_FATAL(LOGF_SysMacOSX, "adjtime() failed");
}
- if (gettimeofday(&T1, NULL) < 0) {
- LOG_FATAL(LOGF_SysMacOSX, "gettimeofday() failed");
- }
+ LCL_ReadRawTime(&T1);
- UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
+ UTI_DiffTimespecsToDouble(&elapsed, &T1, &T0);
UTI_TimevalToDouble(&remadj, &adjustment_remaining);
adjustment_achieved = adjustment_requested - adjustment_remaining;
static int
apply_step_offset(double offset)
{
- struct timeval old_time, new_time, T1;
+ struct timespec old_time, new_time, T1;
+ struct timeval new_time_tv;
stop_adjust();
- if (gettimeofday(&old_time, NULL) < 0) {
- LOG_FATAL(LOGF_SysMacOSX, "gettimeofday() failed");
- }
+ LCL_ReadRawTime(&old_time);
- UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
+ UTI_AddDoubleToTimespec(&old_time, -offset, &new_time);
+ UTI_TimespecToTimeval(&new_time, &new_time_tv);
- if (PRV_SetTime(&new_time, NULL) < 0) {
+ if (PRV_SetTime(&new_time_tv, NULL) < 0) {
DEBUG_LOG(LOGF_SysMacOSX, "settimeofday() failed");
return 0;
}
- UTI_AddDoubleToTimeval(&T0, -offset, &T1);
+ UTI_AddDoubleToTimespec(&T0, -offset, &T1);
T0 = T1;
start_adjust();
/* ================================================== */
static void
-get_offset_correction(struct timeval *raw,
+get_offset_correction(struct timespec *raw,
double *corr, double *err)
{
stop_adjust();
stop_adjust();
- if (gettimeofday(&Tdrift, NULL) < 0) {
- LOG_FATAL(LOGF_SysMacOSX, "gettimeofday() failed");
- }
+ LCL_ReadRawTime(&Tdrift);
current_drift_removal_interval = drift_removal_interval;
drift_removal_interval = MAX(drift_removal_interval, DRIFT_REMOVAL_INTERVAL);
} else {
if (CNF_GetRtcSync()) {
- struct timeval now;
+ struct timespec now;
double rtc_sync_elapsed;
SCH_GetLastEventTime(NULL, NULL, &now);
- UTI_DiffTimevalsToDouble(&rtc_sync_elapsed, &now, &last_rtc_sync);
+ UTI_DiffTimespecsToDouble(&rtc_sync_elapsed, &now, &last_rtc_sync);
if (fabs(rtc_sync_elapsed) >= RTC_SYNC_INTERVAL) {
/* update the RTC by applying a step of 0.0 secs */
apply_step_offset(0.0);
accrue_offset(double offset, double corr_rate)
{
struct timeval newadj, oldadj;
+ double doldadj;
UTI_DoubleToTimeval(-offset, &newadj);
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
/* Add the old remaining adjustment if not zero */
- UTI_TimevalToDouble(&oldadj, &offset);
- if (offset != 0.0) {
- UTI_AddDoubleToTimeval(&newadj, offset, &newadj);
+ UTI_TimevalToDouble(&oldadj, &doldadj);
+ if (doldadj != 0.0) {
+ UTI_DoubleToTimeval(-offset + doldadj, &newadj);
if (PRV_AdjustTime(&newadj, NULL) < 0)
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
}
/* ================================================== */
static void
-get_offset_correction(struct timeval *raw,
+get_offset_correction(struct timespec *raw,
double *corr, double *err)
{
struct timeval remadj;
DEBUG_LOG(LOGF_TempComp, "tempcomp updated to %f for %f", comp, temp);
if (logfileid != -1) {
- struct timeval now;
+ struct timespec now;
LCL_ReadCookedTime(&now, NULL);
LOG_FileWrite(logfileid, "%s %11.4e %11.4e",
test_unit(void)
{
int i, j, index;
- struct timeval tv;
+ struct timespec ts;
IPAddr ip;
char conf[][100] = {
"clientloglimit 10000",
for (i = 0; i < 500; i++) {
DEBUG_LOG(0, "iteration %d", i);
- tv.tv_sec = (time_t)random() & 0x0fffffff;
- tv.tv_usec = 0;
+ ts.tv_sec = (time_t)random() & 0x0fffffff;
+ ts.tv_nsec = 0;
for (j = 0; j < 1000; j++) {
TST_GetRandomAddress(&ip, IPADDR_UNSPEC, i % 8 ? -1 : i / 8 % 9);
DEBUG_LOG(0, "address %s", UTI_IPToString(&ip));
if (random() % 2) {
- index = CLG_LogNTPAccess(&ip, &tv);
+ index = CLG_LogNTPAccess(&ip, &ts);
TEST_CHECK(index >= 0);
CLG_LimitNTPResponseRate(index);
} else {
- index = CLG_LogCommandAccess(&ip, &tv);
+ index = CLG_LogCommandAccess(&ip, &ts);
TEST_CHECK(index >= 0);
CLG_LimitCommandResponseRate(index);
}
- UTI_AddDoubleToTimeval(&tv, (1 << random() % 14) / 100.0, &tv);
+ UTI_AddDoubleToTimespec(&ts, (1 << random() % 14) / 100.0, &ts);
}
}
TEST_CHECK(ARR_GetSize(records) == 128);
for (i = j = 0; i < 10000; i++) {
- tv.tv_sec += 1;
- index = CLG_LogNTPAccess(&ip, &tv);
+ ts.tv_sec += 1;
+ index = CLG_LogNTPAccess(&ip, &ts);
TEST_CHECK(index >= 0);
if (!CLG_LimitNTPResponseRate(index))
j++;
IPAddr addr;
int i, j, k, l, samples, sel_options;
double offset, delay, disp;
- struct timeval tv;
+ struct timespec ts;
CNF_Initialise(0);
LCL_Initialise();
offset = TST_GetRandomDouble(-1.0, 1.0);
for (k = 0; k < samples; k++) {
- SCH_GetLastEventTime(&tv, NULL, NULL);
- UTI_AddDoubleToTimeval(&tv, TST_GetRandomDouble(k - samples, k - samples + 1), &tv);
+ SCH_GetLastEventTime(&ts, NULL, NULL);
+ UTI_AddDoubleToTimespec(&ts, TST_GetRandomDouble(k - samples, k - samples + 1), &ts);
offset += TST_GetRandomDouble(-1.0e-2, 1.0e-2);
delay = TST_GetRandomDouble(1.0e-6, 1.0e-1);
DEBUG_LOG(0, "source %d sample %d offset %f delay %f disp %f", j, k,
offset, delay, disp);
- SRC_AccumulateSample(srcs[j], &tv, offset, delay, disp, delay, disp,
+ SRC_AccumulateSample(srcs[j], &ts, offset, delay, disp, delay, disp,
1, LEAP_Normal);
}
}
for (j = 0; j < sizeof (srcs) / sizeof (srcs[0]); j++) {
- SRC_ReportSource(j, &report, &tv);
+ SRC_ReportSource(j, &report, &ts);
SRC_DestroyInstance(srcs[j]);
}
}
}
static void
-offset_convert(struct timeval *raw, double *corr, double *err)
+offset_convert(struct timespec *raw, double *corr, double *err)
{
*corr = 0.0;
if (err)
#include "util.h"
#include "hash.h"
+#define NSEC_PER_SEC 1000000000
+
+/* ================================================== */
+
+void
+UTI_ZeroTimespec(struct timespec *ts)
+{
+ ts->tv_sec = 0;
+ ts->tv_nsec = 0;
+}
+
+/* ================================================== */
+
+void
+UTI_TimevalToTimespec(struct timeval *tv, struct timespec *ts)
+{
+ ts->tv_sec = tv->tv_sec;
+ ts->tv_nsec = 1000 * tv->tv_usec;
+}
+
+/* ================================================== */
+
+void
+UTI_TimespecToTimeval(struct timespec *ts, struct timeval *tv)
+{
+ tv->tv_sec = ts->tv_sec;
+ tv->tv_usec = ts->tv_nsec / 1000;
+}
+
+/* ================================================== */
+
+void
+UTI_TimespecToDouble(struct timespec *ts, double *d)
+{
+ *d = ts->tv_sec + 1.0e-9 * ts->tv_nsec;
+}
+
+/* ================================================== */
+
+void
+UTI_DoubleToTimespec(double d, struct timespec *ts)
+{
+ ts->tv_sec = d;
+ ts->tv_nsec = 1.0e9 * (d - ts->tv_sec);
+ UTI_NormaliseTimespec(ts);
+}
+
+/* ================================================== */
+
+void
+UTI_NormaliseTimespec(struct timespec *ts)
+{
+ if (ts->tv_nsec >= NSEC_PER_SEC || ts->tv_nsec < 0) {
+ ts->tv_sec += ts->tv_nsec / NSEC_PER_SEC;
+ ts->tv_nsec = ts->tv_nsec % NSEC_PER_SEC;
+
+ /* If seconds are negative nanoseconds would end up negative too */
+ if (ts->tv_nsec < 0) {
+ ts->tv_sec--;
+ ts->tv_nsec += NSEC_PER_SEC;
+ }
+ }
+}
+
/* ================================================== */
void
/* ================================================== */
-int
-UTI_CompareTimevals(struct timeval *a, struct timeval *b)
-{
- if (a->tv_sec < b->tv_sec) {
- return -1;
- } else if (a->tv_sec > b->tv_sec) {
- return +1;
- } else {
- if (a->tv_usec < b->tv_usec) {
- return -1;
- } else if (a->tv_usec > b->tv_usec) {
- return +1;
- } else {
- return 0;
- }
- }
-}
-
-/* ================================================== */
-
void
UTI_NormaliseTimeval(struct timeval *x)
{
/* ================================================== */
-void
-UTI_DiffTimevals(struct timeval *result,
- struct timeval *a,
- struct timeval *b)
+int
+UTI_CompareTimespecs(struct timespec *a, struct timespec *b)
{
- result->tv_sec = a->tv_sec - b->tv_sec;
- result->tv_usec = a->tv_usec - b->tv_usec;
+ if (a->tv_sec < b->tv_sec)
+ return -1;
+ if (a->tv_sec > b->tv_sec)
+ return 1;
+ if (a->tv_nsec < b->tv_nsec)
+ return -1;
+ if (a->tv_nsec > b->tv_nsec)
+ return 1;
+ return 0;
+}
- /* Correct microseconds field to bring it into the range
- (0,1000000) */
+/* ================================================== */
- UTI_NormaliseTimeval(result); /* JGH */
+void
+UTI_DiffTimespecs(struct timespec *result, struct timespec *a, struct timespec *b)
+{
+ result->tv_sec = a->tv_sec - b->tv_sec;
+ result->tv_nsec = a->tv_nsec - b->tv_nsec;
+ UTI_NormaliseTimespec(result);
}
/* ================================================== */
/* Calculate result = a - b and return as a double */
void
-UTI_DiffTimevalsToDouble(double *result,
- struct timeval *a,
- struct timeval *b)
+UTI_DiffTimespecsToDouble(double *result, struct timespec *a, struct timespec *b)
{
- *result = (double)(a->tv_sec - b->tv_sec) +
- (double)(a->tv_usec - b->tv_usec) * 1.0e-6;
+ *result = (a->tv_sec - b->tv_sec) + 1.0e-9 * (a->tv_nsec - b->tv_nsec);
}
/* ================================================== */
void
-UTI_AddDoubleToTimeval(struct timeval *start,
- double increment,
- struct timeval *end)
+UTI_AddDoubleToTimespec(struct timespec *start, double increment, struct timespec *end)
{
- long int_part, frac_part;
-
- /* Don't want to do this by using (long)(1000000 * increment), since
- that will only cope with increments up to +/- 2148 seconds, which
- is too marginal here. */
+ time_t int_part;
- int_part = (long) increment;
- increment = (increment - int_part) * 1.0e6;
- frac_part = (long) (increment > 0.0 ? increment + 0.5 : increment - 0.5);
-
- end->tv_sec = int_part + start->tv_sec;
- end->tv_usec = frac_part + start->tv_usec;
-
- UTI_NormaliseTimeval(end);
+ int_part = increment;
+ end->tv_sec = start->tv_sec + int_part;
+ end->tv_nsec = start->tv_nsec + 1.0e9 * (increment - int_part);
+ UTI_NormaliseTimespec(end);
}
/* ================================================== */
-/* Calculate the average and difference (as a double) of two timevals */
+/* Calculate the average and difference (as a double) of two timespecs */
void
-UTI_AverageDiffTimevals (struct timeval *earlier,
- struct timeval *later,
- struct timeval *average,
- double *diff)
+UTI_AverageDiffTimespecs(struct timespec *earlier, struct timespec *later,
+ struct timespec *average, double *diff)
{
- struct timeval tvdiff;
- struct timeval tvhalf;
-
- UTI_DiffTimevals(&tvdiff, later, earlier);
- *diff = (double)tvdiff.tv_sec + 1.0e-6 * (double)tvdiff.tv_usec;
-
- if (*diff < 0.0) {
- /* Either there's a bug elsewhere causing 'earlier' and 'later' to
- be backwards, or something wierd has happened. Maybe when we
- change the frequency on Linux? */
-
- /* Assume the required behaviour is to treat it as zero */
- *diff = 0.0;
- }
-
- tvhalf.tv_sec = tvdiff.tv_sec / 2;
- tvhalf.tv_usec = tvdiff.tv_usec / 2 + (tvdiff.tv_sec % 2) * 500000; /* JGH */
-
- average->tv_sec = earlier->tv_sec + tvhalf.tv_sec;
- average->tv_usec = earlier->tv_usec + tvhalf.tv_usec;
-
- /* Bring into range */
- UTI_NormaliseTimeval(average);
-
- }
+ UTI_DiffTimespecsToDouble(diff, later, earlier);
+ UTI_AddDoubleToTimespec(earlier, *diff / 2.0, average);
+}
/* ================================================== */
void
-UTI_AddDiffToTimeval(struct timeval *a, struct timeval *b,
- struct timeval *c, struct timeval *result)
+UTI_AddDiffToTimespec(struct timespec *a, struct timespec *b,
+ struct timespec *c, struct timespec *result)
{
double diff;
- UTI_DiffTimevalsToDouble(&diff, a, b);
- UTI_AddDoubleToTimeval(c, diff, result);
+ UTI_DiffTimespecsToDouble(&diff, a, b);
+ UTI_AddDoubleToTimespec(c, diff, result);
}
/* ================================================== */
#define NEXT_BUFFER (buffer_pool[pool_ptr = ((pool_ptr + 1) % POOL_ENTRIES)])
/* ================================================== */
-/* Convert a timeval into a temporary string, largely for diagnostic
- display */
+/* Convert a timespec into a temporary string, largely for diagnostic display */
char *
-UTI_TimevalToString(struct timeval *tv)
+UTI_TimespecToString(struct timespec *ts)
{
char *result;
result = NEXT_BUFFER;
#ifdef HAVE_LONG_TIME_T
- snprintf(result, BUFFER_LENGTH, "%"PRId64".%06lu",
- (int64_t)tv->tv_sec, (unsigned long)tv->tv_usec);
+ snprintf(result, BUFFER_LENGTH, "%"PRId64".%09lu",
+ (int64_t)ts->tv_sec, (unsigned long)ts->tv_nsec);
#else
- snprintf(result, BUFFER_LENGTH, "%ld.%06lu",
- (long)tv->tv_sec, (unsigned long)tv->tv_usec);
+ snprintf(result, BUFFER_LENGTH, "%ld.%09lu",
+ (long)ts->tv_sec, (unsigned long)ts->tv_nsec);
#endif
return result;
}
for diagnostic display */
char *
-UTI_TimestampToString(NTP_int64 *ts)
+UTI_TimestampToString(NTP_int64 *ntp_ts)
{
- struct timeval tv;
- UTI_Int64ToTimeval(ts, &tv);
- return UTI_TimevalToString(&tv);
+ struct timespec ts;
+ UTI_Int64ToTimespec(ntp_ts, &ts);
+ return UTI_TimespecToString(&ts);
}
/* ================================================== */
/* ================================================== */
void
-UTI_AdjustTimeval(struct timeval *old_tv, struct timeval *when, struct timeval *new_tv, double *delta_time, double dfreq, double doffset)
+UTI_AdjustTimespec(struct timespec *old_ts, struct timespec *when, struct timespec *new_ts, double *delta_time, double dfreq, double doffset)
{
double elapsed;
- UTI_DiffTimevalsToDouble(&elapsed, when, old_tv);
+ UTI_DiffTimespecsToDouble(&elapsed, when, old_ts);
*delta_time = elapsed * dfreq - doffset;
- UTI_AddDoubleToTimeval(old_tv, *delta_time, new_tv);
+ UTI_AddDoubleToTimespec(old_ts, *delta_time, new_ts);
}
/* ================================================== */
/* ================================================== */
-/* Seconds part of NTP timestamp correponding to the origin of the
- struct timeval format. */
+/* Seconds part of NTP timestamp correponding to the origin of the time_t format */
#define JAN_1970 0x83aa7e80UL
+#define NSEC_PER_NTP64 4.294967296
+
void
-UTI_TimevalToInt64(struct timeval *src,
- NTP_int64 *dest, NTP_int64 *fuzz)
+UTI_TimespecToInt64(struct timespec *src, NTP_int64 *dest, NTP_int64 *fuzz)
{
- uint32_t hi, lo, sec, usec;
+ uint32_t hi, lo, sec, nsec;
sec = (uint32_t)src->tv_sec;
- usec = (uint32_t)src->tv_usec;
+ nsec = (uint32_t)src->tv_nsec;
/* Recognize zero as a special case - it always signifies
an 'unknown' value */
- if (!usec && !sec) {
+ if (!nsec && !sec) {
hi = lo = 0;
} else {
hi = htonl(sec + JAN_1970);
-
- /* This formula gives an error of about 0.1us worst case */
- lo = htonl(4295 * usec - (usec >> 5) - (usec >> 9));
+ lo = htonl(NSEC_PER_NTP64 * nsec);
/* Add the fuzz */
if (fuzz) {
/* ================================================== */
void
-UTI_Int64ToTimeval(NTP_int64 *src,
- struct timeval *dest)
+UTI_Int64ToTimespec(NTP_int64 *src, struct timespec *dest)
{
uint32_t ntp_sec, ntp_frac;
#else
dest->tv_sec = ntp_sec - JAN_1970;
#endif
-
- /* Until I invent a slick way to do this, just do it the obvious way */
- dest->tv_usec = (int)(0.5 + (double)(ntp_frac) / 4294.967296);
- UTI_NormaliseTimeval(dest);
+ dest->tv_nsec = ntp_frac / NSEC_PER_NTP64 + 0.5;
+
+ UTI_NormaliseTimespec(dest);
}
/* ================================================== */
#define MIN_ENDOFTIME_DISTANCE (365 * 24 * 3600)
int
-UTI_IsTimeOffsetSane(struct timeval *tv, double offset)
+UTI_IsTimeOffsetSane(struct timespec *ts, double offset)
{
double t;
if (!(offset > -MAX_OFFSET && offset < MAX_OFFSET))
return 0;
- UTI_TimevalToDouble(tv, &t);
+ UTI_TimespecToDouble(ts, &t);
t += offset;
/* Time before 1970 is not considered valid */
/* ================================================== */
void
-UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest)
+UTI_TimespecNetworkToHost(Timespec *src, struct timespec *dest)
{
uint32_t sec_low;
#ifdef HAVE_LONG_TIME_T
uint32_t sec_high;
#endif
- dest->tv_usec = ntohl(src->tv_nsec) / 1000;
+ dest->tv_nsec = ntohl(src->tv_nsec);
sec_low = ntohl(src->tv_sec_low);
#ifdef HAVE_LONG_TIME_T
sec_high = ntohl(src->tv_sec_high);
dest->tv_sec = sec_low;
#endif
- UTI_NormaliseTimeval(dest);
+ UTI_NormaliseTimespec(dest);
}
/* ================================================== */
void
-UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest)
+UTI_TimespecHostToNetwork(struct timespec *src, Timespec *dest)
{
- dest->tv_nsec = htonl(src->tv_usec * 1000);
+ dest->tv_nsec = htonl(src->tv_nsec);
#ifdef HAVE_LONG_TIME_T
dest->tv_sec_high = htonl((uint64_t)src->tv_sec >> 32);
#else
#include "candm.h"
#include "hash.h"
+/* Zero a timespec */
+extern void UTI_ZeroTimespec(struct timespec *ts);
+
+/* Convert a timeval into a timespec */
+extern void UTI_TimevalToTimespec(struct timeval *tv, struct timespec *ts);
+
+/* Convert a timespec into a timeval */
+extern void UTI_TimespecToTimeval(struct timespec *ts, struct timeval *tv);
+
+/* Convert a timespec into a floating point number of seconds */
+extern void UTI_TimespecToDouble(struct timespec *ts, double *d);
+
+/* Convert a number of seconds expressed in floating point into a
+ timespec */
+extern void UTI_DoubleToTimespec(double d, struct timespec *ts);
+
+/* Normalise a timespec, by adding or subtracting seconds to bring
+ its nanosecond field into range */
+extern void UTI_NormaliseTimespec(struct timespec *ts);
+
/* Convert a timeval into a floating point number of seconds */
extern void UTI_TimevalToDouble(struct timeval *a, double *b);
timeval */
extern void UTI_DoubleToTimeval(double a, struct timeval *b);
-/* Returns -1 if a comes earlier than b, 0 if a is the same time as b,
- and +1 if a comes after b */
-extern int UTI_CompareTimevals(struct timeval *a, struct timeval *b);
-
/* Normalise a struct timeval, by adding or subtracting seconds to bring
its microseconds field into range */
extern void UTI_NormaliseTimeval(struct timeval *x);
+/* Returns -1 if a comes earlier than b, 0 if a is the same time as b,
+ and +1 if a comes after b */
+extern int UTI_CompareTimespecs(struct timespec *a, struct timespec *b);
+
/* Calculate result = a - b */
-extern void UTI_DiffTimevals(struct timeval *result, struct timeval *a, struct timeval *b);
+extern void UTI_DiffTimespecs(struct timespec *result, struct timespec *a, struct timespec *b);
/* Calculate result = a - b and return as a double */
-extern void UTI_DiffTimevalsToDouble(double *result, struct timeval *a, struct timeval *b);
+extern void UTI_DiffTimespecsToDouble(double *result, struct timespec *a, struct timespec *b);
-/* Add a double increment to a timeval to get a new one. 'start' is
+/* Add a double increment to a timespec to get a new one. 'start' is
the starting time, 'end' is the result that we return. This is
safe to use if start and end are the same */
-extern void UTI_AddDoubleToTimeval(struct timeval *start, double increment, struct timeval *end);
+extern void UTI_AddDoubleToTimespec(struct timespec *start, double increment, struct timespec *end);
-/* Calculate the average and difference (as a double) of two timevals */
-extern void UTI_AverageDiffTimevals(struct timeval *earlier, struct timeval *later, struct timeval *average, double *diff);
+/* Calculate the average and difference (as a double) of two timespecs */
+extern void UTI_AverageDiffTimespecs(struct timespec *earlier, struct timespec *later, struct timespec *average, double *diff);
/* Calculate result = a - b + c */
-extern void UTI_AddDiffToTimeval(struct timeval *a, struct timeval *b, struct timeval *c, struct timeval *result);
+extern void UTI_AddDiffToTimespec(struct timespec *a, struct timespec *b, struct timespec *c, struct timespec *result);
-/* Convert a timeval into a temporary string, largely for diagnostic
+/* Convert a timespec into a temporary string, largely for diagnostic
display */
-extern char *UTI_TimevalToString(struct timeval *tv);
+extern char *UTI_TimespecToString(struct timespec *ts);
/* Convert an NTP timestamp into a temporary string, largely for
diagnostic display */
extern char *UTI_TimeToLogForm(time_t t);
/* Adjust time following a frequency/offset change */
-extern void UTI_AdjustTimeval(struct timeval *old_tv, struct timeval *when, struct timeval *new_tv, double *delta, double dfreq, double doffset);
+extern void UTI_AdjustTimespec(struct timespec *old_ts, struct timespec *when, struct timespec *new_ts, double *delta_time, double dfreq, double doffset);
/* Get zero NTP timestamp with random bits below precision */
extern void UTI_GetInt64Fuzz(NTP_int64 *ts, int precision);
extern double UTI_Int32ToDouble(NTP_int32 x);
extern NTP_int32 UTI_DoubleToInt32(double x);
-extern void UTI_TimevalToInt64(struct timeval *src, NTP_int64 *dest, NTP_int64 *fuzz);
+extern void UTI_TimespecToInt64(struct timespec *src, NTP_int64 *dest, NTP_int64 *fuzz);
-extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);
+extern void UTI_Int64ToTimespec(NTP_int64 *src, struct timespec *dest);
/* Check if time + offset is sane */
-extern int UTI_IsTimeOffsetSane(struct timeval *tv, double offset);
+extern int UTI_IsTimeOffsetSane(struct timespec *ts, double offset);
/* Get 2 raised to power of a signed integer */
extern double UTI_Log2ToDouble(int l);
-extern void UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest);
-extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);
+extern void UTI_TimespecNetworkToHost(Timespec *src, struct timespec *dest);
+extern void UTI_TimespecHostToNetwork(struct timespec *src, Timespec *dest);
extern double UTI_FloatNetworkToHost(Float x);
extern Float UTI_FloatHostToNetwork(double x);