303 lines
12 KiB
Diff
303 lines
12 KiB
Diff
From ao112@rgfn.epcc.edu Fri Mar 19 06:27:26 1999
|
|
Received: from rgfn.epcc.edu (rgfn.epcc.edu [208.136.234.19]) by hera.cwi.nl with ESMTP
|
|
id GAA27711 for <Andries.Brouwer@cwi.nl>; Fri, 19 Mar 1999 06:27:23 +0100 (MET)
|
|
Received: (from ao112@localhost)
|
|
by rgfn.epcc.edu (8.8.8/8.8.8) id WAA16797;
|
|
Thu, 18 Mar 1999 22:27:19 -0700 (MST)
|
|
Date: Thu, 18 Mar 1999 22:27:19 -0700 (MST)
|
|
Message-Id: <199903190527.WAA16797@rgfn.epcc.edu>
|
|
From: ao112@rgfn.epcc.edu (James P. Rutledge)
|
|
To: Andries.Brouwer@cwi.nl
|
|
Subject: Re: hwclock patch for drift_factor calculation improvement
|
|
Reply-To: ao112@rgfn.epcc.edu
|
|
Status: R
|
|
|
|
|
|
|
|
>
|
|
>Could you perhaps make your patch relative to
|
|
>util-linux-2.9n (found in ftp.cwi.nl/pub/aeb/util-linux/util-linux-2.9n.tar.gz)
|
|
>?
|
|
>
|
|
>(The hwclock stuff has changed quite a bit since 2.9g.)
|
|
>
|
|
>Andries
|
|
>
|
|
|
|
Andries;
|
|
|
|
Per your request, the patch has been modified for util-linux version
|
|
2.9n, from the version for 2.9g.
|
|
|
|
The program "hwclock" (version 2.4c) could give more accurate
|
|
values for the drift factor that it places in the file "/etc/adjtime".
|
|
|
|
A patch to improve the accuracy is included.
|
|
|
|
I have incorporated some error sources which were not compensated
|
|
for into the drift factor calculation (performed when the "--set"
|
|
or the "--systohc" option is used) to make it more accurate.
|
|
In particular, the sync delay between the desired set time and the
|
|
start of the hardware clock second, and the expected drift since the
|
|
last hardware clock adjustment are now accounted for in the drift
|
|
factor calculation.
|
|
|
|
With this patch, if at any time an adjust operation is attempted and
|
|
the hardware clock is found to be not valid, then the calibration
|
|
and adjustment time is set to zero to insure that if the hardware
|
|
clock should coincidentally return to validity, a calibration is not
|
|
done with bad history data (hardware clock info bad) and an adjust is
|
|
not attempted on bad (but now passing validity test) hardware clock
|
|
data. (With this patch, a previous calibration time of zero causes
|
|
the calibration time to initialize with the current time, when the
|
|
hardware clock is set, but no change is made to the drift factor,
|
|
so in effect, an initial calibration is started over while the previous
|
|
drift factor is retained.)
|
|
|
|
Also, the behavior in the case of an initially missing "/etc/adjtime"
|
|
file or such a file produced by the predecessor "clock" program has
|
|
been slightly improved as follows:
|
|
|
|
With this patch, if the file exists but was produced by "clock"
|
|
and, thus, is given a zero calibration time, the drift factor is
|
|
not updated upon the first calibration by "hwclock", but is left alone
|
|
and is only changed by subsequent calibrations.
|
|
|
|
With this patch, if the file does not exist and, thus, is given
|
|
a zero calibration time, the drift factor is set to zero upon the
|
|
first calibration by "hwclock" and is then changed, as appropriate, by
|
|
subsequent calibrations.
|
|
|
|
Also, with this patch, an "--adjust" operation against a non-existent
|
|
"/etc/adjtime" file or one which has zero as the last adjustment
|
|
time will not change the hardware clock setting.
|
|
|
|
A context diff for a patch to the file "hwclock.c" in the directory
|
|
"util-linux-2.9n/clock" is appended.
|
|
To use the patch, "cd" to the directory "util-linux-2.9n/clock".
|
|
Run "patch < bug-report", where "bug-report" is the file name of
|
|
this mail message, to get new file "hwclock.c" which contains the proposed
|
|
new version. This patch is, of course, submitted per the GPL and the
|
|
appropriate "NO WARRANTY OF ANY KIND" and "USE AT YOUR OWN RISK"
|
|
disclaimers apply.
|
|
|
|
Note that the patch presumptuously changes the "hwclock.c" version
|
|
number from 2.4c to 2.4c1 in "hwclock.c".
|
|
|
|
Jim
|
|
|
|
------------------ Patch file follows ----------------------------
|
|
*** hwclock.c Thu Mar 18 22:04:01 1999
|
|
--- new-hwclock.c Thu Mar 18 22:03:18 1999
|
|
***************
|
|
*** 76,86 ****
|
|
|
|
#include "clock.h"
|
|
#include "../version.h"
|
|
|
|
#define MYNAME "hwclock"
|
|
! #define VERSION "2.4c"
|
|
|
|
char *progname = MYNAME;
|
|
|
|
/* The struct that holds our hardware access routines */
|
|
struct clock_ops *ur;
|
|
--- 76,86 ----
|
|
|
|
#include "clock.h"
|
|
#include "../version.h"
|
|
|
|
#define MYNAME "hwclock"
|
|
! #define VERSION "2.4c1"
|
|
|
|
char *progname = MYNAME;
|
|
|
|
/* The struct that holds our hardware access routines */
|
|
struct clock_ops *ur;
|
|
***************
|
|
*** 581,601 ****
|
|
|
|
|
|
static void
|
|
adjust_drift_factor(struct adjtime *adjtime_p,
|
|
const time_t nowtime,
|
|
! const bool hclock_valid, const time_t hclocktime ) {
|
|
/*---------------------------------------------------------------------------
|
|
Update the drift factor in <*adjtime_p> to reflect the fact that the
|
|
Hardware Clock was calibrated to <nowtime> and before that was set
|
|
to <hclocktime>.
|
|
|
|
- We assume that the user has been doing regular drift adjustments
|
|
- using the drift factor in the adjtime file, so if <nowtime> and
|
|
- <clocktime> are different, that means the adjustment factor isn't
|
|
- quite right.
|
|
-
|
|
We record in the adjtime file the time at which we last calibrated
|
|
the clock so we can compute the drift rate each time we calibrate.
|
|
|
|
EXCEPT: if <hclock_valid> is false, assume Hardware Clock was not set
|
|
before to anything meaningful and regular adjustments have not been
|
|
--- 581,598 ----
|
|
|
|
|
|
static void
|
|
adjust_drift_factor(struct adjtime *adjtime_p,
|
|
const time_t nowtime,
|
|
! const bool hclock_valid,
|
|
! const time_t hclocktime,
|
|
! const float sync_delay ) {
|
|
/*---------------------------------------------------------------------------
|
|
Update the drift factor in <*adjtime_p> to reflect the fact that the
|
|
Hardware Clock was calibrated to <nowtime> and before that was set
|
|
to <hclocktime>.
|
|
|
|
We record in the adjtime file the time at which we last calibrated
|
|
the clock so we can compute the drift rate each time we calibrate.
|
|
|
|
EXCEPT: if <hclock_valid> is false, assume Hardware Clock was not set
|
|
before to anything meaningful and regular adjustments have not been
|
|
***************
|
|
*** 604,629 ****
|
|
----------------------------------------------------------------------------*/
|
|
if (!hclock_valid) {
|
|
if (debug)
|
|
printf("Not adjusting drift factor because the Hardware Clock "
|
|
"previously contained garbage.\n");
|
|
} else if ((hclocktime - adjtime_p->last_calib_time) < 23 * 60 * 60) {
|
|
if (debug)
|
|
printf("Not adjusting drift factor because it has been less than a "
|
|
"day since the last calibration.\n");
|
|
} else {
|
|
! const float factor_adjust =
|
|
! ((float) (nowtime - hclocktime)
|
|
! / (hclocktime - adjtime_p->last_calib_time))
|
|
! * 24 * 60 * 60;
|
|
|
|
if (debug)
|
|
! printf("Clock drifted %d seconds in the past %d seconds "
|
|
"in spite of a drift factor of %f seconds/day.\n"
|
|
"Adjusting drift factor by %f seconds/day\n",
|
|
! (int) (nowtime - hclocktime),
|
|
! (int) (hclocktime - adjtime_p->last_calib_time),
|
|
adjtime_p->drift_factor,
|
|
factor_adjust );
|
|
|
|
adjtime_p->drift_factor += factor_adjust;
|
|
}
|
|
--- 601,642 ----
|
|
----------------------------------------------------------------------------*/
|
|
if (!hclock_valid) {
|
|
if (debug)
|
|
printf("Not adjusting drift factor because the Hardware Clock "
|
|
"previously contained garbage.\n");
|
|
+ } else if (adjtime_p->last_calib_time == 0) {
|
|
+ if (debug)
|
|
+ printf("Not adjusting drift factor because last calibration "
|
|
+ "time is zero,\nso history is bad and calibration startover "
|
|
+ "is necessary.\n");
|
|
} else if ((hclocktime - adjtime_p->last_calib_time) < 23 * 60 * 60) {
|
|
if (debug)
|
|
printf("Not adjusting drift factor because it has been less than a "
|
|
"day since the last calibration.\n");
|
|
} else {
|
|
! const float sec_per_day = 24.0 * 60.0 * 60.0;
|
|
! float atime_per_htime; /* adjusted time units per hardware time unit */
|
|
! float adj_days; /* days since last adjustment (in hardware clock time) */
|
|
! float cal_days; /* days since last calibration (in hardware clock time) */
|
|
! float exp_drift; /* expected drift (sec) since last adjustment */
|
|
! float unc_drift; /* uncorrected drift (sec) since last calibration */
|
|
! float factor_adjust; /* amount to add to previous drift factor */
|
|
! atime_per_htime = 1.0 + adjtime_p->drift_factor / sec_per_day;
|
|
! adj_days = (float)(hclocktime - adjtime_p->last_adj_time) / sec_per_day;
|
|
! exp_drift = adj_days * adjtime_p->drift_factor + adjtime_p->not_adjusted;
|
|
! unc_drift = (float)(nowtime - hclocktime) + sync_delay - exp_drift;
|
|
! cal_days = ((float)(adjtime_p->last_adj_time - adjtime_p->last_calib_time)
|
|
! + adjtime_p->not_adjusted) / (sec_per_day * atime_per_htime)
|
|
! + adj_days;
|
|
! factor_adjust = unc_drift / cal_days;
|
|
|
|
if (debug)
|
|
! printf("Clock drifted %.1f seconds in the past %d seconds "
|
|
"in spite of a drift factor of %f seconds/day.\n"
|
|
"Adjusting drift factor by %f seconds/day\n",
|
|
! unc_drift,
|
|
! (int) (nowtime - adjtime_p->last_calib_time),
|
|
adjtime_p->drift_factor,
|
|
factor_adjust );
|
|
|
|
adjtime_p->drift_factor += factor_adjust;
|
|
}
|
|
***************
|
|
*** 764,773 ****
|
|
--- 777,794 ----
|
|
|
|
----------------------------------------------------------------------------*/
|
|
if (!hclock_valid) {
|
|
fprintf(stderr, "The Hardware Clock does not contain a valid time, "
|
|
"so we cannot adjust it.\n");
|
|
+ adjtime_p->last_calib_time = 0; /* calibration startover is required */
|
|
+ adjtime_p->last_adj_time = 0;
|
|
+ adjtime_p->not_adjusted = 0;
|
|
+ adjtime_p->dirty = TRUE;
|
|
+ } else if (adjtime_p->last_adj_time == 0) {
|
|
+ if (debug)
|
|
+ printf("Not setting clock because last adjustment time is zero, "
|
|
+ "so history is bad.");
|
|
} else {
|
|
int adjustment;
|
|
/* Number of seconds we must insert in the Hardware Clock */
|
|
float retro;
|
|
/* Fraction of second we have to remove from clock after inserting
|
|
***************
|
|
*** 878,888 ****
|
|
time_diff(read_time, startup_time));
|
|
*retcode_p = 0;
|
|
} else if (set) {
|
|
set_hardware_clock_exact(set_time, startup_time,
|
|
universal, testing);
|
|
! adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime);
|
|
*retcode_p = 0;
|
|
} else if (adjust) {
|
|
do_adjustment(&adjtime, hclock_valid, hclocktime,
|
|
read_time, universal, testing);
|
|
*retcode_p = 0;
|
|
--- 899,910 ----
|
|
time_diff(read_time, startup_time));
|
|
*retcode_p = 0;
|
|
} else if (set) {
|
|
set_hardware_clock_exact(set_time, startup_time,
|
|
universal, testing);
|
|
! adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime,
|
|
! time_diff(read_time, startup_time));
|
|
*retcode_p = 0;
|
|
} else if (adjust) {
|
|
do_adjustment(&adjtime, hclock_valid, hclocktime,
|
|
read_time, universal, testing);
|
|
*retcode_p = 0;
|
|
***************
|
|
*** 898,908 ****
|
|
|
|
set_hardware_clock_exact((time_t) reftime.tv_sec, reftime,
|
|
universal, testing);
|
|
*retcode_p = 0;
|
|
adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid,
|
|
! hclocktime);
|
|
} else if (hctosys) {
|
|
rc = set_system_clock(hclock_valid, hclocktime, testing);
|
|
if (rc != 0) {
|
|
printf("Unable to set system clock.\n");
|
|
*retcode_p = 1;
|
|
--- 920,930 ----
|
|
|
|
set_hardware_clock_exact((time_t) reftime.tv_sec, reftime,
|
|
universal, testing);
|
|
*retcode_p = 0;
|
|
adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid,
|
|
! hclocktime, (float)(read_time.tv_usec / 1E6));
|
|
} else if (hctosys) {
|
|
rc = set_system_clock(hclock_valid, hclocktime, testing);
|
|
if (rc != 0) {
|
|
printf("Unable to set system clock.\n");
|
|
*retcode_p = 1;
|
|
|