summaryrefslogtreecommitdiffstats
path: root/libcxx/test/std/thread
diff options
context:
space:
mode:
authorDan Albert <danalbert@google.com>2019-09-16 17:57:48 +0000
committerDan Albert <danalbert@google.com>2019-09-16 17:57:48 +0000
commit5e37d7f9ff257ec62d733d3d94b11f03e0fe51ca (patch)
treef4af4ede926be38fda3e28290cb730b12d6faa81 /libcxx/test/std/thread
parent6fcd4e080f09c9765d6e0ea03b1da91669c8509a (diff)
downloadbcm5719-llvm-5e37d7f9ff257ec62d733d3d94b11f03e0fe51ca.tar.gz
bcm5719-llvm-5e37d7f9ff257ec62d733d3d94b11f03e0fe51ca.zip
Implement std::condition_variable via pthread_cond_clockwait() where available
std::condition_variable is currently implemented via pthread_cond_timedwait() on systems that use pthread. This is problematic, since that function waits by default on CLOCK_REALTIME and libc++ does not provide any mechanism to change from this default. Due to this, regardless of if condition_variable::wait_until() is called with a chrono::system_clock or chrono::steady_clock parameter, condition_variable::wait_until() will wait using CLOCK_REALTIME. This is not accurate to the C++ standard as calling condition_variable::wait_until() with a chrono::steady_clock parameter should use CLOCK_MONOTONIC. This is particularly problematic because CLOCK_REALTIME is a bad choice as it is subject to discontinuous time adjustments, that may cause condition_variable::wait_until() to immediately timeout or wait indefinitely. This change fixes this issue with a new POSIX function, pthread_cond_clockwait() proposed on http://austingroupbugs.net/view.php?id=1216. The new function is similar to pthread_cond_timedwait() with the addition of a clock parameter that allows it to wait using either CLOCK_REALTIME or CLOCK_MONOTONIC, thus allowing condition_variable::wait_until() to wait using CLOCK_REALTIME for chrono::system_clock and CLOCK_MONOTONIC for chrono::steady_clock. pthread_cond_clockwait() is implemented in glibc (2.30 and later) and Android's bionic (Android API version 30 and later). This change additionally makes wait_for() and wait_until() with clocks other than chrono::system_clock use CLOCK_MONOTONIC.<Paste> llvm-svn: 372016
Diffstat (limited to 'libcxx/test/std/thread')
-rw-r--r--libcxx/test/std/thread/thread.condition/thread.condition.condvar/wait_until.pass.cpp33
1 files changed, 22 insertions, 11 deletions
diff --git a/libcxx/test/std/thread/thread.condition/thread.condition.condvar/wait_until.pass.cpp b/libcxx/test/std/thread/thread.condition/thread.condition.condvar/wait_until.pass.cpp
index 12ccf3f1c06..e5c77f28eb8 100644
--- a/libcxx/test/std/thread/thread.condition/thread.condition.condvar/wait_until.pass.cpp
+++ b/libcxx/test/std/thread/thread.condition/thread.condition.condvar/wait_until.pass.cpp
@@ -25,12 +25,12 @@
#include "test_macros.h"
-struct Clock
+struct TestClock
{
typedef std::chrono::milliseconds duration;
typedef duration::rep rep;
typedef duration::period period;
- typedef std::chrono::time_point<Clock> time_point;
+ typedef std::chrono::time_point<TestClock> time_point;
static const bool is_steady = true;
static time_point now()
@@ -50,35 +50,40 @@ int test2 = 0;
int runs = 0;
+template <typename Clock>
void f()
{
std::unique_lock<std::mutex> lk(mut);
assert(test2 == 0);
test1 = 1;
cv.notify_one();
- Clock::time_point t0 = Clock::now();
- Clock::time_point t = t0 + Clock::duration(250);
+ typename Clock::time_point t0 = Clock::now();
+ typename Clock::time_point t = t0 + std::chrono::milliseconds(250);
while (test2 == 0 && cv.wait_until(lk, t) == std::cv_status::no_timeout)
;
- Clock::time_point t1 = Clock::now();
+ typename Clock::time_point t1 = Clock::now();
if (runs == 0)
{
- assert(t1 - t0 < Clock::duration(250));
+ assert(t1 - t0 < std::chrono::milliseconds(250));
assert(test2 != 0);
}
else
{
- assert(t1 - t0 - Clock::duration(250) < Clock::duration(50));
+ assert(t1 - t0 - std::chrono::milliseconds(250) < std::chrono::milliseconds(50));
assert(test2 == 0);
}
++runs;
}
-int main(int, char**)
+template <typename Clock>
+void run_test()
{
+ runs = 0;
+ test1 = 0;
+ test2 = 0;
{
std::unique_lock<std::mutex>lk(mut);
- std::thread t(f);
+ std::thread t(f<Clock>);
assert(test1 == 0);
while (test1 == 0)
cv.wait(lk);
@@ -92,7 +97,7 @@ int main(int, char**)
test2 = 0;
{
std::unique_lock<std::mutex>lk(mut);
- std::thread t(f);
+ std::thread t(f<Clock>);
assert(test1 == 0);
while (test1 == 0)
cv.wait(lk);
@@ -100,6 +105,12 @@ int main(int, char**)
lk.unlock();
t.join();
}
+}
- return 0;
+int main(int, char**)
+{
+ run_test<TestClock>();
+ run_test<std::chrono::steady_clock>();
+ run_test<std::chrono::system_clock>();
+ return 0;
}
OpenPOWER on IntegriCloud