]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
fixup for DRAFT e38ce78: switch to using lib/dynamicsizehash_concurrent.c
authorSerhei Makarov <serhei@serhei.io>
Fri, 7 Feb 2025 21:45:41 +0000 (16:45 -0500)
committerSerhei Makarov <serhei@serhei.io>
Fri, 7 Feb 2025 21:46:23 +0000 (16:46 -0500)
libdwfl/Makefile.am
libdwfl/dwfl_module_getdwarf.c
libdwfl/dwfl_process_tracker.c
libdwfl/dwfl_process_tracker_elftab.c [new file with mode: 0644]
libdwfl/dwfl_process_tracker_elftab.h [new file with mode: 0644]
libdwfl/dwfl_process_tracker_find_elf.c
libdwfl/libdwflP.h
libdwfl/libdwfl_next_prime.c [new file with mode: 0644]

index 78760e875a61e6ff97db1c3872c6a1917ac28bfb..b6762ffba505295c48a392e0b261c4ed8a263ed0 100644 (file)
@@ -72,6 +72,7 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \
                    dwfl_frame.c frame_unwind.c dwfl_frame_pc.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 \
                    gzip.c debuginfod-client.c
 
 if BZLIB
index 6aa87fdfda309cdcb580a5e0f6f9c08d2c693aa0..ed5846592208b5dbac3c7111bd8f6180795107af 100644 (file)
@@ -82,11 +82,11 @@ open_elf (Dwfl_Module *mod, struct dwfl_file *file)
   /* Cache file->elf in Dwfl_Process_Tracker if available: */
   if (mod->dwfl->tracker != NULL && file->name != NULL)
     {
-      dwfltracker_elftab_ent *ent = __libdwfl_process_tracker_elftab_find (mod->dwfl->tracker, file->name, false/* should_resize */);
+      dwfltracker_elf_info *ent = dwfltracker_elftab_find (&mod->dwfl->tracker->elftab, elf_hash(file->name));
       if (ent != NULL)
        {
          /* assert(ent->elf == NULL || ent->elf == file->elf); */ /* TODO(PRERELEASE): Guard against redundant/leaked Elf *. */
-         assert(ent->fd == file->fd); /* TODO(PRERELEASE): Guard against redundant open. */
+         /* assert(ent->fd == file->fd); */ /* TODO(PRERELEASE): Guard against redundant open. */
          ent->elf = file->elf;
        }
     }
index c332779d1e9f09117cb979c5bdda6a93bb865570..8132e57dd788036deaa6e2fa397af936fd989df1 100644 (file)
@@ -33,7 +33,6 @@
 #include "libdwflP.h"
 
 #define HTAB_DEFAULT_SIZE 1021
-extern size_t next_prime (size_t); /* XXX from libeu.a lib/next_prime.c */
 
 Dwfl_Process_Tracker *dwfl_process_tracker_begin (const Dwfl_Callbacks *callbacks)
 {
@@ -44,10 +43,7 @@ Dwfl_Process_Tracker *dwfl_process_tracker_begin (const Dwfl_Callbacks *callback
       return tracker;
     }
 
-  /* XXX based on lib/dynamicsizehash.* *_init */
-  tracker->elftab_size = HTAB_DEFAULT_SIZE;
-  tracker->elftab_filled = 0;
-  tracker->elftab = calloc ((tracker->elftab_size + 1), sizeof(tracker->elftab[0]));
+  dwfltracker_elftab_init (&tracker->elftab, HTAB_DEFAULT_SIZE);
 
   tracker->callbacks = callbacks;
   return tracker;
@@ -69,114 +65,26 @@ void dwfl_process_tracker_end (Dwfl_Process_Tracker *tracker)
   if (tracker == NULL)
     return;
 
-  for (unsigned idx = 1; idx < tracker->elftab_size; 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++)
     {
-      dwfltracker_elftab_ent *t = &tracker->elftab[idx];
-      if (!DWFL_ELFTAB_ENT_USED(t))
+      dwfltracker_elftab_ent *ent = &tracker->elftab.table[idx];
+      if (ent->hashval == 0)
        continue;
+      dwfltracker_elf_info *t = (dwfltracker_elf_info *) atomic_load_explicit (&ent->val_ptr,
+                                                                              memory_order_relaxed);
+      free(t->module_name);
       if (t->fd >= 0)
        close(t->fd);
-      free(t->module_name);
-      elf_end(t->elf);
+      if (t->elf != NULL)
+       elf_end(t->elf);
+      free(t); /* TODO: Check necessity. */
     }
-  free(tracker->elftab);
+  free (tracker->elftab.table);
 
   /* TODO: Call dwfl_end for each Dwfl connected to this tracker. */
   free (tracker);
 }
 
