From 81d2797e33d6f95c0b79e20ae8a04f2a4f3841cc Mon Sep 17 00:00:00 2001 From: Yabin Cui Date: Tue, 22 Mar 2016 13:45:55 -0700 Subject: [PATCH] Fix pthread.pthread_barrier_smoke test. pthread_barrier_smoke test uses WaitUntilThreadSleep() to wait until BarrierTestHelper threads sleep in pthread_barrier_wait(). But this is flaky as there a two futex_wait places in pthread_barrier_wait. This patch modifies this test to avoid using WaitUntilThreadSleep(). Bug: 27780937 Change-Id: I4c36b82cce9345d5088f8854b289dc5bf7a08e8c --- tests/pthread_test.cpp | 71 +++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp index aab78adb7..0313171e6 100755 --- a/tests/pthread_test.cpp +++ b/tests/pthread_test.cpp @@ -1818,55 +1818,82 @@ TEST(pthread, pthread_barrierattr_smoke) { ASSERT_EQ(0, pthread_barrierattr_destroy(&attr)); } -struct BarrierTestHelperArg { - std::atomic tid; - pthread_barrier_t* barrier; +struct BarrierTestHelperData { + size_t thread_count; + pthread_barrier_t barrier; + std::atomic finished_mask; + std::atomic serial_thread_count; size_t iteration_count; + std::atomic finished_iteration_count; + + BarrierTestHelperData(size_t thread_count, size_t iteration_count) + : thread_count(thread_count), finished_mask(0), serial_thread_count(0), + iteration_count(iteration_count), finished_iteration_count(0) { + } +}; + +struct BarrierTestHelperArg { + int id; + BarrierTestHelperData* data; }; static void BarrierTestHelper(BarrierTestHelperArg* arg) { - arg->tid = gettid(); - for (size_t i = 0; i < arg->iteration_count; ++i) { - ASSERT_EQ(0, pthread_barrier_wait(arg->barrier)); + for (size_t i = 0; i < arg->data->iteration_count; ++i) { + int result = pthread_barrier_wait(&arg->data->barrier); + if (result == PTHREAD_BARRIER_SERIAL_THREAD) { + arg->data->serial_thread_count++; + } else { + ASSERT_EQ(0, result); + } + arg->data->finished_mask |= (1 << arg->id); + if (arg->data->finished_mask == ((1 << arg->data->thread_count) - 1)) { + ASSERT_EQ(1, arg->data->serial_thread_count); + arg->data->finished_iteration_count++; + arg->data->finished_mask = 0; + arg->data->serial_thread_count = 0; + } } } TEST(pthread, pthread_barrier_smoke) { const size_t BARRIER_ITERATION_COUNT = 10; const size_t BARRIER_THREAD_COUNT = 10; - pthread_barrier_t barrier; - ASSERT_EQ(0, pthread_barrier_init(&barrier, nullptr, BARRIER_THREAD_COUNT + 1)); - std::vector threads(BARRIER_THREAD_COUNT); + BarrierTestHelperData data(BARRIER_THREAD_COUNT, BARRIER_ITERATION_COUNT); + ASSERT_EQ(0, pthread_barrier_init(&data.barrier, nullptr, data.thread_count)); + std::vector threads(data.thread_count); std::vector args(threads.size()); for (size_t i = 0; i < threads.size(); ++i) { - args[i].tid = 0; - args[i].barrier = &barrier; - args[i].iteration_count = BARRIER_ITERATION_COUNT; + args[i].id = i; + args[i].data = &data; ASSERT_EQ(0, pthread_create(&threads[i], nullptr, reinterpret_cast(BarrierTestHelper), &args[i])); } - for (size_t iteration = 0; iteration < BARRIER_ITERATION_COUNT; ++iteration) { - for (size_t i = 0; i < threads.size(); ++i) { - WaitUntilThreadSleep(args[i].tid); - } - ASSERT_EQ(PTHREAD_BARRIER_SERIAL_THREAD, pthread_barrier_wait(&barrier)); - } for (size_t i = 0; i < threads.size(); ++i) { ASSERT_EQ(0, pthread_join(threads[i], nullptr)); } - ASSERT_EQ(0, pthread_barrier_destroy(&barrier)); + ASSERT_EQ(data.iteration_count, data.finished_iteration_count); + ASSERT_EQ(0, pthread_barrier_destroy(&data.barrier)); +} + +struct BarrierDestroyTestArg { + std::atomic tid; + pthread_barrier_t* barrier; +}; + +static void BarrierDestroyTestHelper(BarrierDestroyTestArg* arg) { + arg->tid = gettid(); + ASSERT_EQ(0, pthread_barrier_wait(arg->barrier)); } TEST(pthread, pthread_barrier_destroy) { pthread_barrier_t barrier; ASSERT_EQ(0, pthread_barrier_init(&barrier, nullptr, 2)); pthread_t thread; - BarrierTestHelperArg arg; + BarrierDestroyTestArg arg; arg.tid = 0; arg.barrier = &barrier; - arg.iteration_count = 1; ASSERT_EQ(0, pthread_create(&thread, nullptr, - reinterpret_cast(BarrierTestHelper), &arg)); + reinterpret_cast(BarrierDestroyTestHelper), &arg)); WaitUntilThreadSleep(arg.tid); ASSERT_EQ(EBUSY, pthread_barrier_destroy(&barrier)); ASSERT_EQ(PTHREAD_BARRIER_SERIAL_THREAD, pthread_barrier_wait(&barrier));