Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Jul 2002 15:46:45 +1000 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Giorgos Keramidas <keramida@FreeBSD.ORG>
Cc:        audit@FreeBSD.ORG
Subject:   Re: sysconf(_SC_CLK_TCK) [NetBSD: basesrc/lib/libc/gen]
Message-ID:  <20020701142849.U6692-100000@gamplex.bde.org>
In-Reply-To: <20020630040139.GC1223@hades.hell.gr>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 30 Jun 2002, Giorgos Keramidas wrote:

> Does the following change look like a nice thing to make to our libc
> too?  I'm asking before trying to make a diff that does this, because
> the log mentions that the standards do not require this to return the
> value of HZ, and it's probably improper if programs depend on this
> being == HZ.

It's not only improper; it is just wrong.  sysconf(_SC_CLK_TCK) has
nothing to do with the clock that has frequency hz Hz.  It is fuzzily
related to the clock that has frequency stathz Hz.  Under FreeBSD,
sysconf(_SC_CLK_TCK) is always 128; stathz is always 128 on i386's
except in early versions of FreeBSD-2 it was the same as hz and in
FreeBSD-1 it didn't exist; stathz is different from 128 on some arches
(e.g., on sparc64's it is the same as hz which may be user-configurable
(default 100); hz is very arch-dependent and/or user-configurable
(e.g., it is user-configurable on i386's (default 100), and decided
by the hardware on alphas (usually 1024?)).

> 	Date: Sun, 23 Jun 2002 22:19:03 +0300 (EEST)
> 	From: "Perry E. Metzger" <perry@netbsd.org>
> 	Subject: CVS commit: basesrc/lib/libc/gen
> 	To: source-changes@netbsd.org
>
> 	Modified Files:
> 		basesrc/lib/libc/gen: sysconf.c
>
> 	Log Message:
> 	make sysconf(_SC_CLK_TCK) return the kernel hz value, instead of a
> 	fixed constant, as is done on Solaris, Linux, etc.
>
> 	Technically, standards don't *require* this, but having it return a
> 	constant is a violation of the spirit, and screws up programs that
> 	(perhaps improperly) assume that it will return kernel hz.

NetBSD should probably use stathz in preference to hz.

The correct value for sysconf(_SC_CLK_TCK) is currently 1000000 or
some multiple of that.  Any other value causes gratuitous loss of
precision due to double rounding in the one interface where
sysconf(_SC_CLK_TCK) is used, namely times(3) (NetBSD also changed
libc/gen/times.c to go with the above commit).  times(3) is implemented
using getrusage(2).  The kernel starts with the total process time
which has a precision of 2^-64 seconds in -current (1 usec in RELENG_4).
It converts this to usec, so the precision is reduced to 1 usec in
both -current and RELENG_4.  The time is accurate to about 1 usec on
current hardware, so 1 usec is adequate precision.  The kernel then
subdivides the total process time into user, system and interrupt
portions according to the number of user, system and interrupt statclock
ticks that occurred while the process was running.  These ticks have
a resolution of 1/stathz seconds, so the subdivision is fuzzy.  The
subdivision is a little less fuzzy in -current, since interrupt
handling is pessimized by switching to a different process, so there
are no interrupt ticks except for interrupt tasks.  The kernel then
reports the subdivided time to userland using getrusage().  times(3)
just scales the subdivided time into units of 1/sysconf(_SC_CLK_TCK)
seconds (it actually uses CLK_TCK instead of sysconf(_SC_CLK_TCK) in
FreeBSD; this is fixed in NetBSD).  It loses accuracy by up to
1000000/syscons(_SC_CLK_TCK) (typically 7812) usec.  This is not very
important, since statistical errors in the subdivision may lose even
more accuracy.  However, it would be nice if the sum of the user and
system times were as accurate as possible.

Changing sysconf(_SC_CLK_TCK) to stathz now would mainly prepare for
changing it to a more sensible value later (clock_t needs to have more
than 32 bits before sysconf(_SC_CLK_TCK) can have a sensibly large
value), and this change can wait until 32 bit arches are not supported.
No one uses times(3) anyway -- its man page says that it was obsoleted
by getrusage(2) long ago.  Note that CLK_TCK needs to be changed to
sysconf(_SC_CLK_TCK) to go with this change, or better removed (it
was knwn to be a mistake in the first version of POSIX and was removed
in POSIX.1-2001).  Note that changing CLK_TCK breaks binary compatibility,
and removing breaks source compatibility with crufty sources starting
with libc/gen/times.c.

There are similar issues for ISO C's CLOCKS_PER_SEC.  fanf pointed to
a discussion in comp.std.c about C99's breakage of CLOCKS_PER_SEC.
C99 requires it to be a constant expression, so it can't be #defined
as sysconf(_SC_CLK_TCK).  Nothing seems to have come of the discussion.

Bruce


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020701142849.U6692-100000>