From 9b06cc3c1b2c4e2b08582f3fc9393a05aa589766 Mon Sep 17 00:00:00 2001 From: Jeff Hao Date: Thu, 15 Aug 2013 14:51:16 -0700 Subject: [PATCH] Fix pthread_getcpuclockid. clock_gettime was returning EINVAL for the values produced by pthread_getcpuclockid. Bug: 10346183 Change-Id: Iabe643d7d46110bb311a0367aa0fc737f653208e --- libc/bionic/pthread_getcpuclockid.cpp | 10 ++++++++-- tests/Android.mk | 2 +- tests/pthread_test.cpp | 10 ++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/libc/bionic/pthread_getcpuclockid.cpp b/libc/bionic/pthread_getcpuclockid.cpp index 10046bab5..d11f56a2a 100644 --- a/libc/bionic/pthread_getcpuclockid.cpp +++ b/libc/bionic/pthread_getcpuclockid.cpp @@ -36,7 +36,13 @@ int pthread_getcpuclockid(pthread_t t, clockid_t* clockid) { return ESRCH; } - enum { CLOCK_IDTYPE_BITS = 3 }; - *clockid = CLOCK_THREAD_CPUTIME_ID | (thread->tid << CLOCK_IDTYPE_BITS); + // The tid is stored in the top bits, but negated. + clockid_t result = ~static_cast(thread->tid) << 3; + // Bits 0 and 1: clock type (0 = CPUCLOCK_PROF, 1 = CPUCLOCK_VIRT, 2 = CPUCLOCK_SCHED). + result |= 2; + // Bit 2: thread (set) or process (clear)? + result |= (1 << 2); + + *clockid = result; return 0; } diff --git a/tests/Android.mk b/tests/Android.mk index 177e4520b..902bf6959 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -157,7 +157,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := bionic-unit-tests-glibc LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_CFLAGS += $(test_c_flags) -LOCAL_LDFLAGS += -lpthread -ldl +LOCAL_LDFLAGS += -lpthread -ldl -lrt LOCAL_LDFLAGS += $(test_dynamic_ldflags) LOCAL_SRC_FILES := $(test_src_files) $(test_dynamic_src_files) LOCAL_STATIC_LIBRARIES += bionic-unit-tests-unwind-test-impl-host diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp index c7dbdc78c..d4d38f521 100644 --- a/tests/pthread_test.cpp +++ b/tests/pthread_test.cpp @@ -278,6 +278,16 @@ TEST(pthread, pthread_detach__no_such_thread) { ASSERT_EQ(ESRCH, pthread_detach(dead_thread)); } +TEST(pthread, pthread_getcpuclockid__clock_gettime) { + pthread_t t; + ASSERT_EQ(0, pthread_create(&t, NULL, SleepFn, reinterpret_cast(5))); + + clockid_t c; + ASSERT_EQ(0, pthread_getcpuclockid(t, &c)); + timespec ts; + ASSERT_EQ(0, clock_gettime(c, &ts)); +} + TEST(pthread, pthread_getcpuclockid__no_such_thread) { pthread_t dead_thread; MakeDeadThread(dead_thread);