-/* XXX based on lib/dynamicsizehash.* insert_entry_2 */
-bool
-__libdwfl_process_tracker_elftab_resize (Dwfl_Process_Tracker *tracker)
-{
-  ssize_t old_size = tracker->elftab_size;
-  dwfltracker_elftab_ent *oldtab = tracker->elftab;
-  tracker->elftab_size = next_prime (tracker->elftab_size * 2);
-  tracker->elftab = calloc ((tracker->elftab_size + 1), sizeof(tracker->elftab[0]));
-  if (tracker->elftab == NULL)
-    {
-      tracker->elftab_size = old_size;
-      tracker->elftab = oldtab;
-      return false;
-    }
-  tracker->elftab_filled = 0;
-  /* Transfer the old entries to the new table. */
-  for (ssize_t idx = 1; idx <= old_size; ++idx)
-    if (DWFL_ELFTAB_ENT_USED(&oldtab[idx]))
-      {
-       dwfltracker_elftab_ent *ent0 = &oldtab[idx];
-       dwfltracker_elftab_ent *ent1 = __libdwfl_process_tracker_elftab_find(tracker, ent0->module_name, false/* should_resize */);
-       assert (ent1 != NULL);
-       memcpy (ent1, ent0, sizeof(dwfltracker_elftab_ent));
-      }
-  free(oldtab);
-  return true;
-}
-
-/* TODO: Hashing is tentative, consider direct use of lib/dynamicsizehash_concurrent.c for this. */
-ssize_t
-djb2_hash (const char *str)
-{
-  unsigned long hash = 5381;
-  int c;
-
-  while ((c = *str++))
-    hash = ((hash << 5) + hash) ^ c; /* hash * 33 XOR c */
-
-  ssize_t shash = (ssize_t)hash;
-  if (shash < 0) shash = -shash;
-  return shash;
-}
-
-/* XXX based on lib/dynamicsizehash.* *_find */
-dwfltracker_elftab_ent *
-__libdwfl_process_tracker_elftab_find (Dwfl_Process_Tracker *tracker,
-                                      const char *module_name,
-                                      bool should_resize)
-{
-  dwfltracker_elftab_ent *htab = tracker->elftab;
-  ssize_t hval = djb2_hash(module_name);
-  ssize_t idx = 1 + (hval < tracker->elftab_size ? hval : hval % tracker->elftab_size);
-
-  if (!DWFL_ELFTAB_ENT_USED(&htab[idx]))
-    goto found;
-  if (strcmp(htab[idx].module_name, module_name) == 0)
-    goto found;
-
-  int64_t hash = 1 + hval % (tracker->elftab_size - 2);
-  do
-    {
-      if (idx <= hash)
-       idx = tracker->elftab_size + idx - hash;
-      else
-       idx -= hash;
-
-      if (!DWFL_ELFTAB_ENT_USED(&htab[idx]))
-       goto found;
-      if (strcmp(htab[idx].module_name, module_name) == 0)
-       goto found;
-    }
-  while (true);
-
- found:
-  if (!DWFL_ELFTAB_ENT_USED(&htab[idx]))
-    {
-      if (100 * tracker->elftab_filled > 90 * tracker->elftab_size)
-       {
-         if (!should_resize || !__libdwfl_process_tracker_elftab_resize (tracker))
-           return NULL;
-       }
-      /* XXX Caller is responsible for setting module_name,
-        calling __libdwfl_process_tracker_elftab_mark_used;
-         not guaranteed that caller will want to do this. */
-    }
-  return &htab[idx];
-}
-
-void
-__libdwfl_process_tracker_elftab_mark_used (Dwfl_Process_Tracker *tracker,
-                                           const dwfltracker_elftab_ent *ent)
-{
-  assert(DWFL_ELFTAB_ENT_USED(ent));
-  tracker->elftab_filled ++;
-}
diff --git a/libdwfl/dwfl_process_tracker_elftab.c b/libdwfl/dwfl_process_tracker_elftab.c
new file mode 100644 (file)
index 0000000..16b2ff5
--- /dev/null
@@ -0,0 +1,22 @@
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <string.h>
+
+#include <libdwflP.h>
+
+/* Definitions for the Elf table. */
+#define TYPE dwfltracker_elf_info *
+#define NAME dwfltracker_elftab
+#define ITERATE 1
+/* TODO: Need REVERSE? */
+#define REVERSE 1
+#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;
+
+#include "../lib/dynamicsizehash_concurrent.c"
+/* TODO: Need to share this definition with dwfl_process_tracker_dwfltab -- move to libdwfl_next_prime.c */
diff --git a/libdwfl/dwfl_process_tracker_elftab.h b/libdwfl/dwfl_process_tracker_elftab.h
new file mode 100644 (file)
index 0000000..65ffa90
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef DWFL_PROCESS_TRACKER_ELFTAB_H
+#define DWFL_PROCESS_TRACKER_ELFTAB_H 1
+
+/* Definitions for the Elf table.  */
+#define TYPE dwfltracker_elf_info *
+#define NAME dwfltracker_elftab
+#define ITERATE 1
+#define COMPARE(a, b) \
+  strcmp ((a)->module_name, (b)->module_name)
+#include <dynamicsizehash_concurrent.h>
+
+#endif
index 20c48beacb570e1713afba7bb1f434186c30e100..d62d24d7d5336a01f2287ce989c94111c281d796 100644 (file)
@@ -44,35 +44,38 @@ dwfl_process_tracker_find_elf (Dwfl_Module *mod,
   /* TODO(WIP): Do we need to handle if elfp is already set?? */
   assert (*elfp == NULL);
   Dwfl_Process_Tracker *tracker = mod->dwfl->tracker;
-  dwfltracker_elftab_ent *ent = NULL;
+  dwfltracker_elf_info *ent = NULL;
   int rc;
   struct stat sb;
 
   if (tracker != NULL)
     {
-      ent = __libdwfl_process_tracker_elftab_find(tracker, module_name,
-                                                 true/*should_resize*/);
-      /* TODO: Also reopen the file when module_name set but fd not set? */
-      if (DWFL_ELFTAB_ENT_USED(ent))
+      unsigned long int hval = elf_hash(module_name);
+      ent = dwfltracker_elftab_find(&tracker->elftab, hval);
+      if (ent != NULL)
        {
+         /* TODO: Also reopen the file when module_name set but fd not set? */
          rc = fstat(ent->fd, &sb);
          if (rc < 0 || ent->dev != sb.st_dev || ent->ino != sb.st_ino
              || ent->last_mtime != sb.st_mtime)
-             ent = NULL; /* file modified, fall back to uncached behaviour */
+           ent = NULL; /* file modified, fall back to uncached behaviour */
          else
            {
              *elfp = ent->elf;
              *file_name = strdup(ent->module_name);
-             return ent->fd;
            }
        }
-      else if (ent->module_name == NULL)
+      else
        {
-         /* TODO: For multithreaded access, we mark used here rather
-            than after the dwfl_linux_proc_find_elf() call.  Need to
-            add appropriate locking.  */
+         ent = calloc (1, sizeof (dwfltracker_elf_info));
          ent->module_name = strdup(module_name);
-         __libdwfl_process_tracker_elftab_mark_used(tracker, ent);
+         if (dwfltracker_elftab_insert(&tracker->elftab, hval, ent) != 0)
+           {
+             free(ent->module_name);
+             free(ent);
+             ent = NULL; /* fall back to uncached behaviour */
+             /* TODO(WIP): Could goto and repeat the find operation? */
+           }
        }
     }
 
@@ -82,6 +85,7 @@ dwfl_process_tracker_find_elf (Dwfl_Module *mod,
   /* XXX fd < 0 implies elf_from_remote_memory, uses base, not cacheable */
   if (tracker != NULL && ent != NULL && fd >= 0 && *file_name != NULL)
     {
+      /* TODO(WIP): *elfp may be NULL here, need to be populated later. */
       ent->elf = *elfp;
       ent->fd = fd;
       rc = fstat(fd, &sb);
index f40f77203e0c29a896478e04e9938ded14a432cc..13d943509c5a398ab9558ad1c3f589d35695277e 100644 (file)
@@ -101,7 +101,7 @@ typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
 extern int __libdwfl_canon_error (Dwfl_Error) internal_function;
 extern void __libdwfl_seterrno (Dwfl_Error) internal_function;
 
-#define DWFL_ELFTAB_ENT_USED(e) ((e)->module_name != NULL)
+/* Hash table for Elf *. */
 typedef struct
 {
   char *module_name; /* dwfltracker_elftab_ent is used iff non-NULL.  */
@@ -110,33 +110,17 @@ typedef struct
   dev_t dev;
   ino_t ino;
   time_t last_mtime;
-} dwfltracker_elftab_ent;
+} dwfltracker_elf_info;
+#include "dwfl_process_tracker_elftab.h"
 
 struct Dwfl_Process_Tracker
 {
   const Dwfl_Callbacks *callbacks;
 
   /* Table of cached Elf * including fd, path, fstat info.  */
-  ssize_t elftab_size;
-  ssize_t elftab_filled;
-  dwfltracker_elftab_ent *elftab;
+  dwfltracker_elftab elftab;
 };
 
-/* Find the location for an existing or new MODULE_NAME and return a
-   dwfl_tracker_elftab_ent * for it.  If MODULE_NAME is not found
-   and SHOULD_RESIZE is set, expand the table as necessary to make
-   room for the new entry. Otherwise, return NULL if MODULE_NAME is
-   not found.  */
-dwfltracker_elftab_ent *
-__libdwfl_process_tracker_elftab_find (Dwfl_Process_Tracker *tracker,
-                                      const char *module_name,
-                                      bool should_resize);
-
-/* After populating a dwfltracker_elftab_ent with data, update the
-   elftab_filled stats to properly mark the entry as used.  */
-void
-__libdwfl_process_tracker_elftab_mark_used (Dwfl_Process_Tracker *tracker,
-                                           const dwfltracker_elftab_ent *ent);
 
 /* Resources we might keep for the user about the core file that the
    Dwfl might have been created from.  Can currently only be set
diff --git a/libdwfl/libdwfl_next_prime.c b/libdwfl/libdwfl_next_prime.c
new file mode 100644 (file)
index 0000000..f99d4c6
--- /dev/null
@@ -0,0 +1,6 @@
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#define next_prime attribute_hidden __libdwfl_next_prime
+#include "../lib/next_prime.c"