summaryrefslogtreecommitdiffstats
path: root/lldb/packages/Python/lldbsuite/test
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/packages/Python/lldbsuite/test')
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py74
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/main.cpp26
2 files changed, 86 insertions, 14 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py
index 094c8670596..85fa5d380cf 100644
--- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py
@@ -19,10 +19,11 @@ class NumberOfThreadsTestCase(TestBase):
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
- # Find the line number to break inside main().
- self.line = line_number('main.cpp', '// Set break point at this line.')
+ # Find the line numbers for our break points.
+ self.thread3_notify_all_line = line_number('main.cpp', '// Set thread3 break point on notify_all at this line.')
+ self.thread3_before_lock_line = line_number('main.cpp', '// Set thread3 break point on lock at this line.')
- def test(self):
+ def test_number_of_threads(self):
"""Test number of threads."""
self.build()
exe = os.path.join(os.getcwd(), "a.out")
@@ -30,15 +31,15 @@ class NumberOfThreadsTestCase(TestBase):
# This should create a breakpoint with 1 location.
lldbutil.run_break_set_by_file_and_line(
- self, "main.cpp", self.line, num_expected_locations=1)
+ self, "main.cpp", self.thread3_notify_all_line, num_expected_locations=1)
- # The breakpoint list should show 3 locations.
+ # The breakpoint list should show 1 location.
self.expect(
"breakpoint list -f",
"Breakpoint location shown correctly",
substrs=[
"1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" %
- self.line])
+ self.thread3_notify_all_line])
# Run the program.
self.runCmd("run", RUN_SUCCEEDED)
@@ -57,5 +58,64 @@ class NumberOfThreadsTestCase(TestBase):
# Using std::thread may involve extra threads, so we assert that there are
# at least 4 rather than exactly 4.
self.assertTrue(
- num_threads >= 4,
+ num_threads >= 13,
'Number of expected threads and actual threads do not match.')
+
+ def test_unique_stacks(self):
+ """Test backtrace unique with multiple threads executing the same stack."""
+ self.build()
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ # Set a break point on the thread3 notify all (should get hit on threads 4-13).
+ lldbutil.run_break_set_by_file_and_line(
+ self, "main.cpp", self.thread3_before_lock_line, num_expected_locations=1)
+
+ # Run the program.
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ # Stopped once.
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs=["stop reason = breakpoint 1."])
+
+ process = self.process()
+
+ # Get the number of threads
+ num_threads = process.GetNumThreads()
+
+ # Using std::thread may involve extra threads, so we assert that there are
+ # at least 10 thread3's rather than exactly 10.
+ self.assertTrue(
+ num_threads >= 10,
+ 'Number of expected threads and actual threads do not match.')
+
+ # Attempt to walk each of the thread's executing the thread3 function to
+ # the same breakpoint.
+ def is_thread3(thread):
+ for frame in thread:
+ if "thread3" in frame.GetFunctionName(): return True
+ return False
+
+ expect_threads = ""
+ for i in range(num_threads):
+ thread = process.GetThreadAtIndex(i)
+ self.assertTrue(thread.IsValid())
+ if not is_thread3(thread):
+ continue
+
+ # If we aren't stopped out the thread breakpoint try to resume.
+ if thread.GetStopReason() != lldb.eStopReasonBreakpoint:
+ self.runCmd("thread continue %d"%(i+1))
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonBreakpoint)
+
+ expect_threads += " #%d"%(i+1)
+
+ # Construct our expected back trace string
+ expect_string = "10 thread(s)%s" % (expect_threads)
+
+ # Now that we are stopped, we should have 10 threads waiting in the
+ # thread3 function. All of these threads should show as one stack.
+ self.expect("thread backtrace unique",
+ "Backtrace with unique stack shown correctly",
+ substrs=[expect_string,
+ "main.cpp:%d"%self.thread3_before_lock_line])
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/main.cpp
index 6a0ea4e0d11..42a07f35303 100644
--- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/main.cpp
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/main.cpp
@@ -1,15 +1,19 @@
+#include "pseudo_barrier.h"
#include <condition_variable>
#include <mutex>
#include <thread>
+#include <vector>
std::mutex mutex;
std::condition_variable cond;
+pseudo_barrier_t thread3_barrier;
void *
thread3(void *input)
{
- std::unique_lock<std::mutex> lock(mutex);
- cond.notify_all(); // Set break point at this line.
+ pseudo_barrier_wait(thread3_barrier);
+ std::unique_lock<std::mutex> lock(mutex); // Set thread3 break point on lock at this line.
+ cond.notify_all(); // Set thread3 break point on notify_all at this line.
return NULL;
}
@@ -17,7 +21,7 @@ void *
thread2(void *input)
{
std::unique_lock<std::mutex> lock(mutex);
- cond.notify_all();
+ cond.notify_all(); // release main thread
cond.wait(lock);
return NULL;
}
@@ -36,15 +40,23 @@ int main()
std::unique_lock<std::mutex> lock(mutex);
std::thread thread_1(thread1, nullptr);
- cond.wait(lock);
+ cond.wait(lock); // wait for thread2
- std::thread thread_3(thread3, nullptr);
- cond.wait(lock);
+ pseudo_barrier_init(thread3_barrier, 10);
+
+ std::vector<std::thread> thread_3s;
+ for (int i = 0; i < 10; i++) {
+ thread_3s.push_back(std::thread(thread3, nullptr));
+ }
+
+ cond.wait(lock); // wait for thread_3s
lock.unlock();
thread_1.join();
- thread_3.join();
+ for (auto &t : thread_3s){
+ t.join();
+ }
return 0;
}
OpenPOWER on IntegriCloud