Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 28 Mar 2010 08:46:34 +1100
From:      Peter Jeremy <peterjeremy@acm.org>
To:        Dag-Erling =?iso-8859-1?Q?Sm=F8rgrav?= <des@des.no>
Cc:        freebsd-hackers@FreeBSD.org, Andriy Gapon <avg@icyb.net.ua>
Subject:   Re: periodically save current time to time-of-day hardware
Message-ID:  <20100327214634.GI32799@server.vk2pj.dyndns.org>
In-Reply-To: <86pr2qlhtf.fsf@ds4.des.no>
References:  <4BACC791.70502@icyb.net.ua> <86zl1v84vy.fsf@ds4.des.no> <4BACD88E.2040803@icyb.net.ua> <86vdcj82qx.fsf@ds4.des.no> <20100326213022.GD32799@server.vk2pj.dyndns.org> <86pr2qlhtf.fsf@ds4.des.no>

next in thread | previous in thread | raw e-mail | index | archive | help

--ZY5CS28jBCfb727c
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On 2010-Mar-27 01:38:36 +0100, Dag-Erling Sm=F8rgrav <des@des.no> wrote:
>Peter Jeremy <peterjeremy@acm.org> writes:
>> It's not especially important how regularly the RTC is updated, just
>> that it _is_ updated.  This suggests that an alternative approach
>> would be for adjtime() / ntp_adjtime() to directly call resettodr() if
>> it's more than P minutes since resettodr() was last called.
>
>It just occurred to me that resettodr() is very slow (it usually
>involves writing to NVRAM over an I2C bus), so it might not be a good
>idea to call it from adjtime().

Traditionally, the (PC) RTC is on the ISA bus (though it's possible it
might use I2C on other architectures or LPC on current PCs).  I thought
about speed but only in terms of simulated ISA accesses and didn't
think that adjtime() / ntp_adjtime() were especially time critical
(resettodr() should occur after they have updated the kernel TOD
parameters).  The alternative would be a kthread to update the RTC and
I didn't think that was worth it.

Note that resettodr() is currently called with Giant held so if it _is_
excesssively slow, it might be worthwhile reviewing the existing code
in kern_time.c::settime() and subr_clock.c::sysctl_machdep_adjkerntz().

>> As a general comment, whilst resettodr() needs to be serialised, there
>> is no need for it to block.  If thread B wants to call resettodr()
>> whilst thread A is doing so, thread B can just skip the call because
>> calling resettodr() twice in quick succession has no benefit.
>
>It does if thread B set the system clock before calling resettodr()
>(think ntpd -gq).

Yes - I hadn't considered resettodr() taking a non-trivial time to
execute.  This could allow the scenario: Thread A grabs the RTC update
lock and begin updating the RTC and, whilst it's doing so, thread B
updates the system clock and then calls resettodr() - which turns
into a no-op because the update lock is held.

>  Actually, it might be a good idea to call resettodr()
>any time the clock is stepped.

This should occur now via kern_time.c::settime().

Given that:
- resettodr() needs to be serialised;
- resettodr() may take a significant amount of time; and
- resettodr() should ideally be synchronised to the second boundary;
maybe creating a kthread to manage the RTC updating is reasonable.

A rough outline of my idea would be:

A new kthread which sleeps on channel "update_rtc".  When woken, it
checks to see if it's within (say) 50msec of a second boundary and so,
it does a trylock on the (new) RTC mutex.  If it grabs the mutex then
it performs the update.  If it was too far from the second boundary or
it fails to grab the mutex then it sleeps until the next second
boundary and tries again.

The existing resettodr() would then turn into a wakeup(update_rtc).

Or is this overkill?
--=20
Peter Jeremy

--ZY5CS28jBCfb727c
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (FreeBSD)

iEYEARECAAYFAkuufLoACgkQ/opHv/APuIeSmgCaApSP1xoxTFh+zUi02AcG0X/S
I2cAn27crdOwqShdrSHiQyhRO5BbxqIb
=J3KG
-----END PGP SIGNATURE-----

--ZY5CS28jBCfb727c--



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