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