]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
DRAWF libdwfl: Dwfl* caching via dwfl_process_tracker
authorSerhei Makarov <serhei@serhei.io>
Thu, 13 Feb 2025 21:31:54 +0000 (16:31 -0500)
committerSerhei Makarov <serhei@serhei.io>
Thu, 13 Feb 2025 21:31:54 +0000 (16:31 -0500)
* libdwfl/libdwflP.h (dwfltracker_dwfl_info): New typedef, provides
  indirection to allow a dwfltab entry to be invalidated.
  (struct Dwfl_Process_Tracker): add dwfltab.
  (__libdwfl_add_dwfl_to_tracker): New function.
  (__libdwfl_remove_dwfl_from_tracker): New function.
* libdwfl/dwfl_process_tracker_dwfltab.h: New file.
* libdwfl/dwfl_process_tracker_dwfltab.c: New file.
* libdwfl/dwfl_process_tracker.c (dwfl_process_tracker_begin): Init dwfltab.
  (__libdwfl_add_dwfl_to_tracker): New function; add dwfl to dwfltab.
  (__libdwfl_remove_dwfl_from_tracker): New function; invalidate dwfl entry.
  (dwfl_process_tracker_end): Clean up dwfltab.
* libdwfl/dwfl_frame.c (dwfl_attach_state): Call __libdwfl_add_dwfl_to_tracker.
* libdwfl/dwfl_end.c (dwfl_end): Call __libdwfl_remove_dwfl_from_tracker.
* libdwfl/Makefile.am (libdwfl_a_SOURCES): Add dwfl_process_tracker_dwfltab.c.

libdwfl/Makefile.am
libdwfl/dwfl_end.c
libdwfl/dwfl_frame.c
libdwfl/dwfl_process_tracker.c
libdwfl/dwfl_process_tracker_dwfltab.c [new file with mode: 0644]
libdwfl/dwfl_process_tracker_dwfltab.h [new file with mode: 0644]
libdwfl/dwfl_process_tracker_elftab.c
libdwfl/libdwflP.h

index b6762ffba505295c48a392e0b261c4ed8a263ed0..c85a432ef03d77f742223bba0645ace12d7fd5bb 100644 (file)
@@ -73,6 +73,7 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \
                    linux-pid-attach.c linux-core-attach.c dwfl_frame_regs.c \
                    dwfl_process_tracker.c dwfl_process_tracker_find_elf.c \
                    dwfl_process_tracker_elftab.c libdwfl_next_prime.c \
+                   dwfl_process_tracker_dwfltab.c \
                    gzip.c debuginfod-client.c
 
 if BZLIB
index 7b5ac8a1fdeb4b4acc8892b5d5340377440f62bd..97e257106c9afc1c0acb12efb5cd6a560eecaa43 100644 (file)
@@ -42,6 +42,9 @@ dwfl_end (Dwfl *dwfl)
   __libdwfl_debuginfod_end (dwfl->debuginfod);
 #endif
 
+  if (dwfl->tracker != NULL)
+    __libdwfl_remove_dwfl_from_tracker (dwfl);
+
   if (dwfl->process)
     __libdwfl_process_free (dwfl->process);
 
index 2e6c6de8028051f0be3fcb3d9c9ce33ca164f113..1e715346f8eeb1eb863f69de7c628090028e735d 100644 (file)
@@ -206,6 +206,10 @@ dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
   process->pid = pid;
   process->callbacks = thread_callbacks;
   process->callbacks_arg = arg;
+
+  if (dwfl->tracker != NULL)
+      __libdwfl_add_dwfl_to_tracker (dwfl);
+
   return true;
 }
 INTDEF(dwfl_attach_state)
index 8132e57dd788036deaa6e2fa397af936fd989df1..f1d1feb5c31333bc5e13015c459a064002719aab 100644 (file)
@@ -44,6 +44,7 @@ Dwfl_Process_Tracker *dwfl_process_tracker_begin (const Dwfl_Callbacks *callback
     }
 
   dwfltracker_elftab_init (&tracker->elftab, HTAB_DEFAULT_SIZE);
