aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lldb/test/functionalities/thread/create_during_instruction_step/main.cpp36
-rw-r--r--lldb/test/linux/thread/create_during_instruction_step/Makefile (renamed from lldb/test/functionalities/thread/create_during_instruction_step/Makefile)0
-rw-r--r--lldb/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py (renamed from lldb/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py)33
-rw-r--r--lldb/test/linux/thread/create_during_instruction_step/main.cpp55
4 files changed, 64 insertions, 60 deletions
diff --git a/lldb/test/functionalities/thread/create_during_instruction_step/main.cpp b/lldb/test/functionalities/thread/create_during_instruction_step/main.cpp
deleted file mode 100644
index c50ce47..0000000
--- a/lldb/test/functionalities/thread/create_during_instruction_step/main.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-//===-- main.cpp ------------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <atomic>
-#include <thread>
-
-std::atomic<bool> flag(false);
-
-void do_nothing()
-{
- while (flag)
- ;
-}
-
-int main ()
-{
- // Instruction-level stepping over a creation of the first thread takes a very long time, so
- // we give the threading machinery a chance to initialize all its data structures.
- // This way, stepping over the second thread will be much faster.
- std::thread dummy(do_nothing);
- dummy.join();
-
- // Make sure the new thread does not exit before we get a chance to notice the main thread stopped
- flag = true;
-
- std::thread thread(do_nothing); // Set breakpoint here
- flag = false; // Release the new thread.
- thread.join();
- return 0;
-}
diff --git a/lldb/test/functionalities/thread/create_during_instruction_step/Makefile b/lldb/test/linux/thread/create_during_instruction_step/Makefile
index 67aa166..67aa166 100644
--- a/lldb/test/functionalities/thread/create_during_instruction_step/Makefile
+++ b/lldb/test/linux/thread/create_during_instruction_step/Makefile
diff --git a/lldb/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py b/lldb/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py
index 6135359c..e6fc428 100644
--- a/lldb/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py
+++ b/lldb/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py
@@ -16,8 +16,6 @@ class CreateDuringInstructionStepTestCase(TestBase):
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
- # Find the line numbers to break and continue.
- self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
@dsym_test
def test_step_inst_with_dsym(self):
@@ -25,8 +23,6 @@ class CreateDuringInstructionStepTestCase(TestBase):
self.create_during_step_inst_test()
@dwarf_test
- @skipIfTargetAndroid(archs=['aarch64'])
- @expectedFailureAndroid("llvm.org/pr23944", archs=['aarch64']) # We are unable to step through std::thread::_M_start_thread
def test_step_inst_with_dwarf(self):
self.buildDwarf(dictionary=self.getBuildFlags())
self.create_during_step_inst_test()
@@ -37,7 +33,8 @@ class CreateDuringInstructionStepTestCase(TestBase):
self.assertTrue(target and target.IsValid(), "Target is valid")
# This should create a breakpoint in the stepping thread.
- self.bp_num = lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=-1)
+ breakpoint = target.BreakpointCreateByName("main")
+ self.assertTrue(breakpoint and breakpoint.IsValid(), "Breakpoint is valid")
# Run the program.
process = target.LaunchSimple(None, None, self.get_process_working_directory())
@@ -45,31 +42,19 @@ class CreateDuringInstructionStepTestCase(TestBase):
# The stop reason of the thread should be breakpoint.
self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- self.assertEqual(lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint).IsValid(), 1,
- STOPPED_DUE_TO_BREAKPOINT)
- # Get the number of threads
- num_threads = process.GetNumThreads()
+ threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint)
+ self.assertEquals(len(threads), 1, STOPPED_DUE_TO_BREAKPOINT)
- # Make sure we see only one threads
- self.assertEqual(num_threads, 1, 'Number of expected threads and actual threads do not match.')
-
- thread = process.GetThreadAtIndex(0)
+ thread = threads[0]
self.assertTrue(thread and thread.IsValid(), "Thread is valid")
+ # Make sure we see only one threads
+ self.assertEqual(process.GetNumThreads(), 1, 'Number of expected threads and actual threads do not match.')
+
# Keep stepping until we see the thread creation
while process.GetNumThreads() < 2:
- # This skips some functions we have trouble stepping into. Testing stepping
- # through these is not the purpose of this test. We just want to find the
- # instruction, which creates the thread.
- if thread.GetFrameAtIndex(0).GetFunctionName() in [
- '__sync_fetch_and_add_4', # Android arm: unable to set a breakpoint for software single-step
- 'pthread_mutex_lock', # Android arm: function contains atomic instruction sequences
- 'pthread_mutex_unlock' # Android arm: function contains atomic instruction sequences
- ]:
- thread.StepOut()
- else:
- thread.StepInstruction(False)
+ thread.StepInstruction(False)
self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
self.assertEqual(thread.GetStopReason(), lldb.eStopReasonPlanComplete, "Step operation succeeded")
if self.TraceOn():
diff --git a/lldb/test/linux/thread/create_during_instruction_step/main.cpp b/lldb/test/linux/thread/create_during_instruction_step/main.cpp
new file mode 100644
index 0000000..168575e
--- /dev/null
+++ b/lldb/test/linux/thread/create_during_instruction_step/main.cpp
@@ -0,0 +1,55 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// This file deliberately uses low level linux-specific API for thread creation because:
+// - instruction-stepping over thread creation using higher-level functions was very slow
+// - it was also unreliable due to single-stepping bugs unrelated to this test
+// - some threading libraries do not create or destroy threads when we would expect them to
+
+#include <sched.h>
+
+#include <atomic>
+#include <cstdio>
+
+enum { STACK_SIZE = 0x2000 };
+
+static uint8_t child_stack[STACK_SIZE];
+
+pid_t child_tid;
+
+std::atomic<bool> flag(false);
+
+int thread_main(void *)
+{
+ while (! flag) // Make sure the thread does not exit prematurely
+ ;
+
+ return 0;
+}
+
+int main ()
+{
+ int ret = clone(thread_main,
+ child_stack + STACK_SIZE/2, // Don't care whether the stack grows up or down,
+ // just point to the middle
+ CLONE_CHILD_CLEARTID | CLONE_FILES | CLONE_FS | CLONE_PARENT_SETTID | CLONE_SETTLS |
+ CLONE_SIGHAND | CLONE_SYSVSEM | CLONE_THREAD | CLONE_VM,
+ nullptr, // thread_main argument
+ &child_tid);
+
+ if (ret == -1)
+ {
+ perror("clone");
+ return 1;
+ }
+
+ flag = true;
+
+ return 0;
+}