kern/78787: sysconf(_SC_CLK_TCK) may return incorrect value
Pete French
petefrench at ticketswitch.com
Sun Mar 13 06:40:03 PST 2005
>Number: 78787
>Category: kern
>Synopsis: sysconf(_SC_CLK_TCK) may return incorrect value
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sun Mar 13 14:40:02 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator: Pete French
>Release: FreeBSD 4.11-RELEASE i386
>Organization:
TicketSwitch Limited
>Environment:
System: FreeBSD dilbert.rattatosk 4.11-RELEASE FreeBSD 4.11-RELEASE #0: Wed Jan 26 12:22:35 GMT 2005 petefrench at dilbert.rattatosk:/usr/obj/usr/src/sys/DILBERT i386
>Description:
sysconf(_SC_CLK_TCK) returns a contstant value defined in
src/sys/i386/include/ansi.h this is not correct as the actual value of
the statistics clock is not a constnat. In particular it is 100Hz on
my system, but the constant returned is 128. The stat clock may be 100Hz
is apm is enabled with flags 0x20 in the kernel file
>How-To-Repeat:
Build a kernel which has a statistics clock other tahn 128 and observe that
sysconf(_SC_CLK_TCK) returns the wrong value!
>Fix:
The call to sysconf(_SC_CLK_TCK) should actuallyy query the kernel to
get the correct value. Note that this is how /usr/bin/time gets the
frequency of the clock.
I have included below an analysis of the problem done by someone else on
the FreeBSD stable mailing lists, which follwos the code through in more
depth. I do not know if this problem still exists in 5 or CURRENT.
Response from Jon Noack <noackjr at alumni.rice.edu> to my query on -stable
-------------------------------------------------------------------
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
rev. 1.18.2.4):
**********************************************************************
#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.
1.105.2.11):
**********************************************************************
/*
* Set divisors to 1 (normal case) and let the machine-specific
* code do its bit.
*/
psdiv = pscnt = 1;
cpu_initclocks();
#ifdef DEVICE_POLLING
init_device_poll();
#endif
/*
* 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. 1.149.2.6):
********************************************************************** 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.
1.114.2.6):
**********************************************************************
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.
Jon
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list