xref: /llvm-project/lldb/test/Shell/Register/Inputs/x86-multithread-read.cpp (revision caedbc317a5a4f046c345c136387e3ca199d8503)
1 #include <cstdint>
2 #include <mutex>
3 #include <thread>
4 
5 std::mutex t1_mutex, t2_mutex;
6 
7 struct test_data {
8   uint32_t eax;
9   uint32_t ebx;
10 
11   struct alignas(16) {
12     uint64_t mantissa;
13     uint16_t sign_exp;
14   } st0;
15 };
16 
t_func(std::mutex & t_mutex,const test_data & t_data)17 void t_func(std::mutex &t_mutex, const test_data &t_data) {
18   std::lock_guard<std::mutex> t_lock(t_mutex);
19 
20   asm volatile(
21     "finit\t\n"
22     "fldt %2\t\n"
23     "int3\n\t"
24     :
25     : "a"(t_data.eax), "b"(t_data.ebx), "m"(t_data.st0)
26     : "st"
27   );
28 }
29 
main()30 int main() {
31   test_data t1_data = {
32     .eax = 0x05060708,
33     .ebx = 0x15161718,
34     .st0 = {0x8070605040302010, 0x4000},
35   };
36   test_data t2_data = {
37     .eax = 0x25262728,
38     .ebx = 0x35363738,
39     .st0 = {0x8171615141312111, 0xc000},
40   };
41 
42   // block both threads from proceeding
43   std::unique_lock<std::mutex> m1_lock(t1_mutex);
44   std::unique_lock<std::mutex> m2_lock(t2_mutex);
45 
46   // start both threads
47   std::thread t1(t_func, std::ref(t1_mutex), std::ref(t1_data));
48   std::thread t2(t_func, std::ref(t2_mutex), std::ref(t2_data));
49 
50   // release lock on thread 1 to make it interrupt the program
51   m1_lock.unlock();
52   // wait for thread 1 to finish
53   t1.join();
54 
55   // release lock on thread 2
56   m2_lock.unlock();
57   // wait for thread 2 to finish
58   t2.join();
59 
60   return 0;
61 }
62