This revision was automatically updated to reflect the committed changes.
Closed by commit rG130055647922: Add unix signal hit counts to the target 
statistics. (authored by clayborg).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D112683/new/

https://reviews.llvm.org/D112683

Files:
  lldb/include/lldb/Target/UnixSignals.h
  lldb/source/Target/Statistics.cpp
  lldb/source/Target/StopInfo.cpp
  lldb/source/Target/UnixSignals.cpp
  lldb/test/API/functionalities/signal/TestSendSignal.py

Index: lldb/test/API/functionalities/signal/TestSendSignal.py
===================================================================
--- lldb/test/API/functionalities/signal/TestSendSignal.py
+++ lldb/test/API/functionalities/signal/TestSendSignal.py
@@ -95,6 +95,10 @@
             thread.GetStopReasonDataAtIndex(0), lldbutil.get_signal_number('SIGUSR1'),
             "The stop signal was SIGUSR1")
 
+        self.match("statistics dump",
+                   [r'"signals": \[', r'"SIGUSR1": 1'])
+
+
     def match_state(self, process_listener, expected_state):
         num_seconds = 5
         broadcaster = self.process().GetBroadcaster()
Index: lldb/source/Target/UnixSignals.cpp
===================================================================
--- lldb/source/Target/UnixSignals.cpp
+++ lldb/source/Target/UnixSignals.cpp
@@ -15,6 +15,7 @@
 #include "lldb/Utility/ArchSpec.h"
 
 using namespace lldb_private;
+using namespace llvm;
 
 UnixSignals::Signal::Signal(const char *name, bool default_suppress,
                             bool default_stop, bool default_notify,
@@ -312,3 +313,20 @@
 
   return result;
 }
+
+void UnixSignals::IncrementSignalHitCount(int signo) {
+  collection::iterator pos = m_signals.find(signo);
+  if (pos != m_signals.end())
+    pos->second.m_hit_count += 1;
+}
+
+json::Value UnixSignals::GetHitCountStatistics() const {
+  json::Array json_signals;
+  for (const auto &pair: m_signals) {
+    if (pair.second.m_hit_count > 0)
+      json_signals.emplace_back(json::Object{
+        { pair.second.m_name.GetCString(), pair.second.m_hit_count }
+      });
+  }
+  return std::move(json_signals);
+}
Index: lldb/source/Target/StopInfo.cpp
===================================================================
--- lldb/source/Target/StopInfo.cpp
+++ lldb/source/Target/StopInfo.cpp
@@ -307,7 +307,7 @@
 
           // There's one other complication here.  We may have run an async
           // breakpoint callback that said we should stop.  We only want to
-          // override that if another breakpoint action says we shouldn't 
+          // override that if another breakpoint action says we shouldn't
           // stop.  If nobody else has an opinion, then we should stop if the
           // async callback says we should.  An example of this is the async
           // shared library load notification breakpoint and the setting
@@ -425,7 +425,7 @@
             }
 
             internal_breakpoint = bp_loc_sp->GetBreakpoint().IsInternal();
-            
+
             // First run the precondition, but since the precondition is per
             // breakpoint, only run it once per breakpoint.
             std::pair<std::unordered_set<break_id_t>::iterator, bool> result =
@@ -535,7 +535,7 @@
               else
                 actually_said_continue = true;
             }
