Just a sanity check before I sumbit a buig report

Jon Noack noackjr at alumni.rice.edu
Thu Mar 10 12:42:18 PST 2005

Pete French wrote:
>>'sysctl kern.clockrate' will return this information if you don't want to
>>write a program to do it for you :)
> I was just using the code from time(1). Inteesring though - heres the
> output:
> kern.clockrate: { hz = 100, tick = 10000, tickadj = 5, profhz = 100, stathz = 100 }
> So that thinks stathz is 100, but sysconf(_SC_CLK_TCK) is returning 128!
>>What are the two machines?  stathz is 128 on i386, 100 on sparc64, and 130
>>on amd64. Or thats the defaults at least.
> These are all i386 machines - I have a number of them, all running 4.11.
> I can take the same a.out and run it on all of them - on some both
> numbers are 128, on other the numbers are 100 and 128.
> If I go to one where both the calls return 128 though, the output
> of 'sysctl kern.clockrate' is this:
> kern.clockrate: { hz = 100, tick = 10000, tickadj = 5, profhz = 1024, stathz = 128 }
> So, it looks like theres a bug in sysconf(_SC_CLK_TCK) possibly ? because
> it seems to be always returning 128, regardless of the value of stathz
> as returned by 'sysctl kern.clockrate'
> I can reproduce this on a number of machines BTW - the only things they have in
> common is that I wrote their kernel config files at various points in time...

I infer from your kern.clockrate output that you are running 4.x.

Why does sysconf(_SC_CLK_TCK) always returns 128?  Check out sysconf() 
in src/lib/libc/gen/sysconf.c (lines 83-84 of rev. 1.10):
	case _SC_CLK_TCK:
		return (CLK_TCK);

CLK_TCK is defined in src/include/time.h (line 52 of rev. 1.15):
#define	CLK_TCK		_BSD_CLK_TCK_

_BSD_CLK_TCK_ is defined in src/sys/i386/include/ansi.h (line 101 of 
#define        _BSD_CLK_TCK_           128

So on i386 (and FreeBSD 4.x), sysconf(_SC_CLK_TCK) will always return 
128.  If you look in src/sys/alpha/include/ansi.h, you'll see that on 
alpha it will always return 100.

To determine how stathz can vary, we'll have to dig deeper.  Check out 
initclocks() in src/sys/kern/kern_clock.c (lines 196-213 of rev.
	 * Set divisors to 1 (normal case) and let the machine-specific
	 * code do its bit.
	psdiv = pscnt = 1;


	 * Compute profhz/stathz, and fix profhz if needed.
	i = stathz ? stathz : hz;
	if (profhz == 0)
		profhz = i;
	psratio = profhz / i;

stathz and profhz are originally set by cpu_initclocks() (which is MD). 
  If they are not set at this point, hz is used.  This must be the case 
for some of your machines as both stathz and profhz equal hz.  So why 
aren't stathz and profhz being set earlier?  Check out cpu_initclocks() 
in src/sys/i386/isa/clock.c (lines 995-1008 of rev.
**********************************************************************			if 
(statclock_disable) {
		 * The stat interrupt mask is different without the
		 * statistics clock.  Also, don't set the interrupt
		 * flag which would normally cause the RTC to generate
		 * interrupts.
		stat_imask = HWI_MASK | SWI_MASK;
		rtc_statusb = RTCSB_24HR;
	} else {
	        /* Setting stathz to nonzero early helps avoid races. */
		stathz = RTC_NOPROFRATE;
		profhz = RTC_PROFRATE;

If you look in src/sys/isa/rtc.h, you'll see that RTC_NOPROFRATE=128 and 
RTC_PROFRATE=1024.  The only way stathz and profhz will not be set here 
is if statclock_disable is true.  Where is statclock_disable set?  Check 
out apm_attach() in src/sys/i386/apm/apm.c (lines 1032-1033 of rev.
	if (flags & 0x20)
		statclock_disable = 1;

Thus, you must have "device apm0 flags 0x20" or something similar in 
your kernel config file for you to get stathz and profhz as 100.  apm is 
disabled in GENERIC, so by default this is not a problem; apm_attach 
won't be called if apm is disabled, so the fact that GENERIC includes 
"flags 0x20" is irrelevant.


More information about the freebsd-stable mailing list