Author: avg
Date: Thu Apr 29 09:02:46 2010
New Revision: 207360
URL: http://svn.freebsd.org/changeset/base/207360

Log:
  periodically save system time to hardware time-of-day clock
  
  This is done in kern_ntptime, perhaps not the best place.
  This is done using resettodr().
  Some features:
  - make save period configurable via tunable and sysctl
  - period of zero disables saving, setting a non-zero period re-enables
    it or reschedules it
  - do saving only if system clock is ntp-synchronized
  - save on shutdown
  
  Discussed with:       des, Peter Jeremy <peterjer...@acm.org>
  X-Maybe:              save time near seconds boundary for better precision
  MFC after:            2 weeks

Modified:
  head/sys/kern/kern_ntptime.c

Modified: head/sys/kern/kern_ntptime.c
==============================================================================
--- head/sys/kern/kern_ntptime.c        Thu Apr 29 09:02:21 2010        
(r207359)
+++ head/sys/kern/kern_ntptime.c        Thu Apr 29 09:02:46 2010        
(r207360)
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/sysproto.h>
+#include <sys/eventhandler.h>
 #include <sys/kernel.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
@@ -976,3 +977,67 @@ kern_adjtime(struct thread *td, struct t
        return (0);
 }
 
+static struct callout resettodr_callout;
+static int resettodr_period = 1800;
+
+static void
+periodic_resettodr(void *arg __unused)
+{
+
+       if (!ntp_is_time_error()) {
+               mtx_lock(&Giant);
+               resettodr();
+               mtx_unlock(&Giant);
+       }
+       if (resettodr_period > 0)
+               callout_schedule(&resettodr_callout, resettodr_period * hz);
+}
+
+static void
+shutdown_resettodr(void *arg __unused, int howto __unused)
+{
+
+       callout_drain(&resettodr_callout);
+       if (resettodr_period > 0 && !ntp_is_time_error()) {
+               mtx_lock(&Giant);
+               resettodr();
+               mtx_unlock(&Giant);
+       }
+}
+
+static int
+sysctl_resettodr_period(SYSCTL_HANDLER_ARGS)
+{
+       int error;
+
+       error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
+       if (error || !req->newptr)
+               return (error);
+       if (resettodr_period == 0)
+               callout_stop(&resettodr_callout);
+       else
+               callout_reset(&resettodr_callout, resettodr_period * hz,
+                   periodic_resettodr, NULL);
+       return (0);
+}
+
+SYSCTL_PROC(_machdep, OID_AUTO, rtc_save_period, CTLTYPE_INT|CTLFLAG_RW,
+       &resettodr_period, 1800, sysctl_resettodr_period, "I",
+       "Save system time to RTC with this period (in seconds)");
+TUNABLE_INT("machdep.rtc_save_period", &resettodr_period);
+
+static void
+start_periodic_resettodr(void *arg __unused)
+{
+
+       EVENTHANDLER_REGISTER(shutdown_pre_sync, shutdown_resettodr, NULL,
+           SHUTDOWN_PRI_FIRST);
+       callout_init(&resettodr_callout, 1);
+       if (resettodr_period == 0)
+               return;
+       callout_reset(&resettodr_callout, resettodr_period * hz,
+           periodic_resettodr, NULL);
+}
+
+SYSINIT(periodic_resettodr, SI_SUB_RUN_SCHEDULER, SI_ORDER_ANY - 1,
+       start_periodic_resettodr, NULL);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to