-                  
+
             // If we are going to stop for this breakpoint, then remove the
             // breakpoint.
             if (callback_says_stop && bp_loc_sp &&
@@ -579,7 +579,7 @@
         // Override should_stop decision when we have completed step plan
         // additionally to the breakpoint
         m_should_stop = true;
-        
+
         // We know we're stopping for a completed plan and we don't want to
         // show the breakpoint stop, so compute the public stop info immediately
         // here.
@@ -615,7 +615,7 @@
   // performing watchpoint actions.
   class WatchpointSentry {
   public:
-    WatchpointSentry(ProcessSP p_sp, WatchpointSP w_sp) : process_sp(p_sp), 
+    WatchpointSentry(ProcessSP p_sp, WatchpointSP w_sp) : process_sp(p_sp),
                      watchpoint_sp(w_sp) {
       if (process_sp && watchpoint_sp) {
         const bool notify = false;
@@ -624,7 +624,7 @@
         process_sp->AddPreResumeAction(SentryPreResumeAction, this);
       }
     }
-    
+
     void DoReenable() {
       if (process_sp && watchpoint_sp) {
         bool was_disabled = watchpoint_sp->IsDisabledDuringEphemeralMode();
@@ -637,13 +637,13 @@
         }
       }
     }
-    
+
     ~WatchpointSentry() {
         DoReenable();
         if (process_sp)
             process_sp->ClearPreResumeAction(SentryPreResumeAction, this);
     }
-    
+
     static bool SentryPreResumeAction(void *sentry_void) {
         WatchpointSentry *sentry = (WatchpointSentry *) sentry_void;
         sentry->DoReenable();
@@ -724,14 +724,14 @@
     // course of this code.  Also by default we're going to stop, so set that
     // here.
     m_should_stop = true;
-    
+
 
     ThreadSP thread_sp(m_thread_wp.lock());
     if (thread_sp) {
 
       WatchpointSP wp_sp(
           thread_sp->CalculateTarget()->GetWatchpointList().FindByID(
-              GetValue()));      
+              GetValue()));
       if (wp_sp) {
         ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
         ProcessSP process_sp = exe_ctx.GetProcessSP();
@@ -889,12 +889,12 @@
 
           bool old_async = debugger.GetAsyncExecution();
           debugger.SetAsyncExecution(true);
-          
+
           StoppointCallbackContext context(event_ptr, exe_ctx, false);
           bool stop_requested = wp_sp->InvokeCallback(&context);
-          
+
           debugger.SetAsyncExecution(old_async);
-          
+
           // Also make sure that the callback hasn't continued the target. If
           // it did, when we'll set m_should_stop to false and get out of here.
           if (HasTargetRunSinceMe())
@@ -1272,6 +1272,7 @@
 
 StopInfoSP StopInfo::CreateStopReasonWithSignal(Thread &thread, int signo,
                                                 const char *description) {
+  thread.GetProcess()->GetUnixSignals()->IncrementSignalHitCount(signo);
   return StopInfoSP(new StopInfoUnixSignal(thread, signo, description));
 }
 
Index: lldb/source/Target/Statistics.cpp
===================================================================
--- lldb/source/Target/Statistics.cpp
+++ lldb/source/Target/Statistics.cpp
@@ -11,7 +11,9 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Target/UnixSignals.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -95,6 +97,13 @@
     }
   }
 
+  ProcessSP process_sp = target.GetProcessSP();
+  if (process_sp) {
+    UnixSignalsSP unix_signals_sp = process_sp->GetUnixSignals();
+    if (unix_signals_sp)
+      target_metrics_json.try_emplace("signals",
+                                      unix_signals_sp->GetHitCountStatistics());
+  }
   target_metrics_json.try_emplace("breakpoints", std::move(breakpoints_array));
   target_metrics_json.try_emplace("totalBreakpointResolveTime",
                                   totalBreakpointResolveTime);
Index: lldb/include/lldb/Target/UnixSignals.h
===================================================================
--- lldb/include/lldb/Target/UnixSignals.h
+++ lldb/include/lldb/Target/UnixSignals.h
@@ -16,6 +16,7 @@
 #include "lldb/Utility/ConstString.h"
 #include "lldb/lldb-private.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/Support/JSON.h"
 
 namespace lldb_private {
 
@@ -80,6 +81,18 @@
 
   void RemoveSignal(int signo);
 
+  /// Track how many times signals are hit as stop reasons.
+  void IncrementSignalHitCount(int signo);
+
+  /// Get the hit count statistics for signals.
+  ///
+  /// Gettings statistics on the hit counts of signals can help explain why some
+  /// debug sessions are slow since each stop takes a few hundred ms and some
+  /// software use signals a lot and can cause slow debugging performance if
+  /// they are used too often. Even if a signal is not stopped at, it will auto
+  /// continue the process and a delay will happen.
+  llvm::json::Value GetHitCountStatistics() const;
+
   // Returns a current version of the data stored in this class. Version gets
   // incremented each time Set... method is called.
   uint64_t GetVersion() const;
@@ -99,6 +112,7 @@
     ConstString m_name;
     ConstString m_alias;
     std::string m_description;
+    uint32_t m_hit_count = 0;
     bool m_suppress : 1, m_stop : 1, m_notify : 1;
 
     Signal(const char *name, bool default_suppress, bool default_stop,
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to