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 [email protected]