pthread: Use private futexes by default in condition variables

Now that the system properly uses shared condvars when needed, we
can enable the use of private futexes for them too.

Change-Id: Icf8351fc0a2309f764cba45c65bc3af047720cdf
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index 6a2329f..f93a241 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -1361,9 +1361,11 @@
 /* We use one bit in condition variable values as the 'shared' flag
  * The rest is a counter.
  */
-#define COND_SHARING_MASK       0x0001
+#define COND_SHARED_MASK        0x0001
 #define COND_COUNTER_INCREMENT  0x0002
-#define COND_COUNTER_MASK       (~COND_SHARING_MASK)
+#define COND_COUNTER_MASK       (~COND_SHARED_MASK)
+
+#define COND_IS_SHARED(c)  (((c)->value & COND_SHARED_MASK) != 0)
 
 /* XXX *technically* there is a race condition that could allow
  * XXX a signal to be missed.  If thread A is preempted in _wait()
@@ -1382,7 +1384,7 @@
     cond->value = 0;
 
     if (attr != NULL && *attr == PTHREAD_PROCESS_SHARED)
-        cond->value |= COND_SHARING_MASK;
+        cond->value |= COND_SHARED_MASK;
 
     return 0;
 }
@@ -1397,13 +1399,19 @@
 }
 
 /* This function is used by pthread_cond_broadcast and
- * pthread_cond_signal to atomically decrement the counter.
+ * pthread_cond_signal to atomically decrement the counter
+ * then wake-up 'counter' threads.
  */
-static void
-__pthread_cond_pulse(pthread_cond_t *cond)
+static int
+__pthread_cond_pulse(pthread_cond_t *cond, int  counter)
 {
-    long flags = (cond->value & ~COND_COUNTER_MASK);
+    long flags;
+    int  wake_op;
 
+    if (__unlikely(cond == NULL))
+        return EINVAL;
+
+    flags = (cond->value & ~COND_COUNTER_MASK);
     for (;;) {
         long oldval = cond->value;
         long newval = ((oldval - COND_COUNTER_INCREMENT) & COND_COUNTER_MASK)
@@ -1411,26 +1419,20 @@
         if (__atomic_cmpxchg(oldval, newval, &cond->value) == 0)
             break;
     }
+
+    wake_op = COND_IS_SHARED(cond) ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE;
+    __futex_syscall3(&cond->value, wake_op, counter);
+    return 0;
 }
 
 int pthread_cond_broadcast(pthread_cond_t *cond)
 {
-    if (__unlikely(cond == NULL))
-        return EINVAL;
-
-    __pthread_cond_pulse(cond);
-    __futex_wake(&cond->value, INT_MAX);
-    return 0;
+    return __pthread_cond_pulse(cond, INT_MAX);
 }
 
 int pthread_cond_signal(pthread_cond_t *cond)
 {
-    if (__unlikely(cond == NULL))
-        return EINVAL;
-
-    __pthread_cond_pulse(cond);
-    __futex_wake(&cond->value, 1);
-    return 0;
+    return __pthread_cond_pulse(cond, 1);
 }
 
 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
@@ -1444,9 +1446,10 @@
 {
     int  status;
     int  oldvalue = cond->value;
+    int  wait_op  = COND_IS_SHARED(cond) ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE;
 
     pthread_mutex_unlock(mutex);
-    status = __futex_wait(&cond->value, oldvalue, reltime);
+    status = __futex_syscall4(&cond->value, wait_op, oldvalue, reltime);
     pthread_mutex_lock(mutex);
 
     if (status == (-ETIMEDOUT)) return ETIMEDOUT;
diff --git a/libc/docs/CHANGES.TXT b/libc/docs/CHANGES.TXT
index 08b2009..9080685 100644
--- a/libc/docs/CHANGES.TXT
+++ b/libc/docs/CHANGES.TXT
@@ -83,13 +83,10 @@
 - <pthread.h>: Add pthread_condattr_init/destroy/setpshared/getpshared functions
   to enable proper shared conditional variable initialization.
 
-  Modify the pthread_mutex_t implementation to use private futexes for
-  performance reasons. Mutexes are no longer shareable between processes
-  by default anymore, unless you use PTHREAD_PROCESS_SHARED with
-  pthread_mutexattr_setpshared().
-
-  XXX: The implementation still always uses shared condvars, independent
-       of the flags being selected. This will change in a later commit.
+  Modify the pthread_mutex_t and pthread_cond_t implementation to use private
+  futexes for performance reasons. Mutexes and Condvars are no longer shareable
+  between processes by default anymore, unless you use PTHREAD_PROCESS_SHARED
+  with pthread_mutexattr_setpshared() and/or pthread_condattr_setpshared().
 
 -------------------------------------------------------------------------------
 Differences between Android 2.1 and 2.0.1: