labath created this revision.
labath added a reviewer: tberghammer.
labath added a subscriber: lldb-commits.
Herald added subscribers: srhines, danalbert, tberghammer.

There were a number of issues about the way I have designed this test 
originally:
- it relied on single-stepping through large parts of code, which was slow and 
unreliable
- the threading libraries interfered with the exact thing we wanted to test

For this reason, I have rewritted the test using low-level linux api, which 
allows the test to be
much more focused. The functionality for other platforms will need to be tested 
separately.

http://reviews.llvm.org/D12280

Files:
  test/functionalities/thread/create_during_instruction_step/Makefile
  
test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py
  test/functionalities/thread/create_during_instruction_step/main.cpp
  test/linux/create_during_instruction_step/Makefile
  test/linux/create_during_instruction_step/TestCreateDuringInstructionStep.py
  test/linux/create_during_instruction_step/main.cpp

Index: test/linux/create_during_instruction_step/main.cpp
===================================================================
--- /dev/null
+++ test/linux/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 child 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;
+}
Index: test/linux/create_during_instruction_step/TestCreateDuringInstructionStep.py
===================================================================
--- test/linux/create_during_instruction_step/TestCreateDuringInstructionStep.py
+++ test/linux/create_during_instruction_step/TestCreateDuringInstructionStep.py
@@ -16,17 +16,13 @@
     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):
         self.buildDsym(dictionary=self.getBuildFlags())
         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,39 +33,28 @@
         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())
         self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
 
         # 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():
Index: test/linux/create_during_instruction_step/Makefile
===================================================================
--- test/linux/create_during_instruction_step/Makefile
+++ test/linux/create_during_instruction_step/Makefile
@@ -1,4 +1,4 @@
-LEVEL = ../../../make
+LEVEL = ../../make
 
 CXX_SOURCES := main.cpp
 ENABLE_THREADS := YES
Index: test/functionalities/thread/create_during_instruction_step/main.cpp
===================================================================
--- 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;
-}
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to