[Lldb-commits] [lldb] r140757 - in /lldb/trunk: test/functionalities/watchpoint/multiple_threads/ test/functionalities/watchpoint/multiple_threads/Makefile test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py test/functionalities/watchpoint/multiple_threads/main.cpp tools/debugserver/source/MacOSX/MachThreadList.cpp
Johnny Chen
johnny.chen at apple.com
Wed Sep 28 18:20:42 PDT 2011
Author: johnny
Date: Wed Sep 28 20:20:42 2011
New Revision: 140757
URL: http://llvm.org/viewvc/llvm-project?rev=140757&view=rev
Log:
Fix a bug in the current MacOSX MachThreadList::EnableHardwareWatchpoint() impl so that
it enables the hardware watchpoint for all existing threads. Add a test file for that.
Also fix MachThreadList::DisableHardwareWatchpoint().
Added:
lldb/trunk/test/functionalities/watchpoint/multiple_threads/
lldb/trunk/test/functionalities/watchpoint/multiple_threads/Makefile
lldb/trunk/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py
lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp
Modified:
lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp
Added: lldb/trunk/test/functionalities/watchpoint/multiple_threads/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/multiple_threads/Makefile?rev=140757&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/multiple_threads/Makefile (added)
+++ lldb/trunk/test/functionalities/watchpoint/multiple_threads/Makefile Wed Sep 28 20:20:42 2011
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
Added: lldb/trunk/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py?rev=140757&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py (added)
+++ lldb/trunk/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py Wed Sep 28 20:20:42 2011
@@ -0,0 +1,90 @@
+"""
+Test that lldb watchpoint works for multiple threads.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+
+class WatchpointForMultipleThreadsTestCase(TestBase):
+
+ mydir = os.path.join("functionalities", "watchpoint", "multiple_threads")
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ def test_watchpoint_multiple_threads_with_dsym(self):
+ """Test that lldb watchpoint works for multiple threads."""
+ self.buildDsym(dictionary=self.d)
+ self.setTearDownCleanup(dictionary=self.d)
+ self.hello_multiple_threads()
+
+ def test_watchpoint_multiple_threads_with_dwarf(self):
+ """Test that lldb watchpoint works for multiple threads."""
+ self.buildDwarf(dictionary=self.d)
+ self.setTearDownCleanup(dictionary=self.d)
+ self.hello_multiple_threads()
+
+ 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.line = line_number(self.source, '// Set break point at this line.')
+ # Build dictionary to have unique executable names for each test method.
+ self.exe_name = self.testMethodName
+ self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name}
+
+ def hello_multiple_threads(self):
+ """Test that lldb watchpoint works for multiple threads."""
+ exe = os.path.join(os.getcwd(), self.exe_name)
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
+ self.expect("breakpoint set -l %d" % self.line, BREAKPOINT_CREATED,
+ startstr = "Breakpoint created: 1: file ='%s', line = %d, locations = 1" %
+ (self.source, self.line))
+
+ # 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'])
+
+ # Now let's set a write-type watchpoint for variable 'g_val'.
+ # The main.cpp, by design, misbehaves by not following the agreed upon
+ # protocol of using a mutex while accessing the global pool and by not
+ # writing to the variable.
+ self.expect("frame variable -w write -g g_val", WATCHPOINT_CREATED,
+ substrs = ['Watchpoint created', 'size = 4', 'type = w'])
+
+ # Use the '-v' option to do verbose listing of the watchpoint.
+ # The hit count should be 0 initially.
+ self.expect("watchpoint list -v",
+ substrs = ['hit_count = 0'])
+
+ self.runCmd("process continue")
+
+ # We should be stopped again due to the watchpoint (write type) in a
+ # different work thread. And the stop reason of the thread should be
+ # watchpoint.
+ self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT,
+ substrs = ['stopped',
+ 'stop reason = 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'])
+
+ self.runCmd("thread backtrace all")
+
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
Added: lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp?rev=140757&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp (added)
+++ lldb/trunk/test/functionalities/watchpoint/multiple_threads/main.cpp Wed Sep 28 20:20:42 2011
@@ -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.
+//
+//===----------------------------------------------------------------------===//
+
+// C includes
+#include <pthread.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+pthread_t g_thread_1 = NULL;
+pthread_t g_thread_2 = NULL;
+pthread_t g_thread_3 = NULL;
+
+uint32_t g_val = 0;
+
+uint32_t access_pool (uint32_t flag = 0);
+
+uint32_t
+access_pool (uint32_t flag)
+{
+ static pthread_mutex_t g_access_mutex = PTHREAD_MUTEX_INITIALIZER;
+ if (flag == 0)
+ ::pthread_mutex_lock (&g_access_mutex);
+
+ uint32_t old_val = g_val;
+ if (flag != 0)
+ g_val = old_val + 1;
+
+ if (flag == 0)
+ ::pthread_mutex_unlock (&g_access_mutex);
+ return g_val;
+}
+
+void *
+thread_func (void *arg)
+{
+ uint32_t thread_index = *((uint32_t *)arg);
+ printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index);
+
+ uint32_t count = 0;
+ uint32_t val;
+ while (count++ < 15)
+ {
+ // random micro second sleep from zero to 3 seconds
+ int usec = ::rand() % 3000000;
+ printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec);
+ ::usleep (usec);
+
+ if (count < 7)
+ val = access_pool ();
+ else
+ val = access_pool (1);
+
+ 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);
+ return NULL;
+}
+
+
+int main (int argc, char const *argv[])
+{
+ int err;
+ void *thread_result = NULL;
+ uint32_t thread_index_1 = 1;
+ uint32_t thread_index_2 = 2;
+ uint32_t thread_index_3 = 3;
+
+ // Create 3 threads
+ err = ::pthread_create (&g_thread_1, NULL, thread_func, &thread_index_1);
+ err = ::pthread_create (&g_thread_2, NULL, thread_func, &thread_index_2);
+ err = ::pthread_create (&g_thread_3, NULL, thread_func, &thread_index_3);
+
+ printf ("Before turning all three threads loose...\n"); // Set break point at this line.
+
+ // Join all of our threads
+ err = ::pthread_join (g_thread_1, &thread_result);
+ err = ::pthread_join (g_thread_2, &thread_result);
+ err = ::pthread_join (g_thread_3, &thread_result);
+
+ return 0;
+}
Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp?rev=140757&r1=140756&r2=140757&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp Wed Sep 28 20:20:42 2011
@@ -99,26 +99,14 @@
PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
MachThreadSP thread_sp;
const size_t num_threads = m_threads.size();
- if (MachThread::ThreadIDIsValid(tid))
+ for (size_t idx = 0; idx < num_threads; ++idx)
{
- for (size_t idx = 0; idx < num_threads; ++idx)
+ if (m_threads[idx]->ThreadID() == tid)
{
- if (m_threads[idx]->ThreadID() == tid)
- {
- thread_sp = m_threads[idx];
- break;
- }
+ thread_sp = m_threads[idx];
+ break;
}
}
- else if (num_threads > 0)
- {
- // See DNBWatchpointSet() -> MachProcess::CreateWatchpoint() -> MachProcess::EnableWatchpoint()
- // -> MachThreadList::EnableHardwareWatchpoint() for a use case of this branch.
- if (m_current_thread)
- thread_sp = m_current_thread;
- else
- thread_sp = m_threads[0];
- }
return thread_sp;
}
@@ -477,14 +465,22 @@
return false;
}
+// DNBWatchpointSet() -> MachProcess::CreateWatchpoint() -> MachProcess::EnableWatchpoint()
+// -> MachThreadList::EnableHardwareWatchpoint().
uint32_t
MachThreadList::EnableHardwareWatchpoint (const DNBBreakpoint* wp) const
{
if (wp != NULL)
{
- MachThreadSP thread_sp (GetThreadByID (wp->ThreadID()));
- if (thread_sp)
- return thread_sp->EnableHardwareWatchpoint(wp);
+ uint32_t hw_index;
+ PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
+ const uint32_t num_threads = m_threads.size();
+ for (uint32_t idx = 0; idx < num_threads; ++idx)
+ {
+ if ((hw_index = m_threads[idx]->EnableHardwareWatchpoint(wp)) == INVALID_NUB_HW_INDEX)
+ return INVALID_NUB_HW_INDEX;
+ }
+ return hw_index;
}
return INVALID_NUB_HW_INDEX;
}
@@ -494,9 +490,14 @@
{
if (wp != NULL)
{
- MachThreadSP thread_sp (GetThreadByID (wp->ThreadID()));
- if (thread_sp)
- return thread_sp->DisableHardwareWatchpoint(wp);
+ PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
+ const uint32_t num_threads = m_threads.size();
+ for (uint32_t idx = 0; idx < num_threads; ++idx)
+ {
+ if (!m_threads[idx]->DisableHardwareWatchpoint(wp))
+ return false;
+ }
+ return true;
}
return false;
}
More information about the lldb-commits
mailing list