> Date: Fri, 2 Sep 2016 19:45:39 +0200
> From: Christian Weisgerber <[email protected]>
>
> 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?
looks good to me
> 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 [email protected]
>
>