pmtimer and nanouptime

YONETANI Tomokazu qhwt+dragonfly-bugs at les.ath.cx
Tue Jul 20 04:45:21 PDT 2004


Hello.
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:

- getnanotime() returns non-normalized timespec value when
  basetime.tv_nsec is out of range.

- basetime.tv_nsec becomes out of range when pmtimer_resume() calls
  inittodr(0) which calls set_timeofday(), because nanouptime()
  returns non-normalized value.

- 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.

  nanouptime(struct timespec *tsp)
  {
	  struct globaldata *gd = mycpu;
	  int64_t delta, nsec;
	  sysclock_t count, base;

	  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;
	  if (nsec >= 1000000000) {
		  nsec -= 1000000000;
		  ++tsp->tv_sec;
	  }
	  tsp->tv_nsec = nsec;
	  if (nsec < 0 || 1000000000 <= nsec) {
		  printf("nanouptime: nsec went negative;"
		      "delta: %lld, count: %u, base: %u, freq64_nsec: %lld"
		      "\n",
		      delta, count, base, cputimer_freq64_nsec);
	  }
  }

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

Here (cputimer_freq64_nsec * delta) doesn't fit within signed-64bit
and nsec becomes negative value, bypassing the following conditional.
I'm not sure what to change to fix this.





More information about the Bugs mailing list