From owner-freebsd-hackers@FreeBSD.ORG Sat Mar 27 21:46:47 2010 Return-Path: Delivered-To: freebsd-hackers@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1ACBD1065673 for ; Sat, 27 Mar 2010 21:46:47 +0000 (UTC) (envelope-from peterjeremy@acm.org) Received: from mail13.syd.optusnet.com.au (mail13.syd.optusnet.com.au [211.29.132.194]) by mx1.freebsd.org (Postfix) with ESMTP id 9BD718FC14 for ; Sat, 27 Mar 2010 21:46:46 +0000 (UTC) Received: from server.vk2pj.dyndns.org (c122-106-253-149.belrs3.nsw.optusnet.com.au [122.106.253.149]) by mail13.syd.optusnet.com.au (8.13.1/8.13.1) with ESMTP id o2RLkaO2025989 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sun, 28 Mar 2010 08:46:38 +1100 X-Bogosity: Ham, spamicity=0.000000 Received: from server.vk2pj.dyndns.org (localhost.vk2pj.dyndns.org [127.0.0.1]) by server.vk2pj.dyndns.org (8.14.3/8.14.3) with ESMTP id o2RLkZqo014609; Sun, 28 Mar 2010 08:46:35 +1100 (EST) (envelope-from peter@server.vk2pj.dyndns.org) Received: (from peter@localhost) by server.vk2pj.dyndns.org (8.14.3/8.14.3/Submit) id o2RLkYXs014608; Sun, 28 Mar 2010 08:46:34 +1100 (EST) (envelope-from peter) Date: Sun, 28 Mar 2010 08:46:34 +1100 From: Peter Jeremy To: Dag-Erling =?iso-8859-1?Q?Sm=F8rgrav?= Message-ID: <20100327214634.GI32799@server.vk2pj.dyndns.org> 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> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="ZY5CS28jBCfb727c" Content-Disposition: inline In-Reply-To: <86pr2qlhtf.fsf@ds4.des.no> X-PGP-Key: http://members.optusnet.com.au/peterjeremy/pubkey.asc User-Agent: Mutt/1.5.20 (2009-06-14) X-CMAE-Score: 0 Cc: freebsd-hackers@FreeBSD.org, Andriy Gapon Subject: Re: periodically save current time to time-of-day hardware X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 27 Mar 2010 21:46:47 -0000 --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 wrote: >Peter Jeremy 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--