Use FUTEX_WAIT_BITSET to avoid converting timeouts.
Add unittests for pthread APIs with timeout parameter.
Bug: 17569991
Change-Id: I6b3b9b2feae03680654cd64c3112ce7644632c87
diff --git a/libc/bionic/pthread_cond.cpp b/libc/bionic/pthread_cond.cpp
index 4a69da5..adbce07 100644
--- a/libc/bionic/pthread_cond.cpp
+++ b/libc/bionic/pthread_cond.cpp
@@ -111,8 +111,8 @@
return COND_IS_SHARED(atomic_load_explicit(&state, memory_order_relaxed));
}
- int get_clock() {
- return COND_GET_CLOCK(atomic_load_explicit(&state, memory_order_relaxed));
+ bool use_realtime_clock() {
+ return COND_GET_CLOCK(atomic_load_explicit(&state, memory_order_relaxed)) == CLOCK_REALTIME;
}
#if defined(__LP64__)
@@ -170,12 +170,17 @@
return 0;
}
-static int __pthread_cond_timedwait_relative(pthread_cond_internal_t* cond, pthread_mutex_t* mutex,
- const timespec* rel_timeout_or_null) {
- unsigned int old_state = atomic_load_explicit(&cond->state, memory_order_relaxed);
+static int __pthread_cond_timedwait(pthread_cond_internal_t* cond, pthread_mutex_t* mutex,
+ bool use_realtime_clock, const timespec* abs_timeout_or_null) {
+ int result = check_timespec(abs_timeout_or_null);
+ if (result != 0) {
+ return result;
+ }
+ unsigned int old_state = atomic_load_explicit(&cond->state, memory_order_relaxed);
pthread_mutex_unlock(mutex);
- int status = __futex_wait_ex(&cond->state, cond->process_shared(), old_state, rel_timeout_or_null);
+ int status = __futex_wait_ex(&cond->state, cond->process_shared(), old_state,
+ use_realtime_clock, abs_timeout_or_null);
pthread_mutex_lock(mutex);
if (status == -ETIMEDOUT) {
@@ -184,21 +189,6 @@
return 0;
}
-static int __pthread_cond_timedwait(pthread_cond_internal_t* cond, pthread_mutex_t* mutex,
- const timespec* abs_timeout_or_null, clockid_t clock) {
- timespec ts;
- timespec* rel_timeout = NULL;
-
- if (abs_timeout_or_null != NULL) {
- rel_timeout = &ts;
- if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, clock)) {
- return ETIMEDOUT;
- }
- }
-
- return __pthread_cond_timedwait_relative(cond, mutex, rel_timeout);
-}
-
int pthread_cond_broadcast(pthread_cond_t* cond_interface) {
return __pthread_cond_pulse(__get_internal_cond(cond_interface), INT_MAX);
}
@@ -209,14 +199,14 @@
int pthread_cond_wait(pthread_cond_t* cond_interface, pthread_mutex_t* mutex) {
pthread_cond_internal_t* cond = __get_internal_cond(cond_interface);
- return __pthread_cond_timedwait(cond, mutex, NULL, cond->get_clock());
+ return __pthread_cond_timedwait(cond, mutex, false, nullptr);
}
int pthread_cond_timedwait(pthread_cond_t *cond_interface, pthread_mutex_t * mutex,
const timespec *abstime) {
pthread_cond_internal_t* cond = __get_internal_cond(cond_interface);
- return __pthread_cond_timedwait(cond, mutex, abstime, cond->get_clock());
+ return __pthread_cond_timedwait(cond, mutex, cond->use_realtime_clock(), abstime);
}
#if !defined(__LP64__)
@@ -225,8 +215,7 @@
pthread_mutex_t* mutex,
const timespec* abs_timeout) {
- return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, abs_timeout,
- CLOCK_MONOTONIC);
+ return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, false, abs_timeout);
}
extern "C" int pthread_cond_timedwait_monotonic_np(pthread_cond_t* cond_interface,
@@ -238,8 +227,13 @@
extern "C" int pthread_cond_timedwait_relative_np(pthread_cond_t* cond_interface,
pthread_mutex_t* mutex,
const timespec* rel_timeout) {
-
- return __pthread_cond_timedwait_relative(__get_internal_cond(cond_interface), mutex, rel_timeout);
+ timespec ts;
+ timespec* abs_timeout = nullptr;
+ if (rel_timeout != nullptr) {
+ absolute_timespec_from_timespec(ts, *rel_timeout, CLOCK_REALTIME);
+ abs_timeout = &ts;
+ }
+ return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, true, abs_timeout);
}
extern "C" int pthread_cond_timeout_np(pthread_cond_t* cond_interface,