Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 31 Mar 1998 12:36:17 +0200 (MET DST)
From:      Wolfgang Helbig <helbig@Informatik.BA-Stuttgart.DE>
To:        ache@nagual.pp.ru (=?koi8-r?B?4c7E0sXKIP7F0s7P1w==?=)
Cc:        helbig@Informatik.BA-Stuttgart.DE, freebsd-bugs@FreeBSD.ORG
Subject:   Re: bin/6164
Message-ID:  <199803311036.MAA09745@rvc1.informatik.ba-stuttgart.de>
In-Reply-To: <19980330161329.17370@nagual.pp.ru> from "[______ ______]" at "Mar 30, 98 04:13:29 pm"

next in thread | previous in thread | raw e-mail | index | archive | help
> On Mon, Mar 30, 1998 at 01:02:27PM +0200, Wolfgang Helbig wrote:
> > A fix is to use local.tm_gmtoff to get UTC-time from local time, as in
> > this diff:
> 
> I doubt we can trust tm_gmtoff since it changes over timezone
> switch time. mktime used just to get correct (changed) tm_gmtoff

Hmm. I do trust tm_gmtoff. Maybe it used to be broken long ago, but
in -current and -stable it works quite well--as opposed to the mktime()
method.

Here is an outline of how to exploit tm_gmtoff for adjkerntz:
Let  k  denote the kernel time,  l  the local time and
u(t) an abbreviation for localtime(t)->tm_gmtoff.
Our task is to change  k  or  l  in order to satisfy this equation:
(*)	k + u(k) == l

- adjkerntz -a: This is quite easy: You can assume k is UTC-time,
  and  l  is to be computed like: 
	l = k + u(k)
  So all you have to do is to set the RTC to the new value of l.
  This is done indirectly by setting machdep.adjkerntz to the value of
  u(k).
  You must not change k.

- adjkerntz -i, boot time: This is a little complicated if the RTC is set
  to local time. All you know is local time and you need to compute
  k to satisfy (*):
	k = time(NULL);
	l = k;		/* RTC is set to local time, so the kernel time
			 * is the local time.
			 */

	/* Iterate to make (*) hold, i. e. to find k */
	k0 = l - u(l);			/* first approximation */
	k1 = l - u(k0);
	if (k0 == k1)			/* found the correct value */
		k = k0;
	else {
		k2 = l - u(k1);
		if (k2 == k1)
			k = k1;
		else			/* iteration won't converge ! */
			k = (time_t) - 1;
	}

   Now either (*) holds or k == (time_t) - 1, which means that the
   local time  l  does not exist. This happens *iff* the RTC is
   set to a nonexisting local time during switch from standard time
   to daylight saving time.
   If the local time is ambiguous, we will find one value of k. This
   might be the right one or the wrong one. But we cannot tell--
   we just don't have enough information.
   This only happens if the system is booted during the switch from
   daylight saving time to standard time.

- adjkerntz -i, termination time: Exactly the same as adjkerntz -a.

Setting the kernel time (adjkerntz -i) must be done only 
once. You can use machdep.wall_cmos_clock to determine if the
kernel time is already adjusted.

This solution does not need the sleeping mode, i. e. makes -s obsolete.

During boottime (adjkerntz -i) you should sleep one minute if
k % 60 == 59 to avoid a switch of u(k) before the kernel time is set.

If you trust this method, I'll be glad to rewrite adjkerntz().

Wolfgang

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199803311036.MAA09745>