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>