svn commit: r191883 - head/sys/compat/linux

Bruce Evans brde at
Mon May 11 01:30:32 UTC 2009

On Sun, 10 May 2009, Chagin Dmitry wrote:

> On Fri, May 08, 2009 at 11:45:16AM +1000, Bruce Evans wrote:
>> On Thu, 7 May 2009, Dmitry Chagin wrote:
>>> Log:
>>>  Linux exports HZ value to user space via AT_CLKTCK auxiliary vector entry,
>>>  which is available for Glibc as sysconf(_SC_CLK_TCK). If AT_CLKTCK entry is
>>>  not exported, Glibc uses 100.
>> This cannot work for older applications/glibc's that have CLK_TCK hard-coded.
> yes, I know. Glibc versions prior to 2.2.1 uses hardcoded CLK_TCK value.

>>> -
>>> -#define CONVTCK(r)	(r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
>>> +#define CONVTCK(r)	(r.tv_sec * hz + r.tv_usec / (1000000 / hz))
>> hz has very little to do with statistics clock ticks.  The frequency of the
>> statistics clock in FreeBSD is given by stathz.  stathz will normally only
>> equal hz if the statistics clock is the same as the scheduling clock.
>> stathz is a bogus value too since the clock most relevant for them is the
>> cputicker and the statistics clock is only used to divide them up.
> Thank you!
>> Anyway, this patch is backwards.  The bug was that the value exported to
>> user space didn't match the value here.  The value cannot be changed in
> hmm, r189362. hz exported to user space via AT_CLKTCK.

Bug in r189362.  Now larger.  CLK_TCK = 100 should be exported to user
space via AT_CLKTCK.

>> either FreeBSD or Linux without breaking compatibility.  It is even
>> harder to change in emulators than in a full O/S distribution since the
>> full distribution can more reasonably drop support for all old
>> applications.  A correct emulator would have to have an array of values
>> for each "constant" sysconf() value with the arrays index by the O/S
>> version and maybe the libc version being emulated :-(.
> I will try to make the hard-coded CLK_TCK support. It will depend
> on value of compat.linux.osrelease (2.2 I guess).

Er, it should be constant (= old CLK_TCK = 100).  Old applications are
unlikely to look at compat.linx.osrelease and change their behaviour
depending on it, and anyway they cannot know what to do with an osrelease
newer than themself.  New applications won't care if AT_CLKTCK returns the
old value of CLK_TCK, unless the value is increased significantly (say to
1 million) to give more accuracy.

Linux itself does this, at least in 2.6.10:

% ./arch/ia64/ia32/binfmt_elf32.c:
% #define IA32_CLOCKS_PER_SEC	100	/* Cast in stone for IA32 Linux */

This ia32 value is used for Linux own emulation of compat32.  It has to
be cast in stone since previous mistakes cast it there.  So does the
native ia32 value, but that is not so well commented.  The Linux native
ia64 value might be variable because it doesn't have any mistakes to be
compatible with.

% ./fs/binfmt_elf.c:

This maps AT_CLKTCK to CLOCKS_PER_SEC.  Related mistakes are responsible
for mapping CLK_TCK to CLOCKS_PER_SEC.  IIRC, POSIX.1-1988 narrowly escaped
the bug of specifying CLK_TCK to be the same as CLOCKS_PER_SEC,  It still
has the bug of specifying CLK_TCK at all.  This is partly fixed in
POSIX.1-1990 by specifying CLK_TCK as obsolescent and saying that
CLK_TCK may be #defined as (the variable) sysconf(_SC_CLK_TCK), and is
fixed in POSIX.1-2001 by removing CLK_TCK.

% ./include/asm-x86_64/param.h:
% #ifdef __KERNEL__
% # define HZ            1000            /* Internal kernel timer frequency */
% # define USER_HZ       100          /* .. some user interfaces are in "ticks */
% #define CLOCKS_PER_SEC        (USER_HZ)       /* like times() */
% #endif

Most arches distinguish between the kernel clock(s) and values returned to
userland using HZ/USER_HZ like this, so that the latter can be kept
constant.  Apparently native x86_64 is too old to have not inherited the

% ./include/asm-i386/param.h:
% #ifdef __KERNEL__
% # define HZ		1000		/* Internal kernel timer frequency */
% # define USER_HZ	100		/* .. some user interfaces are in "ticks" */
% # define CLOCKS_PER_SEC		(USER_HZ)	/* like times() */
% #endif

The mistake is oldest in i386.

% ./include/asm-ia64/param.h:
% #ifdef __KERNEL__
% # include <linux/config.h>	/* mustn't include <linux/config.h> outside of #ifdef __KERNEL__ */
% # ifdef CONFIG_IA64_HP_SIM
%   /*
%    * Yeah, simulating stuff is slow, so let us catch some breath between
%    * timer interrupts...
%    */
% #  define HZ	  32
% # else
% #  define HZ	1024
% # endif
% # define USER_HZ	HZ
% # define CLOCKS_PER_SEC	HZ	/* frequency at which times() counts */
% #else
%    /*
%     * Technically, this is wrong, but some old apps still refer to it.  The proper way to
%     * get the HZ value is via sysconf(_SC_CLK_TCK).
%     */
% # define HZ 1024
% #endif

ia64 (itanium?) is the main arch for which USER_HZ is the same as HZ.
The only(?) others are m68knommu, alpha and h8300.  According the the
comment, broken apps have related problems for HZ.

If linux-later-than-2.6.10 has fixed this, then it would have to have a new
syscall for times() and for any other interface that uses "clock ticks"
(mainly clock()), and the FreeBSD emulator would have to emulate these.
Linux apparently doesn't have new interfaces, so emulators cannot have them
and cannot fix the mistakes without making a larger mess.


More information about the svn-src-all mailing list