JDevlieghere created this revision. JDevlieghere added a reviewer: jingham. Herald added a subscriber: mgorny. Herald added a project: All. JDevlieghere requested review of this revision.
Jim is looking into adding support for interrupts to the SB API. Part of that work requires clearing the interrupt bit once we return from the SB API. Luckily, this is already tracked by the API instrumentation. This patch adds the necessary interruption boilerplate to hook it up with the SB API instrumentation. https://reviews.llvm.org/D133129 Files: lldb/include/lldb/Core/Debugger.h lldb/include/lldb/Utility/Instrumentation.h lldb/source/Core/Debugger.cpp lldb/source/Utility/Instrumentation.cpp lldb/unittests/Utility/CMakeLists.txt lldb/unittests/Utility/InstrumentationTest.cpp
Index: lldb/unittests/Utility/InstrumentationTest.cpp =================================================================== --- /dev/null +++ lldb/unittests/Utility/InstrumentationTest.cpp @@ -0,0 +1,49 @@ +//===-- InstrumentationTest.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "lldb/Utility/Instrumentation.h" + +using namespace llvm; +using namespace lldb_private; +using namespace lldb_private::instrumentation; + +TEST(InsturmentationTest, Callback) { + size_t entry = 0; + size_t exit = 0; + + Instrumenter::UnregisterCallbacks(); + + Instrumenter::RegisterEntryCallback([&]() { entry++; }); + Instrumenter::RegisterExitCallback([&]() { exit++; }); + + EXPECT_EQ(entry, 0UL); + EXPECT_EQ(exit, 0UL); + + { + Instrumenter foo("foo"); + EXPECT_EQ(entry, 1UL); + EXPECT_EQ(exit, 0UL); + } + + EXPECT_EQ(entry, 1UL); + EXPECT_EQ(exit, 1UL); + + { + Instrumenter bar("bar"); + EXPECT_EQ(entry, 2UL); + EXPECT_EQ(exit, 1UL); + } + + EXPECT_EQ(entry, 2UL); + EXPECT_EQ(exit, 2UL); + + Instrumenter::UnregisterCallbacks(); +} Index: lldb/unittests/Utility/CMakeLists.txt =================================================================== --- lldb/unittests/Utility/CMakeLists.txt +++ lldb/unittests/Utility/CMakeLists.txt @@ -13,6 +13,7 @@ EventTest.cpp FileSpecTest.cpp FlagsTest.cpp + InstrumentationTest.cpp ListenerTest.cpp LogTest.cpp NameMatchesTest.cpp Index: lldb/source/Utility/Instrumentation.cpp =================================================================== --- lldb/source/Utility/Instrumentation.cpp +++ lldb/source/Utility/Instrumentation.cpp @@ -23,12 +23,20 @@ // Instrument SB API calls with singposts when supported. static llvm::ManagedStatic<llvm::SignpostEmitter> g_api_signposts; +// Callbacks for entering the instrumentation boundary. +static std::vector<Instrumenter::Callback> g_entry_callbacks; + +// Callbacks for leaving the instrumentation boundary. +static std::vector<Instrumenter::Callback> g_exit_callbacks; + Instrumenter::Instrumenter(llvm::StringRef pretty_func, std::string &&pretty_args) : m_pretty_func(pretty_func) { if (!g_global_boundary) { g_global_boundary = true; m_local_boundary = true; + for (Callback callback : g_entry_callbacks) + callback(); g_api_signposts->startInterval(this, m_pretty_func); } LLDB_LOG(GetLog(LLDBLog::API), "[{0}] {1} ({2})", @@ -39,6 +47,21 @@ Instrumenter::~Instrumenter() { if (m_local_boundary) { g_global_boundary = false; + for (Callback callback : g_exit_callbacks) + callback(); g_api_signposts->endInterval(this, m_pretty_func); } } + +void Instrumenter::RegisterEntryCallback(Instrumenter::Callback callback) { + g_entry_callbacks.emplace_back(std::move(callback)); +} + +void Instrumenter::RegisterExitCallback(Instrumenter::Callback callback) { + g_exit_callbacks.emplace_back(std::move(callback)); +} + +void Instrumenter::UnregisterCallbacks() { + g_entry_callbacks.clear(); + g_exit_callbacks.clear(); +} Index: lldb/source/Core/Debugger.cpp =================================================================== --- lldb/source/Core/Debugger.cpp +++ lldb/source/Core/Debugger.cpp @@ -45,6 +45,7 @@ #include "lldb/Target/ThreadList.h" #include "lldb/Utility/AnsiTerminal.h" #include "lldb/Utility/Event.h" +#include "lldb/Utility/Instrumentation.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Listener.h" #include "lldb/Utility/Log.h" @@ -542,6 +543,7 @@ g_debugger_list_ptr = new DebuggerList(); g_thread_pool = new llvm::ThreadPool(llvm::optimal_concurrency()); g_load_plugin_callback = load_plugin_callback; + instrumentation::Instrumenter::RegisterExitCallback([]() { Debugger::ClearInterrupts(); }); } void Debugger::Terminate() { @@ -1303,6 +1305,23 @@ std::make_shared<CallbackLogHandler>(log_callback, baton); } +void Debugger::RequestInterrupt() { + m_interrupt_requested = true; +} + +void Debugger::ClearInterrupt() { + m_interrupt_requested = false; +} + +void Debugger::ClearInterrupts() { + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); + for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) + (*pos)->ClearInterrupt(); + } +} + static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id, const std::string &message, uint64_t completed, uint64_t total, Index: lldb/include/lldb/Utility/Instrumentation.h =================================================================== --- lldb/include/lldb/Utility/Instrumentation.h +++ lldb/include/lldb/Utility/Instrumentation.h @@ -81,6 +81,19 @@ Instrumenter(llvm::StringRef pretty_func, std::string &&pretty_args = {}); ~Instrumenter(); + using Callback = std::function<void(void)>; + + /// Register a callback that's called when entering the instrumentation + /// boundary. + static void RegisterEntryCallback(Callback callback); + + /// Register a callback that's called when leaving the instrumentation + /// boundary. + static void RegisterExitCallback(Callback callback); + + /// Unregister all entry and exit callbacks. + static void UnregisterCallbacks(); + private: void UpdateBoundary(); Index: lldb/include/lldb/Core/Debugger.h =================================================================== --- lldb/include/lldb/Core/Debugger.h +++ lldb/include/lldb/Core/Debugger.h @@ -387,6 +387,15 @@ /// Shared thread poll. Use only with ThreadPoolTaskGroup. static llvm::ThreadPool &GetThreadPool(); + /// Request an interrupt. + void RequestInterrupt(); + + /// Clear the request for an interrupt. + void ClearInterrupt(); + + /// Clear all interrupt requests. + static void ClearInterrupts(); + /// Report warning events. /// /// Progress events will be delivered to any debuggers that have listeners @@ -573,6 +582,8 @@ llvm::once_flag m_clear_once; lldb::TargetSP m_dummy_target_sp; + bool m_interrupt_requested; + // Events for m_sync_broadcaster enum { eBroadcastBitEventThreadIsListening = (1 << 0),
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits