I would like to sync the system time periodically back to the RTC.

Currently we update the RTC
(1) when the time is set with clock_settime() or settimeofday(), which
    never happens for a typical ntpd setup;
(2) before suspend;
(3) when the system is properly shut down.

This means if a machine has been running for a few months and it
loses power, it may come back up with the time way off, leading to
all sorts of problems.

Patch below, originally inspired by FreeBSD, and incorporating various
suggestions from kettenis@ when I first proposed this:

* A timeout schedules a task that actually calls resettodr().
* The RTC is synced back every 30 minutes.
* The timeout and task are removed before shutdown and suspend;
  the timeout is started up again on resume.
* Suspend/resume paths: acpi, i386 apm, loongson "apm".

Comments?

Index: arch/i386/i386/apm.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/apm.c,v
retrieving revision 1.114
diff -u -p -r1.114 apm.c
--- arch/i386/i386/apm.c        28 Sep 2015 18:36:36 -0000      1.114
+++ arch/i386/i386/apm.c        2 Sep 2016 17:28:23 -0000
@@ -248,6 +248,7 @@ apm_suspend(int state)
 #if NWSDISPLAY > 0
        wsdisplay_suspend();
 #endif /* NWSDISPLAY > 0 */
+       stop_periodic_resettodr();
        config_suspend_all(DVACT_QUIESCE);
        bufq_quiesce();
 
@@ -284,6 +285,7 @@ apm_suspend(int state)
        bufq_restart();
 
        config_suspend_all(DVACT_WAKEUP);
+       start_periodic_resettodr();
 
 #if NWSDISPLAY > 0
        wsdisplay_resume();
Index: arch/loongson/dev/apm.c
===================================================================
RCS file: /cvs/src/sys/arch/loongson/dev/apm.c,v
retrieving revision 1.29
diff -u -p -r1.29 apm.c
--- arch/loongson/dev/apm.c     28 Sep 2015 18:36:36 -0000      1.29
+++ arch/loongson/dev/apm.c     2 Sep 2016 17:28:23 -0000
@@ -373,6 +373,7 @@ apm_suspend(int state)
        wsdisplay_suspend();
 #endif
 
+       stop_periodic_resettodr();
        resettodr();
 
        config_suspend_all(DVACT_QUIESCE);
@@ -422,6 +423,8 @@ apm_suspend(int state)
        bufq_restart();
 
        config_suspend_all(DVACT_WAKEUP);
+
+       start_periodic_resettodr();
 
 #if NWSDISPLAY > 0
        wsdisplay_resume();
Index: dev/acpi/acpi.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpi.c,v
retrieving revision 1.314
diff -u -p -r1.314 acpi.c
--- dev/acpi/acpi.c     31 Aug 2016 15:40:42 -0000      1.314
+++ dev/acpi/acpi.c     2 Sep 2016 17:28:23 -0000
@@ -2383,6 +2383,8 @@ acpi_sleep_state(struct acpi_softc *sc, 
        rw_enter_write(&sc->sc_lck);
 #endif /* NWSDISPLAY > 0 */
 
+       stop_periodic_resettodr();
+
 #ifdef HIBERNATE
        if (state == ACPI_STATE_S4) {
                uvmpd_hibernate();
@@ -2482,6 +2484,8 @@ fail_alloc:
                hibernate_resume_bufcache();
        }
 #endif /* HIBERNATE */
+
+       start_periodic_resettodr();
 
 #if NWSDISPLAY > 0
        rw_exit_write(&sc->sc_lck);
Index: kern/init_main.c
===================================================================
RCS file: /cvs/src/sys/kern/init_main.c,v
retrieving revision 1.254
diff -u -p -r1.254 init_main.c
--- kern/init_main.c    2 Sep 2016 12:17:33 -0000       1.254
+++ kern/init_main.c    2 Sep 2016 17:28:23 -0000
@@ -551,6 +551,8 @@ main(void *framep)
        pool_gc_pages(NULL);
 #endif
 
+       start_periodic_resettodr();
+
         /*
          * proc0: nothing to do, back to sleep
          */
Index: kern/kern_time.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_time.c,v
retrieving revision 1.97
diff -u -p -r1.97 kern_time.c
--- kern/kern_time.c    28 Apr 2016 20:11:20 -0000      1.97
+++ kern/kern_time.c    2 Sep 2016 17:28:24 -0000
@@ -41,6 +41,8 @@
 #include <sys/vnode.h>
 #include <sys/signalvar.h>
 #include <sys/pledge.h>
+#include <sys/task.h>
+#include <sys/timeout.h>
 #include <sys/timetc.h>
 
 #include <sys/mount.h>
@@ -785,3 +787,37 @@ ppsratecheck(struct timeval *lasttime, i
        return (rv);
 }
 
+
+#define RESETTODR_PERIOD       1800
+
+void periodic_resettodr(void *);
+void perform_resettodr(void *);
+
+struct timeout resettodr_to = TIMEOUT_INITIALIZER(periodic_resettodr, NULL);
+struct task resettodr_task = TASK_INITIALIZER(perform_resettodr, NULL);
+
+void
+periodic_resettodr(void *arg __unused)
+{
+       task_add(systq, &resettodr_task);
+}
+
+void
+perform_resettodr(void *arg __unused)
+{
+       resettodr();
+       timeout_add_sec(&resettodr_to, RESETTODR_PERIOD);
+}
+
+void
+start_periodic_resettodr(void)
+{
+       timeout_add_sec(&resettodr_to, RESETTODR_PERIOD);
+}
+
+void
+stop_periodic_resettodr(void)
+{
+       timeout_del(&resettodr_to);
+       task_del(systq, &resettodr_task);
+}
Index: kern/kern_xxx.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_xxx.c,v
retrieving revision 1.29
diff -u -p -r1.29 kern_xxx.c
--- kern/kern_xxx.c     5 Dec 2015 10:11:53 -0000       1.29
+++ kern/kern_xxx.c     2 Sep 2016 17:28:24 -0000
@@ -65,6 +65,8 @@ reboot(int howto)
 {
        KASSERT((howto & RB_NOSYNC) || curproc != NULL);
 
+       stop_periodic_resettodr();
+
        boot(howto);
        /* NOTREACHED */
 }
Index: sys/systm.h
===================================================================
RCS file: /cvs/src/sys/sys/systm.h,v
retrieving revision 1.114
diff -u -p -r1.114 systm.h
--- sys/systm.h 1 Sep 2016 12:50:53 -0000       1.114
+++ sys/systm.h 2 Sep 2016 17:28:24 -0000
@@ -232,6 +232,9 @@ void        startprofclock(struct process *);
 void   stopprofclock(struct process *);
 void   setstatclockrate(int);
 
+void   start_periodic_resettodr(void);
+void   stop_periodic_resettodr(void);
+
 struct sleep_state;
 void   sleep_setup(struct sleep_state *, const volatile void *, int,
            const char *);
-- 
Christian "naddy" Weisgerber                          na...@mips.inka.de

Reply via email to