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