Add pthread_condattr_init/destroy/setpshared/getpshared
Note that this does not change the implementation of conditional variables which still use shared futexes, independent on the flags being selected. This will be fixed in a later patch, once our system is modified to use pthread_condattr_setpshared(attr, PTHREAD_PROCESS_SHARED) properly. Change-Id: I935de50964cd41f97a13dbfd6626d3407b0406c3
This commit is contained in:
@@ -1248,11 +1248,57 @@ int pthread_mutex_lock_timeout_np(pthread_mutex_t *mutex, unsigned msecs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pthread_condattr_init(pthread_condattr_t *attr)
|
||||||
|
{
|
||||||
|
if (attr == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
*attr = PTHREAD_PROCESS_PRIVATE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_condattr_getpshared(pthread_condattr_t *attr, int *pshared)
|
||||||
|
{
|
||||||
|
if (attr == NULL || pshared == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
*pshared = *attr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared)
|
||||||
|
{
|
||||||
|
if (attr == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
if (pshared != PTHREAD_PROCESS_SHARED &&
|
||||||
|
pshared != PTHREAD_PROCESS_PRIVATE)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
*attr = pshared;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_condattr_destroy(pthread_condattr_t *attr)
|
||||||
|
{
|
||||||
|
if (attr == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
*attr = 0xdeada11d;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We use one bit in condition variable values as the 'shared' flag
|
||||||
|
* The rest is a counter.
|
||||||
|
*/
|
||||||
|
#define COND_SHARING_MASK 0x0001
|
||||||
|
#define COND_COUNTER_INCREMENT 0x0002
|
||||||
|
#define COND_COUNTER_MASK (~COND_SHARING_MASK)
|
||||||
|
|
||||||
/* 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()
|
||||||
* XXX after unlocking the mutex and before waiting, and if other
|
* XXX after unlocking the mutex and before waiting, and if other
|
||||||
* XXX threads call signal or broadcast UINT_MAX times (exactly),
|
* XXX threads call signal or broadcast UINT_MAX/2 times (exactly),
|
||||||
* XXX before thread A is scheduled again and calls futex_wait(),
|
* XXX before thread A is scheduled again and calls futex_wait(),
|
||||||
* XXX then the signal will be lost.
|
* XXX then the signal will be lost.
|
||||||
*/
|
*/
|
||||||
@@ -1260,26 +1306,59 @@ int pthread_mutex_lock_timeout_np(pthread_mutex_t *mutex, unsigned msecs)
|
|||||||
int pthread_cond_init(pthread_cond_t *cond,
|
int pthread_cond_init(pthread_cond_t *cond,
|
||||||
const pthread_condattr_t *attr)
|
const pthread_condattr_t *attr)
|
||||||
{
|
{
|
||||||
|
if (cond == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
cond->value = 0;
|
cond->value = 0;
|
||||||
|
|
||||||
|
if (attr != NULL && *attr == PTHREAD_PROCESS_SHARED)
|
||||||
|
cond->value |= COND_SHARING_MASK;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_cond_destroy(pthread_cond_t *cond)
|
int pthread_cond_destroy(pthread_cond_t *cond)
|
||||||
{
|
{
|
||||||
|
if (cond == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
cond->value = 0xdeadc04d;
|
cond->value = 0xdeadc04d;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function is used by pthread_cond_broadcast and
|
||||||
|
* pthread_cond_signal to atomically decrement the counter.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
__pthread_cond_pulse(pthread_cond_t *cond)
|
||||||
|
{
|
||||||
|
long flags = (cond->value & ~COND_COUNTER_MASK);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
long oldval = cond->value;
|
||||||
|
long newval = ((oldval - COND_COUNTER_INCREMENT) & COND_COUNTER_MASK)
|
||||||
|
| flags;
|
||||||
|
if (__atomic_cmpxchg(oldval, newval, &cond->value) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int pthread_cond_broadcast(pthread_cond_t *cond)
|
int pthread_cond_broadcast(pthread_cond_t *cond)
|
||||||
{
|
{
|
||||||
__atomic_dec(&cond->value);
|
if (__unlikely(cond == NULL))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
__pthread_cond_pulse(cond);
|
||||||
__futex_wake(&cond->value, INT_MAX);
|
__futex_wake(&cond->value, INT_MAX);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_cond_signal(pthread_cond_t *cond)
|
int pthread_cond_signal(pthread_cond_t *cond)
|
||||||
{
|
{
|
||||||
__atomic_dec(&cond->value);
|
if (__unlikely(cond == NULL))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
__pthread_cond_pulse(cond);
|
||||||
__futex_wake(&cond->value, 1);
|
__futex_wake(&cond->value, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -78,7 +78,13 @@ Differences between current and Android 2.1:
|
|||||||
|
|
||||||
- DNS: get rid of spurious random DNS queries when trying to resolve
|
- DNS: get rid of spurious random DNS queries when trying to resolve
|
||||||
an unknown domain name. Due to an initialization bug, a random DNS search
|
an unknown domain name. Due to an initialization bug, a random DNS search
|
||||||
list was generated for each thread is net.dns.search is not defined.
|
list was generated for each thread if net.dns.search is not defined.
|
||||||
|
|
||||||
|
- <pthread.h>: Add pthread_condattr_init/destroy/setpshared/getpshared functions
|
||||||
|
to enable proper shared conditional variable initialization.
|
||||||
|
|
||||||
|
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:
|
||||||
|
@@ -165,6 +165,11 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex);
|
|||||||
int pthread_mutex_trylock(pthread_mutex_t *mutex);
|
int pthread_mutex_trylock(pthread_mutex_t *mutex);
|
||||||
int pthread_mutex_timedlock(pthread_mutex_t *mutex, struct timespec* ts);
|
int pthread_mutex_timedlock(pthread_mutex_t *mutex, struct timespec* ts);
|
||||||
|
|
||||||
|
int pthread_condattr_init(pthread_condattr_t *attr);
|
||||||
|
int pthread_condattr_getpshared(pthread_condattr_t *attr, int *pshared);
|
||||||
|
int pthread_condattr_setpshared(pthread_condattr_t* attr, int pshared);
|
||||||
|
int pthread_condattr_destroy(pthread_condattr_t *attr);
|
||||||
|
|
||||||
int pthread_cond_init(pthread_cond_t *cond,
|
int pthread_cond_init(pthread_cond_t *cond,
|
||||||
const pthread_condattr_t *attr);
|
const pthread_condattr_t *attr);
|
||||||
int pthread_cond_destroy(pthread_cond_t *cond);
|
int pthread_cond_destroy(pthread_cond_t *cond);
|
||||||
|
Reference in New Issue
Block a user