+  dwfltracker_dwfltab_init (&tracker->dwfltab, HTAB_DEFAULT_SIZE);
 
   tracker->callbacks = callbacks;
   return tracker;
@@ -55,20 +56,68 @@ Dwfl *dwfl_begin_with_tracker (Dwfl_Process_Tracker *tracker)
   if (dwfl == NULL)
     return dwfl;
 
-  /* TODO: Could also share dwfl->debuginfod, but thead-safely? */
+  /* TODO: Could also share dwfl->debuginfod, but thread-safely? */
   dwfl->tracker = tracker;
+
+  /* XXX: dwfl added to dwfltab when dwfl->process set in dwfl_attach_state. */
+  /* XXX: dwfl removed from dwfltab in dwfl_end() */
+
   return dwfl;
 }
 
+void __libdwfl_add_dwfl_to_tracker (Dwfl *dwfl) {
+  Dwfl_Process_Tracker *tracker = dwfl->tracker;
+  assert (tracker != NULL);
+
+  /* First try to find an existing entry to replace: */
+  dwfltracker_dwfl_info *ent = NULL;
+  unsigned long int hval = dwfl->process->pid;
+  ent = dwfltracker_dwfltab_find(&tracker->dwfltab, hval);
+  if (ent != NULL)
+    {
+      ent->dwfl = dwfl;
+      ent->invalid = false;
+      return;
+    }
+
+  /* Only otherwise try to insert an entry: */
+  ent = calloc (1, sizeof(dwfltracker_dwfl_info));
+  ent->dwfl = dwfl;
+  ent->invalid = false;
+  if (dwfltracker_dwfltab_insert(&tracker->dwfltab, hval, ent) != 0)
+    {
+      /* assert(false); */ /* TODO: Need additional locking to guard against this case. */
+      free(ent);
+      return;
+    }
+}
+
+void __libdwfl_remove_dwfl_from_tracker (Dwfl *dwfl) {
+  if (dwfl->tracker == NULL)
+    return;
+  Dwfl_Process_Tracker *tracker = dwfl->tracker;
+
+  dwfltracker_dwfl_info *ent = NULL;
+  unsigned long int hval = dwfl->process->pid;
+  ent = dwfltracker_dwfltab_find(&tracker->dwfltab, hval);
+  if (ent != NULL && ent->dwfl == dwfl)
+    {
+      ent->dwfl = NULL;
+      ent->invalid = true;
+    }
+}
+
 void dwfl_process_tracker_end (Dwfl_Process_Tracker *tracker)
 {
   if (tracker == NULL)
     return;
 
-  /* HACK to allow iteration of dynamicsizehash_concurrent. */
+  size_t idx;
+
+  /* HACK to allow iteration of dynamicsizehash_concurrent.  */
   /* XXX Based on lib/dynamicsizehash_concurrent.c free().  */
   pthread_rwlock_destroy(&tracker->elftab.resize_rwl);
-  for (size_t idx = 1; idx <= tracker->elftab.size; idx++)
+  for (idx = 1; idx <= tracker->elftab.size; idx++)
     {
       dwfltracker_elftab_ent *ent = &tracker->elftab.table[idx];
       if (ent->hashval == 0)
@@ -84,7 +133,20 @@ void dwfl_process_tracker_end (Dwfl_Process_Tracker *tracker)
     }
   free (tracker->elftab.table);
 
-  /* TODO: Call dwfl_end for each Dwfl connected to this tracker. */
+  /* XXX Based on lib/dynamicsizehash_concurrent.c free().  */
+  pthread_rwlock_destroy(&tracker->dwfltab.resize_rwl);
+  for (idx = 1; idx <= tracker->dwfltab.size; idx++)
+    {
+      dwfltracker_dwfltab_ent *ent = &tracker->dwfltab.table[idx];
+      if (ent->hashval == 0)
+       continue;
+      dwfltracker_dwfl_info *t = (dwfltracker_dwfl_info *) atomic_load_explicit (&ent->val_ptr,
+                                                                                memory_order_relaxed);
+      if (t->dwfl != NULL)
+       dwfl_end(t->dwfl);
+      free(t);
+    }
+  free (tracker->dwfltab.table);
+
   free (tracker);
 }
