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
This commit is contained in:
David 'Digit' Turner
2010-03-19 17:59:23 -07:00
parent 377d4c979d
commit b5e4a41606
2 changed files with 27 additions and 27 deletions

View File

@@ -1361,9 +1361,11 @@ int pthread_condattr_destroy(pthread_condattr_t *attr)
/* We use one bit in condition variable values as the 'shared' flag /* We use one bit in condition variable values as the 'shared' flag
* The rest is a counter. * The rest is a counter.
*/ */
#define COND_SHARING_MASK 0x0001 #define COND_SHARED_MASK 0x0001
#define COND_COUNTER_INCREMENT 0x0002 #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 *technically* there is a race condition that could allow
* XXX a signal to be missed. If thread A is preempted in _wait() * XXX a signal to be missed. If thread A is preempted in _wait()
@@ -1382,7 +1384,7 @@ int pthread_cond_init(pthread_cond_t *cond,
cond->value = 0; cond->value = 0;
if (attr != NULL && *attr == PTHREAD_PROCESS_SHARED) if (attr != NULL && *attr == PTHREAD_PROCESS_SHARED)
cond->value |= COND_SHARING_MASK; cond->value |= COND_SHARED_MASK;
return 0; return 0;
} }
@@ -1397,13 +1399,19 @@ int pthread_cond_destroy(pthread_cond_t *cond)
} }
/* This function is used by pthread_cond_broadcast and /* 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 static int
__pthread_cond_pulse(pthread_cond_t *cond) __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 (;;) { for (;;) {
long oldval = cond->value; long oldval = cond->value;
long newval = ((oldval - COND_COUNTER_INCREMENT) & COND_COUNTER_MASK) long newval = ((oldval - COND_COUNTER_INCREMENT) & COND_COUNTER_MASK)
@@ -1411,26 +1419,20 @@ __pthread_cond_pulse(pthread_cond_t *cond)
if (__atomic_cmpxchg(oldval, newval, &cond->value) == 0) if (__atomic_cmpxchg(oldval, newval, &cond->value) == 0)
break; 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) int pthread_cond_broadcast(pthread_cond_t *cond)
{ {
if (__unlikely(cond == NULL)) return __pthread_cond_pulse(cond, INT_MAX);
return EINVAL;
__pthread_cond_pulse(cond);
__futex_wake(&cond->value, INT_MAX);
return 0;
} }
int pthread_cond_signal(pthread_cond_t *cond) int pthread_cond_signal(pthread_cond_t *cond)
{ {
if (__unlikely(cond == NULL)) return __pthread_cond_pulse(cond, 1);
return EINVAL;
__pthread_cond_pulse(cond);
__futex_wake(&cond->value, 1);
return 0;
} }
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
@@ -1444,9 +1446,10 @@ int __pthread_cond_timedwait_relative(pthread_cond_t *cond,
{ {
int status; int status;
int oldvalue = cond->value; int oldvalue = cond->value;
int wait_op = COND_IS_SHARED(cond) ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE;
pthread_mutex_unlock(mutex); pthread_mutex_unlock(mutex);
status = __futex_wait(&cond->value, oldvalue, reltime); status = __futex_syscall4(&cond->value, wait_op, oldvalue, reltime);
pthread_mutex_lock(mutex); pthread_mutex_lock(mutex);
if (status == (-ETIMEDOUT)) return ETIMEDOUT; if (status == (-ETIMEDOUT)) return ETIMEDOUT;

View File

@@ -83,13 +83,10 @@ Differences between current and Android 2.1:
- <pthread.h>: Add pthread_condattr_init/destroy/setpshared/getpshared functions - <pthread.h>: Add pthread_condattr_init/destroy/setpshared/getpshared functions
to enable proper shared conditional variable initialization. to enable proper shared conditional variable initialization.
Modify the pthread_mutex_t implementation to use private futexes for Modify the pthread_mutex_t and pthread_cond_t implementation to use private
performance reasons. Mutexes are no longer shareable between processes futexes for performance reasons. Mutexes and Condvars are no longer shareable
by default anymore, unless you use PTHREAD_PROCESS_SHARED with between processes by default anymore, unless you use PTHREAD_PROCESS_SHARED
pthread_mutexattr_setpshared(). with pthread_mutexattr_setpshared() and/or pthread_condattr_setpshared().
XXX: The implementation still always uses shared condvars, independent
of the flags being selected. This will change in a later commit.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Differences between Android 2.1 and 2.0.1: Differences between Android 2.1 and 2.0.1: