]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/atomic/test/wait_fuzz.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / atomic / test / wait_fuzz.cpp
CommitLineData
20effc67
TL
1// Copyright (c) 2020 Andrey Semashev
2//
3// Distributed under the Boost Software License, Version 1.0.
4// See accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6
7// This is a fuzzing test for waiting and notifying operations.
8// The test creates a number of threads exceeding the number of hardware threads, each of which
9// blocks on the atomic object. The main thread then notifies one or all threads repeatedly,
10// while incrementing the atomic object. The test ends when the atomic counter reaches the predefined limit.
11// The goal of the test is to verify that (a) it doesn't crash and (b) all threads get unblocked in the end.
12
13#include <boost/memory_order.hpp>
14#include <boost/atomic/atomic.hpp>
15
16#include <iostream>
17#include <boost/config.hpp>
18#include <boost/bind/bind.hpp>
19#include <boost/chrono/chrono.hpp>
20#include <boost/thread/thread.hpp>
21#include <boost/thread/barrier.hpp>
22#include <boost/smart_ptr/scoped_array.hpp>
23
24namespace chrono = boost::chrono;
25
26boost::atomic< unsigned int > g_atomic(0u);
27
28BOOST_CONSTEXPR_OR_CONST unsigned int loop_count = 4096u;
29
30void thread_func(boost::barrier* barrier)
31{
32 barrier->wait();
33
34 unsigned int old_count = 0u;
35 while (true)
36 {
37 unsigned int new_count = g_atomic.wait(old_count, boost::memory_order_relaxed);
38 if (new_count >= loop_count)
39 break;
40
41 old_count = new_count;
42 }
43}
44
45int main()
46{
47 const unsigned int thread_count = boost::thread::hardware_concurrency() + 4u;
48 boost::barrier barrier(thread_count + 1u);
49 boost::scoped_array< boost::thread > threads(new boost::thread[thread_count]);
50
51 for (unsigned int i = 0u; i < thread_count; ++i)
52 boost::thread(boost::bind(&thread_func, &barrier)).swap(threads[i]);
53
54 barrier.wait();
55
56 // Let the threads block on the atomic counter
57 boost::this_thread::sleep_for(chrono::milliseconds(100));
58
59 while (true)
60 {
61 for (unsigned int i = 0u; i < thread_count; ++i)
62 {
63 g_atomic.opaque_add(1u, boost::memory_order_relaxed);
64 g_atomic.notify_one();
65 }
66
67 unsigned int old_count = g_atomic.fetch_add(1u, boost::memory_order_relaxed);
68 g_atomic.notify_all();
69
70 if ((old_count + 1u) >= loop_count)
71 break;
72 }
73
74 for (unsigned int i = 0u; i < thread_count; ++i)
75 threads[i].join();
76
77 return 0u;
78}