vlib: add clib_stack_frame_get_raw() 91/41691/2
authorBenoît Ganne <[email protected]>
Tue, 8 Oct 2024 14:43:12 +0000 (16:43 +0200)
committerBeno�t Ganne <[email protected]>
Wed, 13 Nov 2024 13:02:30 +0000 (13:02 +0000)
clib_stack_frame_get() is getting the backtrace for all threads and
does symbol resolution which is too slow for certain features (eg.
memory traces).
clib_stack_frame_get_raw() only gets the local backtrace and defer
symbol resolution only when displaying results.

Type: improvement

Change-Id: Ia374d86e9175b6648a39ed5aaa676ceb7235e877
Signed-off-by: Benoît Ganne <[email protected]>
src/vppinfra/mem.h
src/vppinfra/mem_dlmalloc.c
src/vppinfra/stack.c
src/vppinfra/stack.h

index ab9c5da..6211bb5 100644 (file)
@@ -302,7 +302,7 @@ void clib_mem_exit (void);
 typedef struct
 {
   /* Address of callers: outer first, inner last. */
-  uword callers[12];
+  void *callers[12];
 
   /* Count of allocations with this traceback. */
   u32 n_allocations;
index d5ff21e..7944240 100644 (file)
@@ -53,7 +53,7 @@ mheap_get_trace_internal (const clib_mem_heap_t *heap, uword offset,
   mheap_trace_t *t;
   uword i, trace_index, *p;
   mheap_trace_t trace = {};
-  int index;
+  int n_callers;
 
   if (heap != tm->current_traced_mheap || mheap_trace_thread_disable)
     return;
@@ -67,19 +67,10 @@ mheap_get_trace_internal (const clib_mem_heap_t *heap, uword offset,
   /* Turn off tracing for this thread to avoid embarrassment... */
   mheap_trace_thread_disable = 1;
 
-  index = -2; /* skip first 2 stack frames */
-  foreach_clib_stack_frame (sf)
-    {
-      if (index >= 0)
-       {
-         if (index == ARRAY_LEN (trace.callers))
-           break;
-         trace.callers[index] = sf->ip;
-       }
-      index++;
-    }
-
-  if (index < 1)
+  /* Skip our frame and mspace_get_aligned's frame */
+  n_callers =
+    clib_stack_frame_get_raw (trace.callers, ARRAY_LEN (trace.callers), 2);
+  if (n_callers == 0)
     goto out;
 
   if (!tm->trace_by_callers)
index 190e880..12b24e3 100644 (file)
 static __thread unw_cursor_t cursor;
 static __thread unw_context_t context;
 
-#endif
+#endif /* HAVE_LIBUNWIND */
+
+__clib_export int
+clib_stack_frame_get_raw (void **sf, int n, int skip)
+{
+#if HAVE_LIBUNWIND == 1
+  void *sf__[20];
+  int n__;
+
+  /* Also skip current frame. */
+  skip++;
+  n__ = unw_backtrace (sf__, clib_min (ARRAY_LEN (sf__), n + skip));
+
+  if (n__ <= skip)
+    return 0;
+  else if (n__ - skip < n)
+    n = n__ - skip;
+
+  clib_memcpy_fast (&sf[0], &sf__[skip], n * sizeof (sf[0]));
+  return n;
+#else  /* HAVE_LIBUNWIND */
+  return 0;
+#endif /* HAVE_LIBUNWIND */
+}
 
 __clib_export clib_stack_frame_t *
 clib_stack_frame_get (clib_stack_frame_t *sf)
index 98a621d..5b833a3 100644 (file)
@@ -17,6 +17,7 @@ typedef struct
   u8 is_signal_frame;
 } clib_stack_frame_t;
 
+int clib_stack_frame_get_raw (void **sf, int n, int skip);
 clib_stack_frame_t *clib_stack_frame_get (clib_stack_frame_t *);
 
 #define foreach_clib_stack_frame(sf)                                          \