#pragma once #include "../relacy/relacy_std.hpp" struct livelock_test : rl::test_suite { std::atomic x; void before() { x($) = 0; } void thread(unsigned index) { if (0 == index) { for (;;) { int cmp = 1; if (x($).compare_exchange_weak(cmp, 2)) break; } } else if (1 == index) { x($).store(1); } } }; struct yield_livelock_test : rl::test_suite { std::atomic x, y; void before() { x($) = 0; y($) = 0; } void thread(unsigned index) { if (0 == index) { rl::backoff b; for (;;) { int cmp = 0; if (x($).compare_exchange_weak(cmp, 1)) { cmp = 0; if (y($).compare_exchange_weak(cmp, 1)) { x($).store(0); y($).store(0); break; } else { x($).store(0); } } b.yield($); } } else if (1 == index) { rl::backoff b; for (;;) { int cmp = 0; if (y($).compare_exchange_weak(cmp, 1)) { cmp = 0; if (x($).compare_exchange_weak(cmp, 1)) { y($).store(0); x($).store(0); break; } else { y($).store(0); } } b.yield($); } } } }; struct sched_load_test : rl::test_suite { std::recursive_mutex mtx1, mtx2; std::condition_variable_any cv1, cv2; VAR_T(int) data1, data2; void before() { } void thread(unsigned index) { if (index % 2) { mtx1.lock($); VAR(data1) = 1; mtx1.unlock($); mtx2.lock($); mtx2.lock($); VAR(data2) = 1; mtx2.unlock($); mtx2.unlock($); if (mtx1.try_lock($)) { //mtx1.lock($); VAR(data1) = 1; //mtx1.unlock($); mtx1.unlock($); } mtx1.lock($); VAR(data1) = 2; cv1.notify_all($); mtx1.unlock($); mtx2.lock($); while (VAR(data2) != 2) { rl::yield(1, $); cv2.wait_for(mtx2, 1, $); } mtx2.unlock($); } else { mtx2.lock($); VAR(data2) = 1; mtx2.unlock($); mtx1.lock($); mtx1.lock($); VAR(data1) = 1; mtx1.unlock($); mtx1.unlock($); if (mtx2.try_lock($)) { //mtx2.lock($); VAR(data2) = 1; //mtx2.unlock($); mtx2.unlock($); } mtx2.lock($); VAR(data2) = 2; mtx2.unlock($); cv2.notify_all($); mtx1.lock($); while (VAR(data1) != 2) { rl::yield(1, $); cv1.wait_for(mtx1, 1, $); } mtx1.unlock($); } } };