2020-02-28 18:12:52 +00:00
|
|
|
#include <thread>
|
|
|
|
#include <iostream>
|
2020-04-20 07:45:19 +00:00
|
|
|
#include <atomic>
|
2020-02-28 18:12:52 +00:00
|
|
|
|
|
|
|
#include <common/sleep.h>
|
|
|
|
|
|
|
|
#include <IO/ReadHelpers.h>
|
|
|
|
|
|
|
|
#include <Common/Exception.h>
|
2020-03-01 21:56:17 +00:00
|
|
|
#include <Common/ThreadFuzzer.h>
|
2020-02-28 18:12:52 +00:00
|
|
|
|
|
|
|
|
2020-03-01 21:56:17 +00:00
|
|
|
/** Prooves that ThreadFuzzer helps to find concurrency bugs.
|
|
|
|
*
|
|
|
|
* for i in {1..10}; do ./chaos_sanitizer 1000000; done
|
|
|
|
* for i in {1..10}; do THREAD_FUZZER_CPU_TIME_PERIOD_US=1000 THREAD_FUZZER_SLEEP_PROBABILITY=0.1 THREAD_FUZZER_SLEEP_TIME_US=100000 ./chaos_sanitizer 1000000; done
|
|
|
|
*/
|
|
|
|
int main(int argc, char ** argv)
|
2020-02-28 18:12:52 +00:00
|
|
|
{
|
2020-03-01 21:56:17 +00:00
|
|
|
const size_t num_iterations = argc >= 2 ? DB::parse<size_t>(argv[1]) : 1000000000;
|
2020-02-28 18:12:52 +00:00
|
|
|
|
2020-03-01 21:56:17 +00:00
|
|
|
std::cerr << (DB::ThreadFuzzer::instance().isEffective() ? "ThreadFuzzer is enabled.\n" : "ThreadFuzzer is not enabled.\n");
|
2020-02-28 18:12:52 +00:00
|
|
|
|
2020-04-20 07:45:19 +00:00
|
|
|
std::atomic<size_t> counter1 = 0;
|
|
|
|
std::atomic<size_t> counter2 = 0;
|
2020-03-01 16:06:08 +00:00
|
|
|
|
2020-03-01 21:56:17 +00:00
|
|
|
/// These threads are synchronized by sleep (that's intentionally incorrect).
|
2020-02-28 18:12:52 +00:00
|
|
|
|
2020-03-01 21:56:17 +00:00
|
|
|
std::thread t1([&]
|
2020-02-28 18:12:52 +00:00
|
|
|
{
|
2020-03-01 21:56:17 +00:00
|
|
|
for (size_t i = 0; i < num_iterations; ++i)
|
2020-04-20 07:45:19 +00:00
|
|
|
counter1.store(counter1.load(std::memory_order_relaxed) + 1, std::memory_order_relaxed);
|
2020-03-01 20:18:26 +00:00
|
|
|
|
2020-03-01 21:56:17 +00:00
|
|
|
sleepForNanoseconds(100000000);
|
2020-03-01 16:06:08 +00:00
|
|
|
|
2020-03-01 21:56:17 +00:00
|
|
|
for (size_t i = 0; i < num_iterations; ++i)
|
2020-04-20 07:45:19 +00:00
|
|
|
counter2.store(counter2.load(std::memory_order_relaxed) + 1, std::memory_order_relaxed);
|
2020-03-01 21:56:17 +00:00
|
|
|
});
|
2020-02-28 18:12:52 +00:00
|
|
|
|
2020-03-01 21:56:17 +00:00
|
|
|
std::thread t2([&]
|
2020-03-01 16:06:08 +00:00
|
|
|
{
|
2020-03-01 21:56:17 +00:00
|
|
|
for (size_t i = 0; i < num_iterations; ++i)
|
2020-04-20 07:45:19 +00:00
|
|
|
counter2.store(counter2.load(std::memory_order_relaxed) + 1, std::memory_order_relaxed);
|
2020-03-01 16:06:08 +00:00
|
|
|
|
2020-03-01 21:56:17 +00:00
|
|
|
sleepForNanoseconds(100000000);
|
2020-02-28 18:12:52 +00:00
|
|
|
|
2020-03-01 21:56:17 +00:00
|
|
|
for (size_t i = 0; i < num_iterations; ++i)
|
2020-04-20 07:45:19 +00:00
|
|
|
counter1.store(counter1.load(std::memory_order_relaxed) + 1, std::memory_order_relaxed);
|
2020-03-01 21:56:17 +00:00
|
|
|
});
|
2020-02-28 18:12:52 +00:00
|
|
|
|
2020-03-01 21:56:17 +00:00
|
|
|
t1.join();
|
|
|
|
t2.join();
|
2020-03-01 16:06:08 +00:00
|
|
|
|
2020-03-01 21:56:17 +00:00
|
|
|
std::cerr << "Result: " << counter1 << ", " << counter2 << "\n";
|
2020-03-01 16:06:08 +00:00
|
|
|
|
2020-02-28 18:12:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|