-
diff --git a/libdwfl/dwfl_process_tracker_dwfltab.c b/libdwfl/dwfl_process_tracker_dwfltab.c
new file mode 100644 (file)
index 0000000..79e3725
--- /dev/null
@@ -0,0 +1,22 @@
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <libdwflP.h>
+
+/* Definitions for the Dwfl table. */
+#define TYPE dwfltracker_dwfl_info *
+#define NAME dwfltracker_dwfltab
+#define ITERATE 1
+/* TODO: Need REVERSE? */
+#define REVERSE 1
+#define COMPARE(a, b) \
+  ((a->invalid && b->invalid) || \
+   (!a->invalid && !b->invalid && \
+    (a)->dwfl->process->pid == (b)->dwfl->process->pid))
+
+/* TODO needed? */
+/* #define next_prime __libdwfl_next_prime */
+/* extern size_t next_prime (size_t) attribute_hidden; */
+
+#include "../lib/dynamicsizehash_concurrent.c"
diff --git a/libdwfl/dwfl_process_tracker_dwfltab.h b/libdwfl/dwfl_process_tracker_dwfltab.h
new file mode 100644 (file)
index 0000000..de13c21
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef DWFL_PROCESS_TRACKER_DWFLTAB_H
+#define DWFL_PROCESS_TRACKER_DWFLTAB_H 1
+
+/* Definitions for the Dwfl table.  */
+#define TYPE dwfltracker_dwfl_info *
+#define NAME dwfltracker_dwfltab
+#define ITERATE 1
+#define COMPARE(a, b) \
+  ((a->invalid && b->invalid) || \
+   (!a->invalid && !b->invalid && \
+    (a)->dwfl->process->pid == (b)->dwfl->process->pid))
+#include <dynamicsizehash_concurrent.h>
+
+#endif
index 16b2ff54b99c8c8e1e2dbfc28addf6b8744fa2aa..16a60f6c597e5960e6234ea38f180d02d43b0d85 100644 (file)
@@ -15,8 +15,8 @@
 #define COMPARE(a, b) \
   strcmp ((a)->module_name, (b)->module_name)
 
-#define next_prime __libdwfl_next_prime
-extern size_t next_prime (size_t) attribute_hidden;
+/* TODO needed? */
+/* #define next_prime __libdwfl_next_prime */
+/* extern size_t next_prime (size_t) attribute_hidden; */
 
 #include "../lib/dynamicsizehash_concurrent.c"
-/* TODO: Need to share this definition with dwfl_process_tracker_dwfltab -- move to libdwfl_next_prime.c */
index 13d943509c5a398ab9558ad1c3f589d35695277e..95d5415b05599541340a26f5ae31f4ba641f8b69 100644 (file)
@@ -113,14 +113,32 @@ typedef struct
 } dwfltracker_elf_info;
 #include "dwfl_process_tracker_elftab.h"
 
+/* Hash table for Dwfl *. */
+typedef struct
+{
+  Dwfl *dwfl;
+  bool invalid; /* Mark when the dwfl has been removed.  */
+} dwfltracker_dwfl_info;
+#include "dwfl_process_tracker_dwfltab.h"
+
 struct Dwfl_Process_Tracker
 {
   const Dwfl_Callbacks *callbacks;
 
   /* Table of cached Elf * including fd, path, fstat info.  */
   dwfltracker_elftab elftab;
+
+  /* Table of cached Dwfl * including pid.  */
+  dwfltracker_dwfltab dwfltab;
 };
 
+/* Call when dwfl->process->pid becomes known to add the dwfl to its
+   Dwfl_Process_Tracker's dwfltab:  */
+void __libdwfl_add_dwfl_to_tracker (Dwfl *dwfl);
+
+/* Call from dwlf_ent() to remove the dwfl from its
+   Dwfl_Process_Tracker's dwfltab:  */
+void __libdwfl_remove_dwfl_from_tracker (Dwfl *dwfl);
 
 /* Resources we might keep for the user about the core file that the
    Dwfl might have been created from.  Can currently only be set