diff options
Diffstat (limited to 'libc/bionic/pthread.c')
| -rw-r--r-- | libc/bionic/pthread.c | 63 |
1 files changed, 22 insertions, 41 deletions
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c index 6fd47f2..ac5e6bf 100644 --- a/libc/bionic/pthread.c +++ b/libc/bionic/pthread.c @@ -43,7 +43,7 @@ #include <memory.h> #include <assert.h> #include <malloc.h> -#include <linux/futex.h> +#include <bionic_futex.h> #include <cutils/atomic-inline.h> #include <sys/prctl.h> #include <sys/stat.h> @@ -54,6 +54,16 @@ extern void _exit_with_stack_teardown(void * stackBase, int stackSize, int retCo extern void _exit_thread(int retCode); extern int __set_errno(int); +int __futex_wake_ex(volatile void *ftx, int pshared, int val) +{ + return __futex_syscall3(ftx, pshared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, val); +} + +int __futex_wait_ex(volatile void *ftx, int pshared, int val, const struct timespec *timeout) +{ + return __futex_syscall4(ftx, pshared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE, val, timeout); +} + #define __likely(cond) __builtin_expect(!!(cond), 1) #define __unlikely(cond) __builtin_expect(!!(cond), 0) @@ -716,24 +726,6 @@ int pthread_setschedparam(pthread_t thid, int policy, } -int __futex_wait(volatile void *ftx, int val, const struct timespec *timeout); -int __futex_wake(volatile void *ftx, int count); - -int __futex_syscall3(volatile void *ftx, int op, int val); -int __futex_syscall4(volatile void *ftx, int op, int val, const struct timespec *timeout); - -#ifndef FUTEX_PRIVATE_FLAG -#define FUTEX_PRIVATE_FLAG 128 -#endif - -#ifndef FUTEX_WAIT_PRIVATE -#define FUTEX_WAIT_PRIVATE (FUTEX_WAIT|FUTEX_PRIVATE_FLAG) -#endif - -#ifndef FUTEX_WAKE_PRIVATE -#define FUTEX_WAKE_PRIVATE (FUTEX_WAKE|FUTEX_PRIVATE_FLAG) -#endif - // mutex lock states // // 0: unlocked @@ -935,10 +927,8 @@ _normal_lock(pthread_mutex_t* mutex) * that the mutex is in state 2 when we go to sleep on it, which * guarantees a wake-up call. */ - int wait_op = shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE; - while (__atomic_swap(shared|2, &mutex->value ) != (shared|0)) - __futex_syscall4(&mutex->value, wait_op, shared|2, 0); + __futex_wait_ex(&mutex->value, shared, shared|2, 0); } ANDROID_MEMBAR_FULL(); } @@ -961,7 +951,6 @@ _normal_unlock(pthread_mutex_t* mutex) * if it wasn't 1 we have to do some additional work. */ if (__atomic_dec(&mutex->value) != (shared|1)) { - int wake_op = shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE; /* * Start by releasing the lock. The decrement changed it from * "contended lock" to "uncontended lock", which means we still @@ -999,7 +988,7 @@ _normal_unlock(pthread_mutex_t* mutex) * Either way we have correct behavior and nobody is orphaned on * the wait queue. */ - __futex_syscall3(&mutex->value, wake_op, 1); + __futex_wake_ex(&mutex->value, shared, 1); } } @@ -1019,7 +1008,7 @@ _recursive_unlock(void) int pthread_mutex_lock(pthread_mutex_t *mutex) { - int mtype, tid, new_lock_type, shared, wait_op; + int mtype, tid, new_lock_type, shared; if (__unlikely(mutex == NULL)) return EINVAL; @@ -1064,8 +1053,7 @@ int pthread_mutex_lock(pthread_mutex_t *mutex) new_lock_type = 1; /* compute futex wait opcode and restore shared flag in mtype */ - wait_op = shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE; - mtype |= shared; + mtype |= shared; for (;;) { int oldv; @@ -1091,7 +1079,7 @@ int pthread_mutex_lock(pthread_mutex_t *mutex) */ new_lock_type = 2; - __futex_syscall4(&mutex->value, wait_op, oldv, NULL); + __futex_wait_ex(&mutex->value, shared, oldv, NULL); } return 0; } @@ -1131,8 +1119,7 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex) /* Wake one waiting thread, if any */ if ((oldv & 3) == 2) { - int wake_op = shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE; - __futex_syscall3(&mutex->value, wake_op, 1); + __futex_wake_ex(&mutex->value, shared, 1); } return 0; } @@ -1234,7 +1221,7 @@ int pthread_mutex_lock_timeout_np(pthread_mutex_t *mutex, unsigned msecs) clockid_t clock = CLOCK_MONOTONIC; struct timespec abstime; struct timespec ts; - int mtype, tid, oldv, new_lock_type, shared, wait_op; + int mtype, tid, oldv, new_lock_type, shared; /* compute absolute expiration time */ __timespec_to_relative_msec(&abstime, msecs, clock); @@ -1248,8 +1235,6 @@ int pthread_mutex_lock_timeout_np(pthread_mutex_t *mutex, unsigned msecs) /* Handle common case first */ if ( __likely(mtype == MUTEX_TYPE_NORMAL) ) { - int wait_op = shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE; - /* fast path for uncontended lock */ if (__atomic_cmpxchg(shared|0, shared|1, &mutex->value) == 0) { ANDROID_MEMBAR_FULL(); @@ -1261,7 +1246,7 @@ int pthread_mutex_lock_timeout_np(pthread_mutex_t *mutex, unsigned msecs) if (__timespec_to_absolute(&ts, &abstime, clock) < 0) return EBUSY; - __futex_syscall4(&mutex->value, wait_op, shared|2, &ts); + __futex_wait_ex(&mutex->value, shared, shared|2, &ts); } ANDROID_MEMBAR_FULL(); return 0; @@ -1294,7 +1279,6 @@ int pthread_mutex_lock_timeout_np(pthread_mutex_t *mutex, unsigned msecs) new_lock_type = 1; /* Compute wait op and restore sharing bit in mtype */ - wait_op = shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE; mtype |= shared; for (;;) { @@ -1325,7 +1309,7 @@ int pthread_mutex_lock_timeout_np(pthread_mutex_t *mutex, unsigned msecs) if (__timespec_to_absolute(&ts, &abstime, clock) < 0) return EBUSY; - __futex_syscall4(&mutex->value, wait_op, oldv, &ts); + __futex_wait_ex(&mutex->value, shared, oldv, &ts); } return 0; } @@ -1418,7 +1402,6 @@ static int __pthread_cond_pulse(pthread_cond_t *cond, int counter) { long flags; - int wake_op; if (__unlikely(cond == NULL)) return EINVAL; @@ -1432,8 +1415,7 @@ __pthread_cond_pulse(pthread_cond_t *cond, int counter) break; } - wake_op = COND_IS_SHARED(cond) ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE; - __futex_syscall3(&cond->value, wake_op, counter); + __futex_wake_ex(&cond->value, COND_IS_SHARED(cond), counter); return 0; } @@ -1458,10 +1440,9 @@ int __pthread_cond_timedwait_relative(pthread_cond_t *cond, { int status; int oldvalue = cond->value; - int wait_op = COND_IS_SHARED(cond) ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE; pthread_mutex_unlock(mutex); - status = __futex_syscall4(&cond->value, wait_op, oldvalue, reltime); + status = __futex_wait_ex(&cond->value, COND_IS_SHARED(cond), oldvalue, reltime); pthread_mutex_lock(mutex); if (status == (-ETIMEDOUT)) return ETIMEDOUT; |
