Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ntp / sntp / timing.c
blob14397b36ac6a0a79b5d87d041acd3bb4764a0444
1 /* $NetBSD: timing.c,v 1.3 2006/05/10 21:53:14 mrg Exp $ */
3 /* Copyright (C) 1996 N.M. Maclaren
4 Copyright (C) 1996 The University of Cambridge
6 This includes all of the code needed to handle the time. It assumes rather
7 more than is defined by POSIX, unfortunately. Systems that do not have the
8 'X/Open' extensions may need changes. */
12 #include "header.h"
14 #include <sys/types.h>
15 #include <sys/time.h>
17 #define TIMING
18 #include "kludges.h"
19 #undef TIMING
23 #define MILLION_L 1000000l /* For conversion to/from timeval */
24 #define MILLION_D 1.0e6 /* Must be equal to MILLION_L */
28 double current_time (double offset) {
30 /* Get the current UTC time in seconds since the Epoch plus an offset (usually
31 the time from the beginning of the century to the Epoch!) */
33 struct timeval current;
35 errno = 0;
36 if (gettimeofday(&current,NULL))
37 fatal(1,"unable to read current machine/system time",NULL);
38 return offset+current.tv_sec+1.0e-6*current.tv_usec;
43 time_t convert_time (double value, int *millisecs) {
45 /* Convert the time to the ANSI C form. */
47 time_t result = (time_t)value;
49 if ((*millisecs = (int)(1000.0*(value-result))) >= 1000) {
50 *millisecs = 0;
51 ++result;
53 return result;
58 void adjust_time (double difference, int immediate, double ignore) {
60 /* Adjust the current UTC time. This is portable, even if struct timeval uses
61 an unsigned long for tv_sec. */
63 struct timeval old, new, adjust, previous;
64 char text[40];
65 long n;
67 /* Start by converting to timeval format. Note that we have to cater for
68 negative, unsigned values. */
70 previous.tv_sec = 0; /* XXX gcc */
71 previous.tv_usec = 0; /* XXX gcc */
73 if ((n = (long)difference) > difference) --n;
74 adjust.tv_sec = n;
75 adjust.tv_usec = (long)(MILLION_D*(difference-n));
76 errno = 0;
77 if (gettimeofday(&old,NULL))
78 fatal(1,"unable to read machine/system time",NULL);
79 new.tv_sec = old.tv_sec+adjust.tv_sec;
80 new.tv_usec = (n = (long)old.tv_usec+(long)adjust.tv_usec);
81 if (n < 0) {
82 new.tv_usec += MILLION_L;
83 --new.tv_sec;
84 } else if (n >= MILLION_L) {
85 new.tv_usec -= MILLION_L;
86 ++new.tv_sec;
89 /* Now diagnose the situation if necessary, and perform the dirty deed. */
91 if (verbose > 2)
92 fprintf(stderr,
93 "Times: old=(%ld,%.6ld) new=(%ld,%.6ld) adjust=(%ld,%.6ld)\n",
94 (long)old.tv_sec,(long)old.tv_usec,
95 (long)new.tv_sec,(long)new.tv_usec,
96 (long)adjust.tv_sec,(long)adjust.tv_usec);
97 if (immediate) {
98 errno = 0;
99 if (settimeofday(&new,NULL))
100 fatal(1,"unable to reset current system time",NULL);
101 } else {
102 previous.tv_sec = 0;
103 previous.tv_usec = 0;
104 errno = 0;
105 if (adjtime(&adjust,&previous))
106 fatal(1,"unable to adjust current system time",NULL);
107 if (previous.tv_sec != 0 || previous.tv_usec != 0) {
108 sprintf(text,"(%ld,%.6ld)",
109 (long)previous.tv_sec,(long)previous.tv_usec);
110 if (previous.tv_sec+1.0e-6*previous.tv_usec > ignore)
111 fatal(0,"outstanding time adjustment %s",text);
112 else if (verbose)
113 fprintf(stderr,"%s: outstanding time adjustment %s\n",
114 argv0,text);