From patchwork Tue Apr 25 23:22:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Korolev X-Patchwork-Id: 755131 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from helium.openadk.org (helium.openadk.org [89.238.66.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wCK4n2KBFz9s3w for ; Wed, 26 Apr 2017 09:22:47 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=ndmsystems-com.20150623.gappssmtp.com header.i=@ndmsystems-com.20150623.gappssmtp.com header.b="rpp4O4AO"; dkim-atps=neutral Received: from helium.openadk.org (localhost [IPv6:::1]) by helium.openadk.org (Postfix) with ESMTP id BE3F010686; Wed, 26 Apr 2017 01:22:42 +0200 (CEST) X-Original-To: devel@uclibc-ng.org Delivered-To: devel@helium.openadk.org Received: from mail-qk0-f175.google.com (mail-qk0-f175.google.com [209.85.220.175]) by helium.openadk.org (Postfix) with ESMTPS id E342110686 for ; Wed, 26 Apr 2017 01:22:37 +0200 (CEST) Received: by mail-qk0-f175.google.com with SMTP id f76so78811785qke.2 for ; Tue, 25 Apr 2017 16:22:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ndmsystems-com.20150623.gappssmtp.com; s=20150623; h=mime-version:from:date:message-id:subject:to; bh=RVS77D0TwexOOYn8/FqTWoQYk7yPwjisMhAj3sam35k=; b=rpp4O4AOjRGPiEbIPom3mywLMoZbqhTcAcNJxNvd3YYfSkXE8P9sz/88DPvB6fVafP jhIWOwtK0bbFiju9+wIwHLz2diiv++lz2IsG0ulWf7KcA+SscJb4+Ux3e+YaVUqJNwNM Q+YEZBjK+zmjWXaBemS2Dqdc7C6BiIiyFJ0oZqKsU+IMYtX0ySyXi0vgWBpjoSlx1xeS kNIK+kxpZkNuou6+ot20t0fSzUl/YsU648wx9QosArRsP/4kIw/PF7IcaUJAZbdZaoNK MPBEq9szX+M98Blg0BTRrtSYuGm9zhZz5ScWf3wbO16JCHB7YW52CThyAnZLQhrjn5Go UWXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=RVS77D0TwexOOYn8/FqTWoQYk7yPwjisMhAj3sam35k=; b=MN99a9j8bEM9e2X1r1ouNpT/aWBIUHa+Nma2qaqB0mkTbz/amXGWK89sVsekpztGbr soKu9yp/aZ/lg3fG6QJMSATlwoAKCoVH3JnELsEQM0LTKu1L3/ly946+MZ+DuaSvvL+r 2iDO3IGFSW3ynnvvUKWW2a+xYxwpjoz6zz9029+tClEQ4l4EETxb/VmgCrj9QU7pW/N3 ViGVxEhiNJ0KEFVLg6ZlTjeCjb0Xb4fcsivAVfb5BU3F9oWK7e/JgEL9Ks8+OFNnLuWf eY1Gnezi/vDr3AOQeIYcdzURwPDCQ1evzjCSLJOKZ+/BgQ5VfOLOF1GlT943y8+XoeEB 8jQg== X-Gm-Message-State: AN3rC/48/7vcpa/JwO8J3DSGWtGArDQvuVUFFqQM9mQtyMLjvb4lOeiB DvQGs3uFeeWijqVp5wwsTlyBBX8Hahh8NxI= X-Received: by 10.55.189.1 with SMTP id n1mr30765647qkf.136.1493162555809; Tue, 25 Apr 2017 16:22:35 -0700 (PDT) MIME-Version: 1.0 Received: by 10.140.16.9 with HTTP; Tue, 25 Apr 2017 16:22:34 -0700 (PDT) From: Sergey Korolev Date: Wed, 26 Apr 2017 02:22:34 +0300 Message-ID: To: devel@uclibc-ng.org Subject: [uclibc-ng-devel] [PATCH] pthread_getcpuclockid.c: fix clockid calculation X-BeenThere: devel@uclibc-ng.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: uClibc-ng Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: devel-bounces@uclibc-ng.org Sender: "devel" Current uClibc-ng version incorrectly calculates clockid in pthread_getcpuclockid (at least for modern kernels). The simplest test program #include #include #include #include #include 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. From caebc4ced19c46725109d607c47a355d66da3097 Mon Sep 17 00:00:00 2001 From: Sergey Korolev 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 #include +#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