Message ID | CAKo4hFKbWfhqYino5HjDPwKNzW0nPvF1CWqKrn=utMeEieiVuA@mail.gmail.com |
---|---|
State | Superseded |
Headers | show |
Sorry, Latests official glibc in system dependent implementation for Linux simply use MAKE_THREAD_CPUCLOCK https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/pthread_getcpuclockid.c;h=f5af64ea88b92e64ed86c4a9ca254bbceb103b29;hb=9fe3c80c7c3dbce34dadc7f0693d211fdd9a0b03 On Wed, Apr 26, 2017 at 2:22 AM, Sergey Korolev <s.korolev@ndmsystems.com> wrote: > Current uClibc-ng version incorrectly calculates clockid > in pthread_getcpuclockid (at least for modern kernels). The simplest test > program > > #include <time.h> > #include <errno.h> > #include <stdio.h> > #include <stdlib.h> > #include <pthread.h> > > int main() > { > clockid_t clk; > struct timespec ts; > const int err = pthread_getcpuclockid(pthread_self(), &clk); > > if (err != 0) { > errno = err; > perror("pthread_getcpuclockid"); > return EXIT_FAILURE; > } > > if (clock_gettime(clk, &ts) == -1) { > perror("clock_gettime"); > return EXIT_FAILURE; > } > > printf("Thread time is %lu.%06lu.\n", > ts.tv_sec, > ts.tv_nsec / 1000); > > return EXIT_SUCCESS; > } > > fails with > > clock_gettime: Invalid argument > > Tested on Linux 3.4 / MIPS built with GCC 5.4.0. > > Other implementations, for example musl, use a simple calculation > https://git.musl-libc.org/cgit/musl/tree/src/thread/ > pthread_getcpuclockid.c > > Looks strange, but the official glibc repository > https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=nptl/ > pthread_getcpuclockid.c;hb=HEAD > has the same implementation as in uClibc-ng. > > This fork https://github.com/lattera/glibc/blob/master/ > nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c > use more accurate approach relying on __NR_clock_getres (defined in the > kernel since 2.6.24) with MAKE_THREAD_CPUCLOCK macro copied from the kernel > (http://lxr.free-electrons.com/source/include/linux/ > posix-timers.h?v=2.6.24#L34, Linux 4.10 has the same one). > > I propose an intermediate solution: use MAKE_THREAD_CPUCLOCK like > computation of clockid when __NR_clock_getres defined and do a fallback to > an older implementation when not. >
Hi Sergey, Sergey Korolev wrote, > Current uClibc-ng version incorrectly calculates clockid > in pthread_getcpuclockid (at least for modern kernels). The simplest test > program > > fails with > > clock_gettime: Invalid argument > > Tested on Linux 3.4 / MIPS built with GCC 5.4.0. Thanks for the test case. > Other implementations, for example musl, use a simple calculation > https://git.musl-libc.org/cgit/musl/tree/src/thread/pthread_getcpuclockid.c > > Looks strange, but the official glibc repository > https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=nptl/ > pthread_getcpuclockid.c;hb=HEAD > has the same implementation as in uClibc-ng. uClibc imported NPTL from GNU libc in 2005. There are still many similaraties. Will you propose a new patch? ( I have read your second mail) best regards Waldemar
From caebc4ced19c46725109d607c47a355d66da3097 Mon Sep 17 00:00:00 2001 From: Sergey Korolev <s.korolev@ndmsystems.com> Date: Tue, 25 Apr 2017 02:14:59 +0300 Subject: [PATCH] pthread_getcpuclockid.c: fix clockid calculation According to newer linux kernel sources (since 2.6.24) MAKE_THREAD_CPUCLOCK macro should be used to get clockid. The fix use MAKE_THREAD_CPUCLOCK-like computation when __NR_clock_getres defined and do a fallback to an older implementation when not. --- .../nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c index ca3570f..0fe6a35 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c @@ -20,6 +20,8 @@ #include <sys/time.h> #include <tls.h> +#define CPUCLOCK_PERTHREAD_MASK 4 +#define CPUCLOCK_SCHED 2 int pthread_getcpuclockid ( @@ -33,7 +35,13 @@ pthread_getcpuclockid ( /* Not a valid thread handle. */ return ESRCH; -#ifdef CLOCK_THREAD_CPUTIME_ID +#ifdef __NR_clock_getres + *clockid = ((~(clockid_t) (pd->tid)) << CLOCK_IDFIELD_SIZE) + | CPUCLOCK_SCHED | CPUCLOCK_PERTHREAD_MASK; + + return 0; +#else +# ifdef CLOCK_THREAD_CPUTIME_ID /* We need to store the thread ID in the CLOCKID variable together with a number identifying the clock. We reserve the low 3 bits for the clock ID and the rest for the thread ID. This is @@ -49,8 +57,9 @@ pthread_getcpuclockid ( *clockid = CLOCK_THREAD_CPUTIME_ID | (pd->tid << CLOCK_IDFIELD_SIZE); return 0; -#else +# else /* We don't have a timer for that. */ return ENOENT; +# endif #endif } -- 2.7.4