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
__libdwfl_debuginfod_end (dwfl->debuginfod);
#endif
+ if (dwfl->tracker != NULL)
+ __libdwfl_remove_dwfl_from_tracker (dwfl);
+
if (dwfl->process)
__libdwfl_process_free (dwfl->process);
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)
}
dwfltracker_elftab_init (&tracker->elftab, HTAB_DEFAULT_SIZE);
+ dwfltracker_dwfltab_init (&tracker->dwfltab, HTAB_DEFAULT_SIZE);
tracker->callbacks = callbacks;
return 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)
}
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);
}
-
--- /dev/null
+#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"
--- /dev/null
+#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
#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 */
} 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