DragonFly BSD
DragonFly bugs List (threaded) for 2004-07
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

Re: pmtimer and nanouptime

From: Matthew Dillon <dillon@xxxxxxxxxxxxxxxxxxxx>
Date: Tue, 20 Jul 2004 11:44:37 -0700 (PDT)

:On my PC, getnanotime() starts to return non-normalized value
:(tv_nsec not between 0 and 999999999) after resuming from S3 state.
:This breaks programs relying on the timespec value returned by
:clock_gettime() to be normalized, and libc_r is one of them.
:After inserting printf() in several places, I found the following things:
:- nanouptime() returns non-normalized value when it's called from
:  set_timeofday() called from pmtimer_resume(), because of overflow
:  in multiplication. The following is modified version of nanouptime()
:  I'm using to print out each value used in multiplication.
:	  do {
:		  tsp->tv_sec = gd->gd_time_seconds;
:		  count = cputimer_count();
:		  base = gd->gd_cpuclock_base;
:		  delta = count - base;
:	  } while (tsp->tv_sec != gd->gd_time_seconds);
:	  nsec = (cputimer_freq64_nsec * delta) >> 32;

    What it comes down to is that the calculated delta from the 8254
    cannot safely exceed approximately 2 seconds.  This is not usually
    a problem, because gd_cpuclock_base is updated in hardclock() once
    a second.

    However, when you go into sleep the hardclock is turned off.

    set_timeofday() uses nanouptime() in order to set the basetime 
    offset.  In DragonFly the 'uptime' is the basis for the time in
    the system and a base offset is added to get to the time of day.

    When you go into sleep, though, the basis for calculating the uptime
    gets messed up.   The clock stops happening but the 8254 keeps ticking,
    and various calls to cputimer_count() causes the software to continue to
    update the 32 bit cputimer counter.  When you wake up again, nanoputime()
    gets a big delta.

:And it printed out the following message on the console:
:    nanouptime: nsec went negative;delta: 8697958, count: 55705685, base: 470077
:27, freq64_nsec: 3599591090043

    The 8254 delta you've printed here is 8.6 million ticks.  The 8254 runs
    at 1.19MHz so we are talking around 8 seconds worth of delta here.  This
    easily overflows the pot, so to speak.

    There are two possible solutions.  First, we can put a cap on the delta
    in the various micro/nanotime routines.  I'd prefer not to do this 
    because those routines are in the critical path.  Second, we can add a
    procedure to pmtimer_resume() which resets the deltas.

    This isn't entirely trivial since MP boxes need special care.  I will have
    a patch set for you to try in a moment.


[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]