(patch) Re: pmtimer and nanouptime
YONETANI Tomokazu
qhwt+dfly at les.ath.cx
Mon Sep 27 07:55:07 PDT 2004
On Tue, Jul 20, 2004 at 12:07:06PM -0700, Matthew Dillon wrote:
> Please try this patch.
>
> -Matt
>
> Index: i386/isa/clock.c
> ===================================================================
> RCS file: /cvs/src/sys/i386/isa/clock.c,v
> retrieving revision 1.15
> diff -u -r1.15 clock.c
> --- i386/isa/clock.c 20 Jul 2004 04:12:08 -0000 1.15
> +++ i386/isa/clock.c 20 Jul 2004 19:02:13 -0000
> @@ -596,17 +596,21 @@
> }
>
> /*
> - * Restore all the timers non-atomically (XXX: should be atomically).
> + * Restore all the timers.
> *
> - * This function is called from apm_default_resume() to restore all the timers.
> - * This should not be necessary, but there are broken laptops that do not
> - * restore all the timers on resume.
> + * This function is called from apm_default_resume() / pmtimer to restore
> + * all the timers. We also have to restore our timebases, especially on
> + * MP systems, because cputimer_count() counter's delta may have grown
> + * too large for nanouptime() and friends to handle.
> */
> void
> timer_restore(void)
> {
> + crit_enter();
> i8254_restore(); /* restore timer_freq and hz */
> rtc_restore(); /* reenable RTC interrupts */
> + restoreclocks();
> + crit_exit();
> }
>
> /*
> Index: kern/kern_clock.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/kern_clock.c,v
> retrieving revision 1.21
> diff -u -r1.21 kern_clock.c
> --- kern/kern_clock.c 16 Jul 2004 05:51:09 -0000 1.21
> +++ kern/kern_clock.c 20 Jul 2004 19:05:49 -0000
> @@ -196,6 +196,36 @@
> }
>
> /*
> + * Resynchronize gd_cpuclock_base after the system has been woken up from
> + * a sleep. It is absolutely essential that all the cpus be properly
> + * synchronized. Resynching is required because nanouptime() and friends
> + * will overflow intermediate multiplications if more then 2 seconds
> + * worth of cputimer_cont() delta has built up.
> + */
> +#ifdef SMP
> +
> +static
> +void
> +restoreclocks_remote(lwkt_cpusync_t poll)
> +{
> + mycpu->gd_cpuclock_base = *(sysclock_t *)poll->cs_data;
> + mycpu->gd_time_seconds = globaldata_find(0)->gd_time_seconds;
> +}
> +
> +#endif
> +
> +void
> +restoreclocks(void)
> +{
> + sysclock_t base = cputimer_count();
> +#ifdef SMP
> + lwkt_cpusync_simple(-1, restoreclocks_remote, &base);
> +#else
> + mycpu->gd_cpuclock_base = base;
> +#endif
> +}
> +
> +/*
> * This sets the current real time of day. Timespecs are in seconds and
> * nanoseconds. We do not mess with gd_time_seconds and gd_cpuclock_base,
> * instead we adjust basetime so basetime + gd_* results in the current
> Index: sys/time.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/time.h,v
> retrieving revision 1.8
> diff -u -r1.8 time.h
> --- sys/time.h 30 Jan 2004 05:42:18 -0000 1.8
> +++ sys/time.h 20 Jul 2004 19:02:43 -0000
> @@ -192,6 +192,7 @@
> extern time_t time_second;
>
> void initclocks_pcpu(void);
> +void restoreclocks(void);
> void getmicrouptime (struct timeval *tv);
> void getmicrotime (struct timeval *tv);
> void getnanouptime (struct timespec *tv);
Can you please back out this change? This was supposed to fix my
nanouptime() problem, but unfortunately resulted in system clock to
always skew one hour ahead in a short period of time after resuming
from ACPI S3 state. I'm using a kernel with this change backed out,
but somehow nanouptime() no longer returns strange tv_nsec after
resume.
More information about the Bugs
mailing list