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:
@@ -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;
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user