// Copyright 2018 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef ZIRCON_SYSTEM_UTEST_CORE_CONDITION_GENERIC_CONDITION_GENERIC_H_ #define ZIRCON_SYSTEM_UTEST_CORE_CONDITION_GENERIC_CONDITION_GENERIC_H_ #include #include #include #include template class GenericConditionTest { public: static bool condition_test() { BEGIN_TEST; Context ctx; thrd_t thread1, thread2, thread3; thrd_create(&thread1, cond_thread, &ctx); thrd_create(&thread2, cond_thread, &ctx); thrd_create(&thread3, cond_thread, &ctx); // Wait for all the threads to report that they've started. while (true) { ctx.mutex.lock(); int threads = ctx.threads_started; ctx.mutex.unlock(); if (threads == 3) { break; } sched_yield(); } ctx.cond.broadcast(); // Wait for all the threads to report that they were woken. while (true) { ctx.mutex.lock(); int threads = ctx.threads_woke_first_barrier; ctx.mutex.unlock(); if (threads == 3) { break; } sched_yield(); } for (int iteration = 0; iteration < 3; iteration++) { ctx.cond.signal(); // Wait for one thread to report that it was woken. while (true) { ctx.mutex.lock(); int threads = ctx.threads_waked; ctx.mutex.unlock(); if (threads == iteration + 1) { break; } sched_yield(); } } thrd_join(thread1, nullptr); thrd_join(thread2, nullptr); thrd_join(thread3, nullptr); END_TEST; } static bool condition_timeout_test() { BEGIN_TEST; Condition cond; Mutex mutex; mutex.lock(); zx_status_t result = cond.timedwait(&mutex, ZX_MSEC(1)); mutex.unlock(); EXPECT_EQ(result, ZX_ERR_TIMED_OUT, "Lock should have timeout"); END_TEST; } private: struct Context { Mutex mutex; Condition cond; int threads_waked = 0; int threads_started = 0; int threads_woke_first_barrier = 0; }; static int cond_thread(void* arg) { auto* ctx = static_cast(arg); ctx->mutex.lock(); ctx->threads_started++; ctx->cond.wait(&ctx->mutex); ctx->threads_woke_first_barrier++; ctx->cond.wait(&ctx->mutex); ctx->threads_waked++; ctx->mutex.unlock(); return 0; } }; #endif // ZIRCON_SYSTEM_UTEST_CORE_CONDITION_GENERIC_CONDITION_GENERIC_H_