Fix pthread_getcpuclockid.

clock_gettime was returning EINVAL for the values
produced by pthread_getcpuclockid.

Bug: 10346183
Change-Id: Iabe643d7d46110bb311a0367aa0fc737f653208e
diff --git a/libc/bionic/pthread_getcpuclockid.cpp b/libc/bionic/pthread_getcpuclockid.cpp
index 10046ba..d11f56a 100644
--- a/libc/bionic/pthread_getcpuclockid.cpp
+++ b/libc/bionic/pthread_getcpuclockid.cpp
@@ -36,7 +36,13 @@
     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<clockid_t>(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 177e452..902bf69 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -157,7 +157,7 @@
 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 c7dbdc7..d4d38f5 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -278,6 +278,16 @@
   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<void*>(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);