Implement pthread_condattr_{get,set}clock.

We only support CLOCK_REALTIME and CLOCK_MONOTONIC for now,
so we us a single bit from pthread_cond_t->value to denote
the clock type. Note that this reduces the width of the counter
to 30 bits, but this should be large enough for all practical
purposes.

bug: 13232338

Change-Id: I857e7da64b3ecbb23eeac7c9f3fbd460f60231bd
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index d234118..d481a1d 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -22,6 +22,7 @@
 #include <pthread.h>
 #include <signal.h>
 #include <sys/mman.h>
+#include <time.h>
 #include <unistd.h>
 
 TEST(pthread, pthread_key_create) {
@@ -597,3 +598,58 @@
   ASSERT_EQ(0, pthread_attr_getscope(&attr, &scope));
   ASSERT_EQ(PTHREAD_SCOPE_SYSTEM, scope);
 }
+
+TEST(pthread, pthread_condattr_init) {
+  pthread_condattr_t attr;
+  pthread_condattr_init(&attr);
+
+  clockid_t clock;
+  ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
+  ASSERT_EQ(CLOCK_REALTIME, clock);
+
+  int pshared;
+  ASSERT_EQ(0, pthread_condattr_getpshared(&attr, &pshared));
+  ASSERT_EQ(PTHREAD_PROCESS_PRIVATE, pshared);
+}
+
+TEST(pthread, pthread_condattr_setclock) {
+  pthread_condattr_t attr;
+  pthread_condattr_init(&attr);
+
+  ASSERT_EQ(0, pthread_condattr_setclock(&attr, CLOCK_REALTIME));
+  clockid_t clock;
+  ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
+  ASSERT_EQ(CLOCK_REALTIME, clock);
+
+  ASSERT_EQ(0, pthread_condattr_setclock(&attr, CLOCK_MONOTONIC));
+  ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
+  ASSERT_EQ(CLOCK_MONOTONIC, clock);
+
+  ASSERT_EQ(EINVAL, pthread_condattr_setclock(&attr, CLOCK_PROCESS_CPUTIME_ID));
+}
+
+TEST(pthread, pthread_cond_broadcast__preserves_condattr_flags) {
+#if defined(__BIONIC__) // This tests a bionic implementation detail.
+  pthread_condattr_t attr;
+  pthread_condattr_init(&attr);
+
+  ASSERT_EQ(0, pthread_condattr_setclock(&attr, CLOCK_MONOTONIC));
+  ASSERT_EQ(0, pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED));
+
+  pthread_cond_t cond_var;
+  ASSERT_EQ(0, pthread_cond_init(&cond_var, &attr));
+
+  ASSERT_EQ(0, pthread_cond_signal(&cond_var));
+  ASSERT_EQ(0, pthread_cond_broadcast(&cond_var));
+
+  attr = static_cast<pthread_condattr_t>(cond_var.value);
+  clockid_t clock;
+  ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
+  ASSERT_EQ(CLOCK_MONOTONIC, clock);
+  int pshared;
+  ASSERT_EQ(0, pthread_condattr_getpshared(&attr, &pshared));
+  ASSERT_EQ(PTHREAD_PROCESS_SHARED, pshared);
+#else // __BIONIC__
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif // __BIONIC__
+}