Adding support for stopping all threads of multithreaded inferiors on Linux.  Also adding multithreaded test cases.
llvm-svn: 182809
diff --git a/lldb/test/functionalities/thread/break_after_join/Makefile b/lldb/test/functionalities/thread/break_after_join/Makefile
new file mode 100644
index 0000000..26db481
--- /dev/null
+++ b/lldb/test/functionalities/thread/break_after_join/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/functionalities/thread/break_after_join/TestBreakAfterJoin.py b/lldb/test/functionalities/thread/break_after_join/TestBreakAfterJoin.py
new file mode 100644
index 0000000..9bc14f0
--- /dev/null
+++ b/lldb/test/functionalities/thread/break_after_join/TestBreakAfterJoin.py
@@ -0,0 +1,102 @@
+"""
+Test number of threads.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+import lldbutil
+
+class BreakpointAfterJoinTestCase(TestBase):
+
+    mydir = os.path.join("functionalities", "thread", "break_after_join")
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @dsym_test
+    def test_with_dsym(self):
+        """Test breakpoint handling after a thread join."""
+        self.buildDsym(dictionary=self.getBuildFlags())
+        self.breakpoint_after_join_test()
+
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @skipIfLinux # Fails intermittently, llvm.org/pr16170"
+    @dwarf_test
+    def test_with_dwarf(self):
+        """Test breakpoint handling after a thread join."""
+        self.buildDwarf(dictionary=self.getBuildFlags())
+        self.breakpoint_after_join_test()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Find the line number for our breakpoint.
+        self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
+
+    def breakpoint_after_join_test(self):
+        """Test breakpoint handling after a thread join."""
+        exe = os.path.join(os.getcwd(), "a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # This should create a breakpoint in the main thread.
+        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=1)
+
+        # The breakpoint list should show 1 location.
+        self.expect("breakpoint list -f", "Breakpoint location shown correctly",
+            substrs = ["1: file ='main.cpp', line = %d, locations = 1" % self.breakpoint])
+
+        # Run the program.
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped',
+                       'stop reason = breakpoint'])
+
+        # Get the target process
+        target = self.dbg.GetSelectedTarget()
+        process = target.GetProcess()
+
+        # The exit probably occured during breakpoint handling, but it isn't
+        # guaranteed.  The main thing we're testing here is that the debugger
+        # handles this cleanly is some way.
+
+        # Get the number of threads
+        num_threads = process.GetNumThreads()
+
+        # Make sure we see six threads
+        self.assertTrue(num_threads == 6, 'Number of expected threads and actual threads do not match.')
+
+        # Get the thread objects
+        thread1 = process.GetThreadAtIndex(0)
+        thread2 = process.GetThreadAtIndex(1)
+        thread3 = process.GetThreadAtIndex(2)
+        thread4 = process.GetThreadAtIndex(3)
+        thread5 = process.GetThreadAtIndex(4)
+        thread6 = process.GetThreadAtIndex(5)
+
+        # Make sure all threads are stopped
+        self.assertTrue(thread1.IsStopped(), "Thread 1 didn't stop during breakpoint")
+        self.assertTrue(thread2.IsStopped(), "Thread 2 didn't stop during breakpoint")
+        self.assertTrue(thread3.IsStopped(), "Thread 3 didn't stop during breakpoint")
+        self.assertTrue(thread4.IsStopped(), "Thread 4 didn't stop during breakpoint")
+        self.assertTrue(thread5.IsStopped(), "Thread 5 didn't stop during breakpoint")
+        self.assertTrue(thread6.IsStopped(), "Thread 6 didn't stop during breakpoint")
+
+        # Run to completion
+        self.runCmd("continue")
+
+        # If the process hasn't exited, collect some information
+        if process.GetState() != lldb.eStateExited:
+            self.runCmd("thread list")
+            self.runCmd("process status")
+
+        # At this point, the inferior process should have exited.
+        self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()
diff --git a/lldb/test/functionalities/thread/break_after_join/main.cpp b/lldb/test/functionalities/thread/break_after_join/main.cpp
new file mode 100644
index 0000000..9764976
--- /dev/null
+++ b/lldb/test/functionalities/thread/break_after_join/main.cpp
@@ -0,0 +1,125 @@
+//===-- 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 test is intended to create a situation in which one thread will exit
+// while a breakpoint is being handled in another thread.  This may not always
+// happen because it's possible that the exiting thread will exit before the
+// breakpoint is hit.  The test case should be flexible enough to treat that
+// as success.
+
+#include <pthread.h>
+#include <unistd.h>
+#include <atomic>
+
+volatile int g_test = 0;
+
+// Note that although hogging the CPU while waiting for a variable to change
+// would be terrible in production code, it's great for testing since it
+// avoids a lot of messy context switching to get multiple threads synchronized.
+#define do_nothing()  
+
+#define pseudo_barrier_wait(bar) \
+    --bar;                       \
+    while (bar > 0)              \
+        do_nothing();
+
+#define pseudo_barrier_init(bar, count) (bar = count)
+
+// A barrier to synchronize all the threads.
+std::atomic_int g_barrier1;
+
+// A barrier to keep the threads from exiting until after the breakpoint has
+// been passed.
+std::atomic_int g_barrier2;
+
+void *
+break_thread_func (void *input)
+{
+    // Wait until all the threads are running
+    pseudo_barrier_wait(g_barrier1);
+
+    // Wait for the join thread to join
+    usleep(50);
+
+    // Do something
+    g_test++;       // Set breakpoint here
+
+    // Synchronize after the breakpoint
+    pseudo_barrier_wait(g_barrier2);
+
+    // Return
+    return NULL;
+}
+
+void *
+wait_thread_func (void *input)
+{
+    // Wait until the entire first group of threads is running
+    pseudo_barrier_wait(g_barrier1);
+
+    // Wait until the breakpoint has been passed
+    pseudo_barrier_wait(g_barrier2);
+
+    // Return
+    return NULL;
+}
+
+void *
+join_thread_func (void *input)
+{
+    pthread_t *thread_to_join = (pthread_t*)input;
+
+    // Sync up with the rest of the threads.
+    pseudo_barrier_wait(g_barrier1);
+
+    // Join the other thread
+    pthread_join(*thread_to_join, NULL);
+
+    // Return
+    return NULL;
+}
+
+int main ()
+{
+    pthread_t thread_1;
+    pthread_t thread_2;
+    pthread_t thread_3;
+    pthread_t thread_4;
+    pthread_t thread_5;
+
+    // The first barrier waits for the non-joining threads to start.
+    // This thread will also participate in that barrier.
+    // The idea here is to guarantee that the joining thread will be
+    // last in the internal list maintained by the debugger.
+    pseudo_barrier_init(g_barrier1, 5);
+
+    // The second barrier keeps the waiting threads around until the breakpoint
+    // has been passed.
+    pseudo_barrier_init(g_barrier2, 4);
+
+    // Create a thread to hit the breakpoint
+    pthread_create (&thread_1, NULL, break_thread_func, NULL);
+
+    // Create more threads to slow the debugger down during processing.
+    pthread_create (&thread_2, NULL, wait_thread_func, NULL);
+    pthread_create (&thread_3, NULL, wait_thread_func, NULL);
+    pthread_create (&thread_4, NULL, wait_thread_func, NULL);
+
+    // Create a thread to join the breakpoint thread
+    pthread_create (&thread_5, NULL, join_thread_func, &thread_4);
+
+    // Wait for the threads to finish
+    pthread_join(thread_5, NULL);
+    pthread_join(thread_4, NULL);
+    pthread_join(thread_3, NULL);
+    pthread_join(thread_2, NULL);
+    pthread_join(thread_1, NULL);
+
+    return 0;
+}
diff --git a/lldb/test/functionalities/thread/create_during_step/Makefile b/lldb/test/functionalities/thread/create_during_step/Makefile
new file mode 100644
index 0000000..26db481
--- /dev/null
+++ b/lldb/test/functionalities/thread/create_during_step/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/functionalities/thread/create_during_step/TestCreateDuringStep.py b/lldb/test/functionalities/thread/create_during_step/TestCreateDuringStep.py
new file mode 100644
index 0000000..e2010f0
--- /dev/null
+++ b/lldb/test/functionalities/thread/create_during_step/TestCreateDuringStep.py
@@ -0,0 +1,157 @@
+"""
+Test number of threads.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+import lldbutil
+
+class CreateDuringStepTestCase(TestBase):
+
+    mydir = os.path.join("functionalities", "thread", "create_during_step")
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @dsym_test
+    def test_step_inst_with_dsym(self):
+        """Test thread creation during step-inst handling."""
+        self.buildDsym(dictionary=self.getBuildFlags())
+        self.create_during_step_inst_test()
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @dsym_test
+    def test_step_over_with_dsym(self):
+        """Test thread creation during step-over handling."""
+        self.buildDsym(dictionary=self.getBuildFlags())
+        self.create_during_step_over_test()
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @dsym_test
+    def test_step_in_with_dsym(self):
+        """Test thread creation during step-in handling."""
+        self.buildDsym(dictionary=self.getBuildFlags())
+        self.create_during_step_in_test()
+
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @dwarf_test
+    def test_step_inst_with_dwarf(self):
+        """Test thread creation during step-inst handling."""
+        self.buildDwarf(dictionary=self.getBuildFlags())
+        self.create_during_step_inst_test()
+
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @expectedFailureLinux("llvm.org/pr16171") # step in/over don't behave in the multithreaded case
+    @dwarf_test
+    def test_step_over_with_dwarf(self):
+        """Test thread creation during step-over handling."""
+        self.buildDwarf(dictionary=self.getBuildFlags())
+        self.create_during_step_over_test()
+
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @expectedFailureLinux("llvm.org/pr16171") # step in/over don't behave in the multithreaded case
+    @dwarf_test
+    def test_step_in_with_dwarf(self):
+        """Test thread creation during step-in handling."""
+        self.buildDwarf(dictionary=self.getBuildFlags())
+        self.create_during_step_in_test()
+
+    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')
+        self.continuepoint = line_number('main.cpp', '// Continue from here')
+
+    def create_during_step_inst_test(self):
+        """Test thread creation while using step-inst."""
+        self.create_during_step_base("thread step-inst -m all-threads")
+
+    def create_during_step_over_test(self):
+        """Test thread creation while using step-over."""
+        self.create_during_step_base("thread step-over -m all-threads")
+
+    def create_during_step_in_test(self):
+        """Test thread creation while using step-in."""
+        self.create_during_step_base("thread step-in -m all-threads")
+
+    def create_during_step_base(self, step_cmd):
+        """Test thread creation while using step-in."""
+        exe = os.path.join(os.getcwd(), "a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # This should create a breakpoint in the stepping thread.
+        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=1)
+
+        # The breakpoint list should show 1 location.
+        self.expect("breakpoint list -f", "Breakpoint location shown correctly",
+            substrs = ["1: file ='main.cpp', line = %d, locations = 1" % self.breakpoint])
+
+        # Run the program.
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped',
+                       'stop reason = breakpoint'])
+
+        # Get the target process
+        target = self.dbg.GetSelectedTarget()
+        process = target.GetProcess()
+
+        # Get the number of threads
+        num_threads = process.GetNumThreads()
+
+        # Make sure we see only two threads
+        self.assertTrue(num_threads == 2, 'Number of expected threads and actual threads do not match.')
+
+        # Get the thread objects
+        thread1 = process.GetThreadAtIndex(0)
+        thread2 = process.GetThreadAtIndex(1)
+
+        # Make sure both threads are stopped
+        self.assertTrue(thread1.IsStopped(), "Thread 1 didn't stop during breakpoint")
+        self.assertTrue(thread2.IsStopped(), "Thread 2 didn't stop during breakpoint")
+
+        # Keep stepping until we've reached our designated continue point
+        stepping_thread = process.GetSelectedThread()
+        current_line = self.breakpoint
+        while current_line != self.continuepoint:
+            self.runCmd(step_cmd)
+
+            # The thread creation may change the selected thread.
+            # If it does, we just change it back here.
+            if stepping_thread != process.GetSelectedThread():
+                process.SetSelectedThread(stepping_thread)
+
+            frame = stepping_thread.GetFrameAtIndex(0)
+            current_line = frame.GetLineEntry().GetLine()
+
+            # Make sure we're still where we thought we were
+            self.assertTrue(current_line >= self.breakpoint, "Stepped to unexpected line, " + str(current_line))
+            self.assertTrue(current_line <= self.continuepoint, "Stepped to unexpected line, " + str(current_line))
+
+        # Update the number of threads
+        num_threads = process.GetNumThreads()
+
+        # Check to see that we increased the number of threads as expected
+        self.assertTrue(num_threads == 3, 'Number of expected threads and actual threads do not match after thread exit.')
+
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+                substrs = ['stopped',
+                           'top reason = instruction step int'])
+
+        # Run to completion
+        self.runCmd("process continue")
+
+        # At this point, the inferior process should have exited.
+        self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()
diff --git a/lldb/test/functionalities/thread/create_during_step/main.cpp b/lldb/test/functionalities/thread/create_during_step/main.cpp
new file mode 100644
index 0000000..f64831b
--- /dev/null
+++ b/lldb/test/functionalities/thread/create_during_step/main.cpp
@@ -0,0 +1,92 @@
+//===-- 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 test is intended to create a situation in which one thread will be
+// created while a the debugger is stepping in another thread.
+
+#include <pthread.h>
+#include <atomic>
+
+// Note that although hogging the CPU while waiting for a variable to change
+// would be terrible in production code, it's great for testing since it
+// avoids a lot of messy context switching to get multiple threads synchronized.
+#define do_nothing()
+
+#define pseudo_barrier_wait(bar) \
+    --bar;                       \
+    while (bar > 0)              \
+        do_nothing();
+
+#define pseudo_barrier_init(bar, count) (bar = count)
+
+std::atomic_int g_barrier;
+
+volatile int g_thread_created = 0;
+volatile int g_test = 0;
+
+void *
+step_thread_func (void *input)
+{
+    g_test = 0;         // Set breakpoint here
+
+    while (!g_thread_created)
+        g_test++;
+
+    // One more time to provide a continue point
+    g_test++;           // Continue from here
+
+    // Return
+    return NULL;
+}
+
+void *
+create_thread_func (void *input)
+{
+    pthread_t *step_thread = (pthread_t*)input;
+
+    // Wait until the main thread knows this thread is started.
+    pseudo_barrier_wait(g_barrier);
+
+    // Wait until the other thread is done.
+    pthread_join(*step_thread, NULL);
+
+    // Return
+    return NULL;
+}
+
+int main ()
+{
+    pthread_t thread_1;
+    pthread_t thread_2;
+
+    // Use a simple count to simulate a barrier.
+    pseudo_barrier_init(g_barrier, 2);
+
+    // Create a thread to hit the breakpoint.
+    pthread_create (&thread_1, NULL, step_thread_func, NULL);
+
+    // Wait until the step thread is stepping
+    while (g_test < 1)
+        do_nothing();
+
+    // Create a thread to exit while we're stepping.
+    pthread_create (&thread_2, NULL, create_thread_func, &thread_1);
+
+    // Wait until that thread is started
+    pseudo_barrier_wait(g_barrier);
+
+    // Let the stepping thread know the other thread is there
+    g_thread_created = 1;
+
+    // Wait for the threads to finish.
+    pthread_join(thread_2, NULL);
+    pthread_join(thread_1, NULL);
+
+    return 0;
+}
diff --git a/lldb/test/functionalities/thread/exit_during_break/Makefile b/lldb/test/functionalities/thread/exit_during_break/Makefile
new file mode 100644
index 0000000..26db481
--- /dev/null
+++ b/lldb/test/functionalities/thread/exit_during_break/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py b/lldb/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py
new file mode 100644
index 0000000..7c0a29b
--- /dev/null
+++ b/lldb/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py
@@ -0,0 +1,94 @@
+"""
+Test number of threads.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+import lldbutil
+
+class ExitDuringBreakpointTestCase(TestBase):
+
+    mydir = os.path.join("functionalities", "thread", "exit_during_break")
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @dsym_test
+    def test_with_dsym(self):
+        """Test thread exit during breakpoint handling."""
+        self.buildDsym(dictionary=self.getBuildFlags())
+        self.exit_during_breakpoint_test()
+
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @dwarf_test
+    def test_with_dwarf(self):
+        """Test thread exit during breakpoint handling."""
+        self.buildDwarf(dictionary=self.getBuildFlags())
+        self.exit_during_breakpoint_test()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Find the line number for our breakpoint.
+        self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
+
+    def exit_during_breakpoint_test(self):
+        """Test thread exit during breakpoint handling."""
+        exe = os.path.join(os.getcwd(), "a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # This should create a breakpoint in the main thread.
+        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=1)
+
+        # The breakpoint list should show 1 location.
+        self.expect("breakpoint list -f", "Breakpoint location shown correctly",
+            substrs = ["1: file ='main.cpp', line = %d, locations = 1" % self.breakpoint])
+
+        # Run the program.
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped',
+                       'stop reason = breakpoint'])
+
+        # Get the target process
+        target = self.dbg.GetSelectedTarget()
+        process = target.GetProcess()
+
+        # The exit probably occured during breakpoint handling, but it isn't
+        # guaranteed.  The main thing we're testing here is that the debugger
+        # handles this cleanly is some way.
+
+        # Get the number of threads
+        num_threads = process.GetNumThreads()
+
+        # Make sure we see at least five threads
+        self.assertTrue(num_threads >= 5, 'Number of expected threads and actual threads do not match.')
+
+        # Get the thread objects
+        thread1 = process.GetThreadAtIndex(0)
+        thread2 = process.GetThreadAtIndex(1)
+        thread3 = process.GetThreadAtIndex(2)
+        thread4 = process.GetThreadAtIndex(3)
+        thread5 = process.GetThreadAtIndex(4)
+
+        # Make sure all threads are stopped
+        self.assertTrue(thread1.IsStopped(), "Thread 1 didn't stop during breakpoint")
+        self.assertTrue(thread2.IsStopped(), "Thread 2 didn't stop during breakpoint")
+        self.assertTrue(thread3.IsStopped(), "Thread 3 didn't stop during breakpoint")
+        self.assertTrue(thread4.IsStopped(), "Thread 4 didn't stop during breakpoint")
+        self.assertTrue(thread5.IsStopped(), "Thread 5 didn't stop during breakpoint")
+
+        # Run to completion
+        self.runCmd("continue")
+
+        # At this point, the inferior process should have exited.
+        self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()
diff --git a/lldb/test/functionalities/thread/exit_during_break/main.cpp b/lldb/test/functionalities/thread/exit_during_break/main.cpp
new file mode 100644
index 0000000..f900194
--- /dev/null
+++ b/lldb/test/functionalities/thread/exit_during_break/main.cpp
@@ -0,0 +1,135 @@
+//===-- 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 test is intended to create a situation in which one thread will exit
+// while a breakpoint is being handled in another thread.  This may not always
+// happen because it's possible that the exiting thread will exit before the
+// breakpoint is hit.  The test case should be flexible enough to treat that
+// as success.
+
+#include <pthread.h>
+#include <unistd.h>
+#include <atomic>
+
+volatile int g_test = 0;
+
+// Note that although hogging the CPU while waiting for a variable to change
+// would be terrible in production code, it's great for testing since it
+// avoids a lot of messy context switching to get multiple threads synchronized.
+#define do_nothing()  
+
+#define pseudo_barrier_wait(bar) \
+    --bar;                       \
+    while (bar > 0)              \
+        do_nothing();
+
+#define pseudo_barrier_init(bar, count) (bar = count)
+
+// A barrier to synchronize all the threads except the one that will exit.
+std::atomic_int g_barrier1;
+
+// A barrier to synchronize all the threads including the one that will exit.
+std::atomic_int g_barrier2;
+
+// A barrier to keep the first group of threads from exiting until after the
+// breakpoint has been passed.
+std::atomic_int g_barrier3;
+
+void *
+break_thread_func (void *input)
+{
+    // Wait until the entire first group of threads is running
+    pseudo_barrier_wait(g_barrier1);
+
+    // Wait for the exiting thread to start
+    pseudo_barrier_wait(g_barrier2);
+
+    // Do something
+    g_test++;       // Set breakpoint here
+
+    // Synchronize after the breakpoint
+    pseudo_barrier_wait(g_barrier3);
+
+    // Return
+    return NULL;
+}
+
+void *
+wait_thread_func (void *input)
+{
+    // Wait until the entire first group of threads is running
+    pseudo_barrier_wait(g_barrier1);
+
+    // Wait for the exiting thread to start
+    pseudo_barrier_wait(g_barrier2);
+
+    // Wait until the breakpoint has been passed
+    pseudo_barrier_wait(g_barrier3);
+
+    // Return
+    return NULL;
+}
+
+void *
+exit_thread_func (void *input)
+{
+    // Sync up with the rest of the threads.
+    pseudo_barrier_wait(g_barrier2);
+
+    // Try to make sure this thread doesn't exit until the breakpoint is hit.
+    usleep(1);
+
+    // Return
+    return NULL;
+}
+
+int main ()
+{
+    pthread_t thread_1;
+    pthread_t thread_2;
+    pthread_t thread_3;
+    pthread_t thread_4;
+    pthread_t thread_5;
+
+    // The first barrier waits for the non-exiting threads to start.
+    // This thread will also participate in that barrier.
+    // The idea here is to guarantee that the exiting thread will be
+    // last in the internal list maintained by the debugger.
+    pseudo_barrier_init(g_barrier1, 5);
+
+    // The second break synchronyizes thread exection with the breakpoint.
+    pseudo_barrier_init(g_barrier2, 5);
+
+    // The third barrier keeps the waiting threads around until the breakpoint
+    // has been passed.
+    pseudo_barrier_init(g_barrier3, 4);
+
+    // Create a thread to hit the breakpoint
+    pthread_create (&thread_1, NULL, break_thread_func, NULL);
+
+    // Create more threads to slow the debugger down during processing.
+    pthread_create (&thread_2, NULL, wait_thread_func, NULL);
+    pthread_create (&thread_3, NULL, wait_thread_func, NULL);
+    pthread_create (&thread_4, NULL, wait_thread_func, NULL);
+
+    // Wait for all these threads to get started.
+    pseudo_barrier_wait(g_barrier1);
+
+    // Create a thread to exit during the breakpoint
+    pthread_create (&thread_5, NULL, exit_thread_func, NULL);
+
+    // Wait for the threads to finish
+    pthread_join(thread_5, NULL);
+    pthread_join(thread_4, NULL);
+    pthread_join(thread_3, NULL);
+    pthread_join(thread_2, NULL);
+    pthread_join(thread_1, NULL);
+
+    return 0;
+}
diff --git a/lldb/test/functionalities/thread/exit_during_break/main.d.23591 b/lldb/test/functionalities/thread/exit_during_break/main.d.23591
new file mode 100644
index 0000000..f5194df
--- /dev/null
+++ b/lldb/test/functionalities/thread/exit_during_break/main.d.23591
@@ -0,0 +1,39 @@
+main.o: main.cpp /usr/include/pthread.h /usr/include/features.h \
+  /usr/include/x86_64-linux-gnu/bits/predefs.h \
+  /usr/include/x86_64-linux-gnu/sys/cdefs.h \
+  /usr/include/x86_64-linux-gnu/bits/wordsize.h \
+  /usr/include/x86_64-linux-gnu/gnu/stubs.h \
+  /usr/include/x86_64-linux-gnu/gnu/stubs-64.h /usr/include/endian.h \
+  /usr/include/x86_64-linux-gnu/bits/endian.h \
+  /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/sched.h \
+  /usr/include/x86_64-linux-gnu/bits/types.h \
+  /usr/include/x86_64-linux-gnu/bits/typesizes.h \
+  /home/akaylor/clang-install/bin/../lib/clang/3.3/include/stddef.h \
+  /usr/include/time.h /usr/include/x86_64-linux-gnu/bits/sched.h \
+  /usr/include/x86_64-linux-gnu/bits/time.h \
+  /usr/include/x86_64-linux-gnu/bits/timex.h /usr/include/xlocale.h \
+  /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \
+  /usr/include/x86_64-linux-gnu/bits/setjmp.h /usr/include/stdio.h \
+  /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+  /home/akaylor/clang-install/bin/../lib/clang/3.3/include/stdarg.h \
+  /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
+  /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/unistd.h \
+  /usr/include/x86_64-linux-gnu/bits/posix_opt.h \
+  /usr/include/x86_64-linux-gnu/bits/environments.h \
+  /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \
+  /usr/include/x86_64-linux-gnu/sys/types.h \
+  /usr/include/x86_64-linux-gnu/sys/select.h \
+  /usr/include/x86_64-linux-gnu/bits/select.h \
+  /usr/include/x86_64-linux-gnu/bits/sigset.h \
+  /usr/include/x86_64-linux-gnu/sys/sysmacros.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/atomic \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/c++0x_warning.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/atomic_base.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/x86_64-linux-gnu/bits/c++config.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/x86_64-linux-gnu/bits/os_defines.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/x86_64-linux-gnu/bits/cpu_defines.h \
+  /home/akaylor/clang-install/bin/../lib/clang/3.3/include/stdbool.h \
+  /home/akaylor/clang-install/bin/../lib/clang/3.3/include/stdint.h \
+  /usr/include/stdint.h /usr/include/x86_64-linux-gnu/bits/wchar.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/atomic_0.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/atomic_2.h
diff --git a/lldb/test/functionalities/thread/exit_during_break/main.d.23604 b/lldb/test/functionalities/thread/exit_during_break/main.d.23604
new file mode 100644
index 0000000..f5194df
--- /dev/null
+++ b/lldb/test/functionalities/thread/exit_during_break/main.d.23604
@@ -0,0 +1,39 @@
+main.o: main.cpp /usr/include/pthread.h /usr/include/features.h \
+  /usr/include/x86_64-linux-gnu/bits/predefs.h \
+  /usr/include/x86_64-linux-gnu/sys/cdefs.h \
+  /usr/include/x86_64-linux-gnu/bits/wordsize.h \
+  /usr/include/x86_64-linux-gnu/gnu/stubs.h \
+  /usr/include/x86_64-linux-gnu/gnu/stubs-64.h /usr/include/endian.h \
+  /usr/include/x86_64-linux-gnu/bits/endian.h \
+  /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/sched.h \
+  /usr/include/x86_64-linux-gnu/bits/types.h \
+  /usr/include/x86_64-linux-gnu/bits/typesizes.h \
+  /home/akaylor/clang-install/bin/../lib/clang/3.3/include/stddef.h \
+  /usr/include/time.h /usr/include/x86_64-linux-gnu/bits/sched.h \
+  /usr/include/x86_64-linux-gnu/bits/time.h \
+  /usr/include/x86_64-linux-gnu/bits/timex.h /usr/include/xlocale.h \
+  /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \
+  /usr/include/x86_64-linux-gnu/bits/setjmp.h /usr/include/stdio.h \
+  /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+  /home/akaylor/clang-install/bin/../lib/clang/3.3/include/stdarg.h \
+  /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
+  /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/unistd.h \
+  /usr/include/x86_64-linux-gnu/bits/posix_opt.h \
+  /usr/include/x86_64-linux-gnu/bits/environments.h \
+  /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \
+  /usr/include/x86_64-linux-gnu/sys/types.h \
+  /usr/include/x86_64-linux-gnu/sys/select.h \
+  /usr/include/x86_64-linux-gnu/bits/select.h \
+  /usr/include/x86_64-linux-gnu/bits/sigset.h \
+  /usr/include/x86_64-linux-gnu/sys/sysmacros.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/atomic \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/c++0x_warning.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/atomic_base.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/x86_64-linux-gnu/bits/c++config.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/x86_64-linux-gnu/bits/os_defines.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/x86_64-linux-gnu/bits/cpu_defines.h \
+  /home/akaylor/clang-install/bin/../lib/clang/3.3/include/stdbool.h \
+  /home/akaylor/clang-install/bin/../lib/clang/3.3/include/stdint.h \
+  /usr/include/stdint.h /usr/include/x86_64-linux-gnu/bits/wchar.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/atomic_0.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/atomic_2.h
diff --git a/lldb/test/functionalities/thread/exit_during_break/main.d.23614 b/lldb/test/functionalities/thread/exit_during_break/main.d.23614
new file mode 100644
index 0000000..f5194df
--- /dev/null
+++ b/lldb/test/functionalities/thread/exit_during_break/main.d.23614
@@ -0,0 +1,39 @@
+main.o: main.cpp /usr/include/pthread.h /usr/include/features.h \
+  /usr/include/x86_64-linux-gnu/bits/predefs.h \
+  /usr/include/x86_64-linux-gnu/sys/cdefs.h \
+  /usr/include/x86_64-linux-gnu/bits/wordsize.h \
+  /usr/include/x86_64-linux-gnu/gnu/stubs.h \
+  /usr/include/x86_64-linux-gnu/gnu/stubs-64.h /usr/include/endian.h \
+  /usr/include/x86_64-linux-gnu/bits/endian.h \
+  /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/sched.h \
+  /usr/include/x86_64-linux-gnu/bits/types.h \
+  /usr/include/x86_64-linux-gnu/bits/typesizes.h \
+  /home/akaylor/clang-install/bin/../lib/clang/3.3/include/stddef.h \
+  /usr/include/time.h /usr/include/x86_64-linux-gnu/bits/sched.h \
+  /usr/include/x86_64-linux-gnu/bits/time.h \
+  /usr/include/x86_64-linux-gnu/bits/timex.h /usr/include/xlocale.h \
+  /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \
+  /usr/include/x86_64-linux-gnu/bits/setjmp.h /usr/include/stdio.h \
+  /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+  /home/akaylor/clang-install/bin/../lib/clang/3.3/include/stdarg.h \
+  /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
+  /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/unistd.h \
+  /usr/include/x86_64-linux-gnu/bits/posix_opt.h \
+  /usr/include/x86_64-linux-gnu/bits/environments.h \
+  /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \
+  /usr/include/x86_64-linux-gnu/sys/types.h \
+  /usr/include/x86_64-linux-gnu/sys/select.h \
+  /usr/include/x86_64-linux-gnu/bits/select.h \
+  /usr/include/x86_64-linux-gnu/bits/sigset.h \
+  /usr/include/x86_64-linux-gnu/sys/sysmacros.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/atomic \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/c++0x_warning.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/atomic_base.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/x86_64-linux-gnu/bits/c++config.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/x86_64-linux-gnu/bits/os_defines.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/x86_64-linux-gnu/bits/cpu_defines.h \
+  /home/akaylor/clang-install/bin/../lib/clang/3.3/include/stdbool.h \
+  /home/akaylor/clang-install/bin/../lib/clang/3.3/include/stdint.h \
+  /usr/include/stdint.h /usr/include/x86_64-linux-gnu/bits/wchar.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/atomic_0.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/atomic_2.h
diff --git a/lldb/test/functionalities/thread/exit_during_step/Makefile b/lldb/test/functionalities/thread/exit_during_step/Makefile
new file mode 100644
index 0000000..26db481
--- /dev/null
+++ b/lldb/test/functionalities/thread/exit_during_step/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/functionalities/thread/exit_during_step/TestExitDuringStep.py b/lldb/test/functionalities/thread/exit_during_step/TestExitDuringStep.py
new file mode 100644
index 0000000..b6968cdf
--- /dev/null
+++ b/lldb/test/functionalities/thread/exit_during_step/TestExitDuringStep.py
@@ -0,0 +1,113 @@
+"""
+Test number of threads.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+import lldbutil
+
+class ExitDuringStepTestCase(TestBase):
+
+    mydir = os.path.join("functionalities", "thread", "exit_during_step")
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @dsym_test
+    def test_with_dsym(self):
+        """Test thread exit during step handling."""
+        self.buildDsym(dictionary=self.getBuildFlags())
+        self.exit_during_step_test()
+
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @dwarf_test
+    def test_with_dwarf(self):
+        """Test thread exit during step handling."""
+        self.buildDwarf(dictionary=self.getBuildFlags())
+        self.exit_during_step_test()
+
+    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')
+        self.continuepoint = line_number('main.cpp', '// Continue from here')
+
+    def exit_during_step_test(self):
+        """Test thread exit during step handling."""
+        exe = os.path.join(os.getcwd(), "a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # This should create a breakpoint in the main thread.
+        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=1)
+
+        # The breakpoint list should show 1 location.
+        self.expect("breakpoint list -f", "Breakpoint location shown correctly",
+            substrs = ["1: file ='main.cpp', line = %d, locations = 1" % self.breakpoint])
+
+        # Run the program.
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped',
+                       'stop reason = breakpoint'])
+
+        # Get the target process
+        target = self.dbg.GetSelectedTarget()
+        process = target.GetProcess()
+
+        # Get the number of threads
+        num_threads = process.GetNumThreads()
+
+        # Make sure we see all three threads
+        self.assertTrue(num_threads == 3, 'Number of expected threads and actual threads do not match.')
+
+        # Get the thread objects
+        thread1 = process.GetThreadAtIndex(0)
+        thread2 = process.GetThreadAtIndex(1)
+        thread3 = process.GetThreadAtIndex(2)
+
+        # Make sure all threads are stopped
+        self.assertTrue(thread1.IsStopped(), "Thread 1 didn't stop during breakpoint")
+        self.assertTrue(thread2.IsStopped(), "Thread 2 didn't stop during breakpoint")
+        self.assertTrue(thread3.IsStopped(), "Thread 3 didn't stop during breakpoint")
+
+        # Keep stepping until we've reached our designated continue point
+        stepping_thread = process.GetSelectedThread()
+        current_line = self.breakpoint
+        stepping_frame = stepping_thread.GetFrameAtIndex(0)
+        self.assertTrue(current_line == stepping_frame.GetLineEntry().GetLine(), "Starting line for stepping doesn't match breakpoint line.")
+        while current_line != self.continuepoint:
+            self.runCmd("thread step-inst -m all-threads")
+
+            if stepping_thread != process.GetSelectedThread():
+                process.SetSelectedThread(stepping_thread)
+
+            frame = stepping_thread.GetFrameAtIndex(0)
+
+            current_line = frame.GetLineEntry().GetLine()
+
+            self.assertTrue(current_line >= self.breakpoint, "Stepped to unexpected line, " + str(current_line))
+            self.assertTrue(current_line <= self.continuepoint, "Stepped to unexpected line, " + str(current_line))
+
+        self.runCmd("thread list")
+
+        # Update the number of threads
+        num_threads = process.GetNumThreads()
+
+        # Check to see that we reduced the number of threads as expected
+        self.assertTrue(num_threads == 2, 'Number of expected threads and actual threads do not match after thread exit.')
+
+        # Run to completion
+        self.runCmd("continue")
+
+        # At this point, the inferior process should have exited.
+        self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()
diff --git a/lldb/test/functionalities/thread/exit_during_step/main.cpp b/lldb/test/functionalities/thread/exit_during_step/main.cpp
new file mode 100644
index 0000000..9949212
--- /dev/null
+++ b/lldb/test/functionalities/thread/exit_during_step/main.cpp
@@ -0,0 +1,91 @@
+//===-- 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 test is intended to create a situation in which one thread will exit
+// while a the debugger is stepping in another thread.
+
+#include <pthread.h>
+#include <unistd.h>
+
+// Note that although hogging the CPU while waiting for a variable to change
+// would be terrible in production code, it's great for testing since it
+// avoids a lot of messy context switching to get multiple threads synchronized.
+#define do_nothing()
+
+#define pseudo_barrier_wait(bar) \
+    --bar;                       \
+    while (bar > 0)              \
+        do_nothing();
+
+#define pseudo_barrier_init(bar, count) (bar = count)
+
+// A barrier to synchronize thread start.
+volatile int g_barrier;
+
+volatile int g_thread_exited = 0;
+
+volatile int g_test = 0;
+
+void *
+step_thread_func (void *input)
+{
+    // Wait until both threads are started.
+    pseudo_barrier_wait(g_barrier);
+
+    g_test = 0;         // Set breakpoint here
+
+    while (!g_thread_exited)
+        g_test++;
+
+    // One more time to provide a continue point
+    g_test++;           // Continue from here
+
+    // Return
+    return NULL;
+}
+
+void *
+exit_thread_func (void *input)
+{
+    // Wait until both threads are started.
+    pseudo_barrier_wait(g_barrier);
+
+    // Wait until the other thread is stepping.
+    while (g_test == 0)
+      do_nothing();
+
+    // Return
+    return NULL;
+}
+
+int main ()
+{
+    pthread_t thread_1;
+    pthread_t thread_2;
+
+    // Synchronize thread start so that doesn't happen during stepping.
+    pseudo_barrier_init(g_barrier, 2);
+
+    // Create a thread to hit the breakpoint.
+    pthread_create (&thread_1, NULL, step_thread_func, NULL);
+
+    // Create a thread to exit while we're stepping.
+    pthread_create (&thread_2, NULL, exit_thread_func, NULL);
+
+    // Wait for the exit thread to finish.
+    pthread_join(thread_2, NULL);
+
+    // Let the stepping thread know the other thread is gone.
+    g_thread_exited = 1;
+
+    // Wait for the stepping thread to finish.
+    pthread_join(thread_1, NULL);
+
+    return 0;
+}
diff --git a/lldb/test/functionalities/thread/multi_break/Makefile b/lldb/test/functionalities/thread/multi_break/Makefile
new file mode 100644
index 0000000..26db481
--- /dev/null
+++ b/lldb/test/functionalities/thread/multi_break/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py b/lldb/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py
new file mode 100644
index 0000000..a042284
--- /dev/null
+++ b/lldb/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py
@@ -0,0 +1,90 @@
+"""
+Test number of threads.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+import lldbutil
+
+class MultipleBreakpointTestCase(TestBase):
+
+    mydir = os.path.join("functionalities", "thread", "multi_break")
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @dsym_test
+    def test_with_dsym(self):
+        """Test simultaneous breakpoints in multiple threads."""
+        self.buildDsym(dictionary=self.getBuildFlags())
+        self.multiple_breakpoint_test()
+
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @dwarf_test
+    def test_with_dwarf(self):
+        """Test simultaneous breakpoints in multiple threads."""
+        self.buildDwarf(dictionary=self.getBuildFlags())
+        self.multiple_breakpoint_test()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Find the line number for our breakpoint.
+        self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
+
+    def multiple_breakpoint_test(self):
+        """Test simultaneous breakpoints in multiple threads."""
+        exe = os.path.join(os.getcwd(), "a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # This should create a breakpoint in the main thread.
+        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=1)
+
+        # The breakpoint list should show 1 location.
+        self.expect("breakpoint list -f", "Breakpoint location shown correctly",
+            substrs = ["1: file ='main.cpp', line = %d, locations = 1" % self.breakpoint])
+
+        # Run the program.
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        # The breakpoint may be hit in either thread 2 or thread 3.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped',
+                       'stop reason = breakpoint'])
+
+        # Get the target process
+        target = self.dbg.GetSelectedTarget()
+        process = target.GetProcess()
+
+        # Get the number of threads
+        num_threads = process.GetNumThreads()
+
+        # Make sure we see all three threads
+        self.assertTrue(num_threads == 3, 'Number of expected threads and actual threads do not match.')
+
+        # Get the thread objects
+        thread1 = process.GetThreadAtIndex(0)
+        thread2 = process.GetThreadAtIndex(1)
+        thread3 = process.GetThreadAtIndex(2)
+
+        # Make sure both threads are stopped
+        self.assertTrue(thread1.IsStopped(), "Primary thread didn't stop during breakpoint")
+        self.assertTrue(thread2.IsStopped(), "Secondary thread didn't stop during breakpoint")
+        self.assertTrue(thread3.IsStopped(), "Tertiary thread didn't stop during breakpoint")
+
+        # Delete the first breakpoint then continue
+        self.runCmd("breakpoint delete 1")
+
+        # Run to completion
+        self.runCmd("continue")
+
+        # At this point, the inferior process should have exited.
+        self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()
diff --git a/lldb/test/functionalities/thread/multi_break/main.cpp b/lldb/test/functionalities/thread/multi_break/main.cpp
new file mode 100644
index 0000000..e567e54
--- /dev/null
+++ b/lldb/test/functionalities/thread/multi_break/main.cpp
@@ -0,0 +1,64 @@
+//===-- 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 test is intended to create a situation in which a breakpoint will be
+// hit in two threads at nearly the same moment.  The expected result is that
+// the breakpoint in the second thread will be hit while the breakpoint handler
+// in the first thread is trying to stop all threads.
+
+#include <pthread.h>
+#include <atomic>
+
+// Note that although hogging the CPU while waiting for a variable to change
+// would be terrible in production code, it's great for testing since it
+// avoids a lot of messy context switching to get multiple threads synchronized.
+#define do_nothing()
+
+#define pseudo_barrier_wait(bar) \
+    --bar;                       \
+    while (bar > 0)              \
+        do_nothing();
+
+#define pseudo_barrier_init(bar, count) (bar = count)
+
+std::atomic_int g_barrier;
+
+volatile int g_test = 0;
+
+void *
+thread_func (void *input)
+{
+    // Wait until both threads are running
+    pseudo_barrier_wait(g_barrier);
+
+    // Do something
+    g_test++;       // Set breakpoint here
+
+    // Return
+    return NULL;
+}
+
+int main ()
+{
+    pthread_t thread_1;
+    pthread_t thread_2;
+
+    // Don't let either thread do anything until they're both ready.
+    pseudo_barrier_init(g_barrier, 2);
+
+    // Create two threads
+    pthread_create (&thread_1, NULL, thread_func, NULL);
+    pthread_create (&thread_2, NULL, thread_func, NULL);
+
+    // Wait for the threads to finish
+    pthread_join(thread_1, NULL);
+    pthread_join(thread_2, NULL);
+
+    return 0;
+}
diff --git a/lldb/test/functionalities/thread/state/Makefile b/lldb/test/functionalities/thread/state/Makefile
index 0cde994..3b5a8a3 100644
--- a/lldb/test/functionalities/thread/state/Makefile
+++ b/lldb/test/functionalities/thread/state/Makefile
@@ -1,5 +1,4 @@
 LEVEL = ../../../make
 
 C_SOURCES := main.c
-LD_EXTRAS := -lpthread
 include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/functionalities/thread/state/TestThreadStates.py b/lldb/test/functionalities/thread/state/TestThreadStates.py
index 22b51bf..fe9fb20 100644
--- a/lldb/test/functionalities/thread/state/TestThreadStates.py
+++ b/lldb/test/functionalities/thread/state/TestThreadStates.py
@@ -8,7 +8,7 @@
 from lldbtest import *
 import lldbutil
 
-class StopThreadsTestCase(TestBase):
+class ThreadStateTestCase(TestBase):
 
     mydir = os.path.join("functionalities", "thread", "state")
 
@@ -16,54 +16,54 @@
     @dsym_test
     def test_state_after_breakpoint_with_dsym(self):
         """Test thread state after breakpoint."""
-        self.buildDsym()
+        self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
         self.thread_state_after_breakpoint_test()
 
     @dwarf_test
     def test_state_after_breakpoint_with_dwarf(self):
         """Test thread state after breakpoint."""
-        self.buildDwarf()
+        self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
         self.thread_state_after_breakpoint_test()
 
     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     @dsym_test
     def test_state_after_continue_with_dsym(self):
         """Test thread state after continue."""
-        self.buildDsym()
+        self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
         self.thread_state_after_continue_test()
 
     @dwarf_test
     def test_state_after_continue_with_dwarf(self):
         """Test thread state after continue."""
-        self.buildDwarf()
+        self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
         self.thread_state_after_continue_test()
 
     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     @dsym_test
     def test_state_after_expression_with_dsym(self):
         """Test thread state after expression."""
-        self.buildDsym()
+        self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
         self.thread_state_after_continue_test()
 
     @dwarf_test
     def test_state_after_expression_with_dwarf(self):
         """Test thread state after expression."""
-        self.buildDwarf()
+        self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
         self.thread_state_after_continue_test()
 
     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     @dsym_test
-    @unittest2.expectedFailure("llvm.org/pr15824") # thread states not properly maintained
+    @unittest2.expectedFailure("llvm.org/pr16172") # thread states not properly maintained
     def test_process_interrupt_with_dsym(self):
         """Test process interrupt."""
-        self.buildDsym()
+        self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
         self.process_interrupt_test()
 
     @dwarf_test
-    @unittest2.expectedFailure("llvm.org/pr15824") # thread states not properly maintained
+    @unittest2.expectedFailure("llvm.org/pr16712") # thread states not properly maintained
     def test_process_interrupt_with_dwarf(self):
         """Test process interrupt."""
-        self.buildDwarf()
+        self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
         self.process_interrupt_test()
 
     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
@@ -71,14 +71,14 @@
     @unittest2.expectedFailure("llvm.org/pr15824") # thread states not properly maintained
     def test_process_state_with_dsym(self):
         """Test thread states (comprehensive)."""
-        self.buildDsym()
+        self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
         self.thread_states_test()
 
     @dwarf_test
     @unittest2.expectedFailure("llvm.org/pr15824") # thread states not properly maintained
     def test_process_state_with_dwarf(self):
         """Test thread states (comprehensive)."""
-        self.buildDwarf()
+        self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
         self.thread_states_test()
 
     def setUp(self):
diff --git a/lldb/test/functionalities/thread/thread_exit/Makefile b/lldb/test/functionalities/thread/thread_exit/Makefile
new file mode 100644
index 0000000..26db481
--- /dev/null
+++ b/lldb/test/functionalities/thread/thread_exit/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/functionalities/thread/thread_exit/TestThreadExit.py b/lldb/test/functionalities/thread/thread_exit/TestThreadExit.py
new file mode 100644
index 0000000..7fd4f91
--- /dev/null
+++ b/lldb/test/functionalities/thread/thread_exit/TestThreadExit.py
@@ -0,0 +1,132 @@
+"""
+Test number of threads.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+import lldbutil
+
+class ThreadExitTestCase(TestBase):
+
+    mydir = os.path.join("functionalities", "thread", "thread_exit")
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @dsym_test
+    def test_with_dsym(self):
+        """Test thread exit handling."""
+        self.buildDsym(dictionary=self.getBuildFlags())
+        self.thread_exit_test()
+
+    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
+    @dwarf_test
+    def test_with_dwarf(self):
+        """Test thread exit handling."""
+        self.buildDwarf(dictionary=self.getBuildFlags())
+        self.thread_exit_test()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Find the line numbers for our breakpoints.
+        self.break_1 = line_number('main.cpp', '// Set first breakpoint here')
+        self.break_2 = line_number('main.cpp', '// Set second breakpoint here')
+        self.break_3 = line_number('main.cpp', '// Set third breakpoint here')
+        self.break_4 = line_number('main.cpp', '// Set fourth breakpoint here')
+
+    def thread_exit_test(self):
+        """Test thread exit handling."""
+        exe = os.path.join(os.getcwd(), "a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # This should create a breakpoint with 1 location.
+        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_1, num_expected_locations=1)
+        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_2, num_expected_locations=1)
+        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_3, num_expected_locations=1)
+        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_4, num_expected_locations=1)
+
+        # The breakpoint list should show 1 locations.
+        self.expect("breakpoint list -f", "Breakpoint location shown correctly",
+            substrs = ["1: file ='main.cpp', line = %d, locations = 1" % self.break_1,
+                       "2: file ='main.cpp', line = %d, locations = 1" % self.break_2,
+                       "3: file ='main.cpp', line = %d, locations = 1" % self.break_3,
+                       "4: file ='main.cpp', line = %d, locations = 1" % self.break_4])
+
+        # Run the program.
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint 1.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 1",
+            substrs = ['stopped',
+                       '* thread #1',
+                       'stop reason = breakpoint 1',
+                       'thread #2'])
+
+        # Get the target process
+        target = self.dbg.GetSelectedTarget()
+        process = target.GetProcess()
+
+        # Get the number of threads
+        num_threads = process.GetNumThreads()
+
+        self.assertTrue(num_threads == 2, 'Number of expected threads and actual threads do not match at breakpoint 1.')
+
+        # Run to the second breakpoint
+        self.runCmd("continue")
+
+        # The stop reason of the thread should be breakpoint 1.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 2",
+            substrs = ['stopped',
+                       'thread #1',
+                       '* thread #2',
+                       'stop reason = breakpoint 2',
+                       'thread #3'])
+
+        # Update the number of threads
+        num_threads = process.GetNumThreads()
+
+        self.assertTrue(num_threads == 3, 'Number of expected threads and actual threads do not match at breakpoint 2.')
+
+        # Run to the third breakpoint
+        self.runCmd("continue")
+
+        # The stop reason of the thread should be breakpoint 3.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 3",
+            substrs = ['stopped',
+                       '* thread #1',
+                       'stop reason = breakpoint 3',
+                       'thread #3',
+                       ])
+
+        # Update the number of threads
+        num_threads = process.GetNumThreads()
+
+        self.assertTrue(num_threads == 2, 'Number of expected threads and actual threads do not match at breakpoint 3.')
+
+        # Run to the fourth breakpoint
+        self.runCmd("continue")
+
+        # The stop reason of the thread should be breakpoint 4.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 4",
+            substrs = ['stopped',
+                       '* thread #1',
+                       'stop reason = breakpoint 4'])
+
+        # Update the number of threads
+        num_threads = process.GetNumThreads()
+
+        self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match at breakpoint 4.')
+
+        # Run to completion
+        self.runCmd("continue")
+
+        # At this point, the inferior process should have exited.
+        self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()
diff --git a/lldb/test/functionalities/thread/thread_exit/main.cpp b/lldb/test/functionalities/thread/thread_exit/main.cpp
new file mode 100644
index 0000000..94ed517
--- /dev/null
+++ b/lldb/test/functionalities/thread/thread_exit/main.cpp
@@ -0,0 +1,89 @@
+//===-- 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 test verifies the correct handling of child thread exits.
+
+#include <pthread.h>
+#include <atomic>
+
+// Note that although hogging the CPU while waiting for a variable to change
+// would be terrible in production code, it's great for testing since it
+// avoids a lot of messy context switching to get multiple threads synchronized.
+#define do_nothing()
+
+#define pseudo_barrier_wait(bar) \
+    --bar;                       \
+    while (bar > 0)              \
+        do_nothing();
+
+#define pseudo_barrier_init(bar, count) (bar = count)
+
+std::atomic_int g_barrier1;
+std::atomic_int g_barrier2;
+std::atomic_int g_barrier3;
+
+void *
+thread1 (void *input)
+{
+    // Synchronize with the main thread.
+    pseudo_barrier_wait(g_barrier1);
+
+    // Synchronize with the main thread and thread2.
+    pseudo_barrier_wait(g_barrier2);
+
+    // Return
+    return NULL;                                      // Set second breakpoint here
+}
+
+void *
+thread2 (void *input)
+{
+    // Synchronize with thread1 and the main thread.
+    pseudo_barrier_wait(g_barrier2);
+
+    // Synchronize with the main thread.
+    pseudo_barrier_wait(g_barrier3);
+
+    // Return
+    return NULL;
+}
+
+int main ()
+{
+    pthread_t thread_1;
+    pthread_t thread_2;
+    pthread_t thread_3;
+
+    pseudo_barrier_init(g_barrier1, 2);
+    pseudo_barrier_init(g_barrier2, 3);
+    pseudo_barrier_init(g_barrier3, 2);
+
+    // Create a thread.
+    pthread_create (&thread_1, NULL, thread1, NULL);
+
+    // Wait for thread1 to start.
+    pseudo_barrier_wait(g_barrier1);
+
+    // Create another thread.
+    pthread_create (&thread_2, NULL, thread2, NULL);  // Set first breakpoint here
+
+    // Wait for thread2 to start.
+    pseudo_barrier_wait(g_barrier2);
+
+    // Wait for the first thread to finish
+    pthread_join(thread_1, NULL);
+
+    // Synchronize with the remaining thread
+    pseudo_barrier_wait(g_barrier3);                  // Set third breakpoint here
+
+    // Wait for the second thread to finish
+    pthread_join(thread_2, NULL);
+
+    return 0;                                         // Set fourth breakpoint here
+}
diff --git a/lldb/test/lldbtest.py b/lldb/test/lldbtest.py
index ae81189..353f455 100644
--- a/lldb/test/lldbtest.py
+++ b/lldb/test/lldbtest.py
@@ -1251,6 +1251,29 @@
         if not module.buildDwarf(self, architecture, compiler, dictionary, clean):
             raise Exception("Don't know how to build binary with dwarf")
 
+    def getBuildFlags(self, use_cpp11=True, use_pthreads=True):
+        """ Returns a dictionary (which can be provided to build* functions above) which
+            contains OS-specific build flags.
+        """
+        cflags = ""
+        if use_cpp11:
+            cflags += "-std="
+            if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion():
+                cflags += "c++0x"
+            else:
+                cflags += "c++11"
+        if sys.platform.startswith("darwin"):
+            cflags += " -stdlib=libc++"
+        elif "clang" in self.getCompiler():
+            cflags += " -stdlib=libstdc++"
+
+        if use_pthreads:
+            ldflags = "-lpthread"
+
+        return {'CFLAGS_EXTRAS' : cflags,
+                'LD_EXTRAS' : ldflags,
+               }
+
     def cleanup(self, dictionary=None):
         """Platform specific way to do cleanup after build."""
         if lldb.skip_build_and_cleanup: