From b7d1fd011c0b21c43418edbabc4a438facfc436c Mon Sep 17 00:00:00 2001 From: Serhei Makarov Date: Fri, 7 Feb 2025 16:45:41 -0500 Subject: [PATCH] fixup for DRAFT e38ce78: switch to using lib/dynamicsizehash_concurrent.c --- libdwfl/Makefile.am | 1 + libdwfl/dwfl_module_getdwarf.c | 4 +- libdwfl/dwfl_process_tracker.c | 120 +++--------------------- libdwfl/dwfl_process_tracker_elftab.c | 22 +++++ libdwfl/dwfl_process_tracker_elftab.h | 12 +++ libdwfl/dwfl_process_tracker_find_elf.c | 28 +++--- libdwfl/libdwflP.h | 24 +---- libdwfl/libdwfl_next_prime.c | 6 ++ 8 files changed, 77 insertions(+), 140 deletions(-) create mode 100644 libdwfl/dwfl_process_tracker_elftab.c create mode 100644 libdwfl/dwfl_process_tracker_elftab.h create mode 100644 libdwfl/libdwfl_next_prime.c diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am index 78760e87..b6762ffb 100644 --- a/libdwfl/Makefile.am +++ b/libdwfl/Makefile.am @@ -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 diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c index 6aa87fdf..ed584659 100644 --- a/libdwfl/dwfl_module_getdwarf.c +++ b/libdwfl/dwfl_module_getdwarf.c @@ -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; } } diff --git a/libdwfl/dwfl_process_tracker.c b/libdwfl/dwfl_process_tracker.c index c332779d..8132e57d 100644 --- a/libdwfl/dwfl_process_tracker.c +++ b/libdwfl/dwfl_process_tracker.c @@ -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 index 00000000..16b2ff54 --- /dev/null +++ b/libdwfl/dwfl_process_tracker_elftab.c @@ -0,0 +1,22 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include + +/* 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 index 00000000..65ffa909 --- /dev/null +++ b/libdwfl/dwfl_process_tracker_elftab.h @@ -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 + +#endif diff --git a/libdwfl/dwfl_process_tracker_find_elf.c b/libdwfl/dwfl_process_tracker_find_elf.c index 20c48bea..d62d24d7 100644 --- a/libdwfl/dwfl_process_tracker_find_elf.c +++ b/libdwfl/dwfl_process_tracker_find_elf.c @@ -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); diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index f40f7720..13d94350 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -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 index 00000000..f99d4c6c --- /dev/null +++ b/libdwfl/libdwfl_next_prime.c @@ -0,0 +1,6 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#define next_prime attribute_hidden __libdwfl_next_prime +#include "../lib/next_prime.c" -- 2.47.2