(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