Convert futex to cond wait.

Switch to the better supported pthread_cond to handle the Wait/Wake
functions.

Also, increase the number of simultaneous threads in the thread tests.

Bug: 18381207
Change-Id: I63240208e8b7f641b3f35a3fc0bb1acf80dc796e
diff --git a/libbacktrace/BacktraceThread.cpp b/libbacktrace/BacktraceThread.cpp
index b47cd2a..439cc3b 100644
--- a/libbacktrace/BacktraceThread.cpp
+++ b/libbacktrace/BacktraceThread.cpp
@@ -17,14 +17,15 @@
 #include <errno.h>
 #include <inttypes.h>
 #include <limits.h>
-#include <linux/futex.h>
 #include <pthread.h>
 #include <signal.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/syscall.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <ucontext.h>
+#include <unistd.h>
 
 #include <cutils/atomic.h>
 
@@ -32,10 +33,6 @@
 #include "BacktraceThread.h"
 #include "thread_utils.h"
 
-static inline int futex(volatile int* uaddr, int op, int val, const struct timespec* ts, volatile int* uaddr2, int val3) {
-  return syscall(__NR_futex, uaddr, op, val, ts, uaddr2, val3);
-}
-
 //-------------------------------------------------------------------------
 // ThreadEntry implementation.
 //-------------------------------------------------------------------------
@@ -45,7 +42,14 @@
 // Assumes that ThreadEntry::list_mutex_ has already been locked before
 // creating a ThreadEntry object.
 ThreadEntry::ThreadEntry(pid_t pid, pid_t tid)
-    : pid_(pid), tid_(tid), futex_(0), ref_count_(1), mutex_(PTHREAD_MUTEX_INITIALIZER), next_(ThreadEntry::list_), prev_(NULL) {
+    : pid_(pid), tid_(tid), ref_count_(1), mutex_(PTHREAD_MUTEX_INITIALIZER),
+      wait_mutex_(PTHREAD_MUTEX_INITIALIZER), wait_value_(0),
+      next_(ThreadEntry::list_), prev_(NULL) {
+  pthread_condattr_t attr;
+  pthread_condattr_init(&attr);
+  pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+  pthread_cond_init(&wait_cond_, &attr);
+
   // Add ourselves to the list.
   if (ThreadEntry::list_) {
     ThreadEntry::list_->prev_ = this;
@@ -99,22 +103,35 @@
 
   next_ = NULL;
   prev_ = NULL;
+
+  pthread_cond_destroy(&wait_cond_);
 }
 
 void ThreadEntry::Wait(int value) {
   timespec ts;
-  ts.tv_sec = 10;
-  ts.tv_nsec = 0;
-  errno = 0;
-  futex(&futex_, FUTEX_WAIT, value, &ts, NULL, 0);
-  if (errno != 0 && errno != EWOULDBLOCK) {
-    BACK_LOGW("futex wait failed, futex = %d: %s", futex_, strerror(errno));
+  if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
+    BACK_LOGW("clock_gettime failed: %s", strerror(errno));
+    abort();
   }
+  ts.tv_sec += 10;
+
+  pthread_mutex_lock(&wait_mutex_);
+  while (wait_value_ != value) {
+    int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts);
+    if (ret != 0) {
+      BACK_LOGW("pthread_cond_timedwait failed: %s", strerror(ret));
+      break;
+    }
+  }
+  pthread_mutex_unlock(&wait_mutex_);
 }
 
 void ThreadEntry::Wake() {
-  futex_++;
-  futex(&futex_, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
+  pthread_mutex_lock(&wait_mutex_);
+  wait_value_++;
+  pthread_mutex_unlock(&wait_mutex_);
+
+  pthread_cond_signal(&wait_cond_);
 }
 
 void ThreadEntry::CopyUcontextFromSigcontext(void* sigcontext) {
@@ -142,7 +159,7 @@
 
   // Pause the thread until the unwind is complete. This avoids having
   // the thread run ahead causing problems.
-  entry->Wait(1);
+  entry->Wait(2);
 
   ThreadEntry::Remove(entry);
 }
@@ -194,7 +211,7 @@
   }
 
   // Wait for the thread to get the ucontext.
-  entry->Wait(0);
+  entry->Wait(1);
 
   // After the thread has received the signal, allow other unwinders to
   // continue.