Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Mar 2005 14:35:45 +0000
From:      Pete French <petefrench@ticketswitch.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/78787: sysconf(_SC_CLK_TCK) may return incorrect value
Message-ID:  <E1DAUC1-0002RC-9C@dilbert.firstcallgroup.co.uk>
Resent-Message-ID: <200503131440.j2DEe2tA019163@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>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@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@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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?E1DAUC1-0002RC-9C>