From 51f122997d95d99a2b0e68444995323789c9da37 Mon Sep 17 00:00:00 2001 From: dchagin Date: Sun, 10 May 2009 18:43:43 +0000 Subject: Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0, as it has appeared in the 2.4.0-rc7 first time. Being exported, AT_CLKTCK is returned by sysconf(_SC_CLK_TCK), glibc falls back to the hard-coded CLK_TCK value when aux entry is not present. Glibc versions prior to 2.2.1 always use hard-coded CLK_TCK value. For older applications/libc's which depends on hard-coded CLK_TCK value user should set compat.linux.osrelease less than 2.4.0. Approved by: kib (mentor) --- sys/amd64/linux32/linux32_sysvec.c | 12 +++++++++++- sys/compat/linux/linux_mib.h | 1 + sys/compat/linux/linux_misc.c | 14 +++++++++++++- sys/i386/linux/linux_sysvec.c | 12 +++++++++++- 4 files changed, 36 insertions(+), 3 deletions(-) (limited to 'sys') diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c index 6010045..2626ccf 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -261,7 +261,17 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp) pos = base + (imgp->args->argc + imgp->args->envc + 2); AUXARGS_ENTRY_32(pos, LINUX_AT_HWCAP, cpu_feature); - AUXARGS_ENTRY_32(pos, LINUX_AT_CLKTCK, stclohz); + + /* + * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0, + * as it has appeared in the 2.4.0-rc7 first time. + * Being exported, AT_CLKTCK is returned by sysconf(_SC_CLK_TCK), + * glibc falls back to the hard-coded CLK_TCK value when aux entry + * is not present. + * Also see linux_times() implementation. + */ + if (linux_kernver(curthread) >= LINUX_KERNVER_2004000) + AUXARGS_ENTRY_32(pos, LINUX_AT_CLKTCK, stclohz); AUXARGS_ENTRY_32(pos, AT_PHDR, args->phdr); AUXARGS_ENTRY_32(pos, AT_PHENT, args->phent); AUXARGS_ENTRY_32(pos, AT_PHNUM, args->phnum); diff --git a/sys/compat/linux/linux_mib.h b/sys/compat/linux/linux_mib.h index 9f0f41c..f78a5e5 100644 --- a/sys/compat/linux/linux_mib.h +++ b/sys/compat/linux/linux_mib.h @@ -45,6 +45,7 @@ int linux_set_oss_version(struct thread *td, int oss_version); int linux_kernver(struct thread *td); +#define LINUX_KERNVER_2004000 2004000 #define LINUX_KERNVER_2006000 2006000 #define linux_use26(t) (linux_kernver(t) >= LINUX_KERNVER_2006000) diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index c5b1e54..7279197 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -661,7 +661,19 @@ struct l_times_argv { l_clock_t tms_cstime; }; -#define CONVTCK(r) (r.tv_sec * stclohz + r.tv_usec / (1000000 / stclohz)) + +/* + * Glibc versions prior to 2.2.1 always use hard-coded CLK_TCK value. + * Since 2.2.1 Glibc uses value exported from kernel via AT_CLKTCK + * auxiliary vector entry. + */ +#define CLK_TCK 100 + +#define CONVOTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK)) +#define CONVNTCK(r) (r.tv_sec * stclohz + r.tv_usec / (1000000 / stclohz)) + +#define CONVTCK(r) (linux_kernver(td) >= LINUX_KERNVER_2004000 ? \ + CONVNTCK(r) : CONVOTCK(r)) int linux_times(struct thread *td, struct linux_times_args *args) diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 0a3d297..186e14c 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -255,7 +255,17 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp) pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2); AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature); - AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz); + + /* + * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0, + * as it has appeared in the 2.4.0-rc7 first time. + * Being exported, AT_CLKTCK is returned by sysconf(_SC_CLK_TCK), + * glibc falls back to the hard-coded CLK_TCK value when aux entry + * is not present. + * Also see linux_times() implementation. + */ + if (linux_kernver(curthread) >= LINUX_KERNVER_2004000) + AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz); AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); AUXARGS_ENTRY(pos, AT_PHENT, args->phent); AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); -- cgit v1.1