xref: /llvm-project/lldb/test/API/commands/watchpoints/watchpoint_set_command/main.cpp (revision fdea9a4ec9b0d9585b8fe8a612686d9f44f40ddc)
1 #include <chrono>
2 #include <condition_variable>
3 #include <cstdio>
4 #include <thread>
5 
6 std::condition_variable g_condition_variable;
7 std::mutex g_mutex;
8 int g_count;
9 
10 char *g_char_ptr = nullptr;
11 
12 void
barrier_wait()13 barrier_wait()
14 {
15     std::unique_lock<std::mutex> lock{g_mutex};
16     if (--g_count > 0)
17         g_condition_variable.wait(lock);
18     else
19         g_condition_variable.notify_all();
20 }
21 
22 void
do_bad_thing_with_location(unsigned index,char * char_ptr,char new_val)23 do_bad_thing_with_location(unsigned index, char *char_ptr, char new_val)
24 {
25     unsigned what = new_val;
26     printf("new value written to array(%p) and index(%u) = %u\n", char_ptr, index, what);
27     char_ptr[index] = new_val;
28 }
29 
30 uint32_t
access_pool(bool flag=false)31 access_pool (bool flag = false)
32 {
33     static std::mutex g_access_mutex;
34     static unsigned idx = 0; // Well-behaving thread only writes into indexs from 0..6.
35     if (!flag)
36         g_access_mutex.lock();
37 
38     // idx valid range is [0, 6].
39     if (idx > 6)
40         idx = 0;
41 
42     if (flag)
43     {
44         // Write into a forbidden area.
45         do_bad_thing_with_location(7, g_char_ptr, 99);
46     }
47 
48     unsigned index = idx++;
49 
50     if (!flag)
51         g_access_mutex.unlock();
52     return g_char_ptr[index];
53 }
54 
55 void
thread_func(uint32_t thread_index)56 thread_func (uint32_t thread_index)
57 {
58     printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index);
59 
60     barrier_wait();
61 
62     uint32_t count = 0;
63     uint32_t val;
64     while (count++ < 15)
65     {
66         printf ("%s (thread = %u) sleeping for 1 second...\n", __FUNCTION__, thread_index);
67         std::this_thread::sleep_for(std::chrono::seconds(1));
68 
69         if (count < 7)
70             val = access_pool ();
71         else
72             val = access_pool (true);
73 
74         printf ("%s (thread = %u) after sleep access_pool returns %d (count=%d)...\n", __FUNCTION__, thread_index, val, count);
75     }
76     printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index);
77 }
78 
79 
main(int argc,char const * argv[])80 int main (int argc, char const *argv[])
81 {
82     g_count = 4;
83     std::thread threads[3];
84 
85     g_char_ptr = new char[10]{};
86 
87     // Create 3 threads
88     for (auto &thread : threads)
89         thread = std::thread{thread_func, std::distance(threads, &thread)};
90 
91     struct {
92         int a;
93         int b;
94         int c;
95     } MyAggregateDataType;
96 
97     printf ("Before turning all three threads loose...\n"); // Set break point at this line.
98     barrier_wait();
99 
100     // Join all of our threads
101     for (auto &thread : threads)
102         thread.join();
103 
104     delete[] g_char_ptr;
105 
106     return 0;
107 }
108