From 4c693a894f73af181803932b91c117f90a0ded0f Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Fri, 2 Mar 2018 00:17:05 +0000 Subject: [PATCH] Speed up TestWatchpointMultipleThreads Summary: The inferior was sleeping before doing any interesting work. I remove that to make the test faster. While looking at the purpose of the test (to check that watchpoints are propagated to all existing threads - r140757) I noticed that the test has diverged from the original intention and now it creates the threads *after* the watchpoint is set (this probably happened during the std::thread refactor). After some discussion, we decided both scenarios make sense, so I modify the test to test both. The watchpoint propagation functionality is not really debug info depenent, so I also stop replication of this test. This brings the test's time from ~108s down to 4s. Reviewers: davide, jingham Subscribers: aprantl, lldb-commits Differential Revision: https://reviews.llvm.org/D43857 llvm-svn: 326514 --- .../TestWatchpointMultipleThreads.py | 85 ++++++------------- .../watchpoint/multiple_threads/main.cpp | 76 ++++------------- 2 files changed, 41 insertions(+), 120 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py b/lldb/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py index c0be20d058f2..85d6c84d68ff 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py @@ -17,51 +17,26 @@ from lldbsuite.test import lldbutil class WatchpointForMultipleThreadsTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + main_spec = lldb.SBFileSpec("main.cpp", False) @expectedFailureAll( oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") - def test_watchpoint_multiple_threads(self): - """Test that lldb watchpoint works for multiple threads.""" - self.build() - self.setTearDownCleanup() - self.hello_multiple_threads() + def test_watchpoint_before_thread_start(self): + """Test that we can hit a watchpoint we set before starting another thread""" + self.do_watchpoint_test("Before running the thread") @expectedFailureAll( oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") - def test_watchpoint_multiple_threads_wp_set_and_then_delete(self): - """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires.""" + def test_watchpoint_after_thread_start(self): + """Test that we can hit a watchpoint we set after starting another thread""" + self.do_watchpoint_test("After running the thread") + + def do_watchpoint_test(self, line): self.build() - self.setTearDownCleanup() - self.hello_multiple_threads_wp_set_and_then_delete() - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Our simple source filename. - self.source = 'main.cpp' - # Find the line number to break inside main(). - self.first_stop = line_number( - self.source, '// Set break point at this line') - - def hello_multiple_threads(self): - """Test that lldb watchpoint works for multiple threads.""" - self.runCmd("file " + self.getBuildArtifact("a.out"), - CURRENT_EXECUTABLE_SET) - - # Add a breakpoint to set a watchpoint when stopped on the breakpoint. - lldbutil.run_break_set_by_file_and_line( - self, None, self.first_stop, num_expected_locations=1) - - # Run the program. - self.runCmd("run", RUN_SUCCEEDED) - - # We should be stopped again due to the breakpoint. - # The stop reason of the thread should be breakpoint. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, - substrs=['stopped', - 'stop reason = breakpoint']) + lldbutil.run_to_source_breakpoint(self, line, self.main_spec) # Now let's set a write-type watchpoint for variable 'g_val'. self.expect( @@ -77,39 +52,29 @@ class WatchpointForMultipleThreadsTestCase(TestBase): self.expect("watchpoint list -v", substrs=['hit_count = 0']) - while True: - self.runCmd("process continue") + self.runCmd("process continue") - self.runCmd("thread list") - if "stop reason = watchpoint" in self.res.GetOutput(): - # Good, we verified that the watchpoint works! - self.runCmd("thread backtrace all") - break - else: - self.fail("The stop reason should be either break or watchpoint") + self.runCmd("thread list") + if "stop reason = watchpoint" in self.res.GetOutput(): + # Good, we verified that the watchpoint works! + self.runCmd("thread backtrace all") + else: + self.fail("The stop reason should be either break or watchpoint") # Use the '-v' option to do verbose listing of the watchpoint. # The hit count should now be 1. self.expect("watchpoint list -v", substrs=['hit_count = 1']) - def hello_multiple_threads_wp_set_and_then_delete(self): + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + def test_watchpoint_multiple_threads_wp_set_and_then_delete(self): """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires.""" - self.runCmd("file " + self.getBuildArtifact("a.out"), - CURRENT_EXECUTABLE_SET) + self.build() + self.setTearDownCleanup() - # Add a breakpoint to set a watchpoint when stopped on the breakpoint. - lldbutil.run_break_set_by_file_and_line( - self, None, self.first_stop, num_expected_locations=1) - - # Run the program. - self.runCmd("run", RUN_SUCCEEDED) - - # We should be stopped again due to the breakpoint. - # The stop reason of the thread should be breakpoint. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, - substrs=['stopped', - 'stop reason = breakpoint']) + lldbutil.run_to_source_breakpoint(self, "After running the thread", self.main_spec) # Now let's set a write-type watchpoint for variable 'g_val'. self.expect( diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/main.cpp index 7f2e5e6e6cb5..1bfc3b2538b2 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/main.cpp @@ -7,73 +7,29 @@ // //===----------------------------------------------------------------------===// -#include +#include "pseudo_barrier.h" #include -#include -#include #include -std::default_random_engine g_random_engine{std::random_device{}()}; -std::uniform_int_distribution<> g_distribution{0, 3000000}; +volatile uint32_t g_val = 0; +pseudo_barrier_t g_barrier; -uint32_t g_val = 0; - - -uint32_t -access_pool (bool flag = false) -{ - static std::mutex g_access_mutex; - g_access_mutex.lock(); - - uint32_t old_val = g_val; - if (flag) - { - printf("changing g_val to %d...\n", old_val + 1); - g_val = old_val + 1; - } - - g_access_mutex.unlock(); - return g_val; +void thread_func() { + pseudo_barrier_wait(g_barrier); + printf("%s starting...\n", __FUNCTION__); + for (uint32_t i = 0; i < 10; ++i) + g_val = i; } -void -thread_func (uint32_t thread_index) -{ - printf ("%s (thread index = %u) starting...\n", __FUNCTION__, thread_index); +int main(int argc, char const *argv[]) { + printf("Before running the thread\n"); + pseudo_barrier_init(g_barrier, 2); + std::thread thread(thread_func); - uint32_t count = 0; - uint32_t val; - while (count++ < 15) - { - // random micro second sleep from zero to 3 seconds - int usec = g_distribution(g_random_engine); - printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec); - std::this_thread::sleep_for(std::chrono::microseconds{usec}); + printf("After running the thread\n"); + pseudo_barrier_wait(g_barrier); - if (count < 7) - val = access_pool (); - else - val = access_pool (true); + thread.join(); - printf ("%s (thread = %u) after usleep access_pool returns %d (count=%d)...\n", __FUNCTION__, thread_index, val, count); - } - printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index); -} - - -int main (int argc, char const *argv[]) -{ - std::thread threads[3]; - - printf ("Before turning all three threads loose...\n"); // Set break point at this line, - // in order to set our watchpoint. - // Create 3 threads - for (auto &thread : threads) - thread = std::thread{thread_func, std::distance(threads, &thread)}; - - // Join all of our threads - for (auto &thread : threads) - thread.join(); - - return 0; + return 0; }