Changes for v2:

- Add locking for dwfltab.

* * *

New function that retrieves the Dwfl for a particular PID, or,
if the Dwfl is absent, creates it via a provided callback
and adds it to the table later, when the PID is confirmed
via dwfl_attach_state.

* libdwfl/libdwfl.h (dwfl_process_tracker_find_pid): New function.
* libdwfl/dwfl_process_tracker.h (dwfl_process_tracker_find_pid):
  New function; find a Dwfl in the dwfltab or create one using the
  provided callback.  The newly created Dwfl will be added to the
  dwfltab automatically when its pid is confirmed by a call to
  dwfl_attach_state.
* libdw/libdw.map: Add dwfl_process_tracker_find_pid.
---
 libdw/libdw.map                |  1 +
 libdwfl/dwfl_process_tracker.c | 26 ++++++++++++++++++++++++++
 libdwfl/libdwfl.h              | 11 +++++++++++
 3 files changed, 38 insertions(+)

diff --git a/libdw/libdw.map b/libdw/libdw.map
index a52d1b87..99fd9105 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -393,4 +393,5 @@ ELFUTILS_0.193 {
     dwfl_begin_with_tracker;
     dwfl_process_tracker_end;
     dwfl_process_tracker_find_elf;
+    dwfl_process_tracker_find_pid;
 } ELFUTILS_0.192;
diff --git a/libdwfl/dwfl_process_tracker.c b/libdwfl/dwfl_process_tracker.c
index dd93f16e..caf6a8ff 100644
--- a/libdwfl/dwfl_process_tracker.c
+++ b/libdwfl/dwfl_process_tracker.c
@@ -67,6 +67,32 @@ Dwfl *dwfl_begin_with_tracker (Dwfl_Process_Tracker *tracker)
   return dwfl;
 }
 
+Dwfl *dwfl_process_tracker_find_pid (Dwfl_Process_Tracker *tracker,
+                                    pid_t pid,
+                                    Dwfl *(*callback) (Dwfl_Process_Tracker *,
+                                                       pid_t, void *),
+                                    void *arg)
+{
+  Dwfl *dwfl = NULL;
+
+  rwlock_rdlock (tracker->dwfltab_lock);
+  dwfltracker_dwfl_info *ent = dwfltracker_dwfltab_find(&tracker->dwfltab, 
pid);
+  rwlock_unlock (tracker->dwfltab_lock);
+
+  if (ent != NULL && !ent->invalid)
+    dwfl = ent->dwfl;
+  if (dwfl == NULL && callback != NULL)
+    dwfl = callback(tracker, pid, arg);
+  if (dwfl != NULL)
+    {
+      assert (dwfl->tracker == tracker);
+      /* XXX: dwfl added to dwfltab when dwfl->process set in 
dwfl_attach_state.
+         Prior to that, the pid is not confirmed. */
+    }
+
+  return dwfl;
+}
+
 void __libdwfl_add_dwfl_to_tracker (Dwfl *dwfl) {
   Dwfl_Process_Tracker *tracker = dwfl->tracker;
   assert (tracker != NULL);
diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
index a4408a26..64b3ee82 100644
--- a/libdwfl/libdwfl.h
+++ b/libdwfl/libdwfl.h
@@ -133,6 +133,17 @@ extern Dwfl_Process_Tracker *dwfl_process_tracker_begin 
(const Dwfl_Callbacks *c
 extern Dwfl *dwfl_begin_with_tracker (Dwfl_Process_Tracker *tracker)
   __nonnull_attribute__ (1);
 
+/* Find the Dwfl corresponding to PID.  If CALLBACK is non-NULL
+   and the Dwfl has not been created, invoke CALLBACK to create
+   the Dwfl and then store it in the tracker.  */
+extern Dwfl *dwfl_process_tracker_find_pid (Dwfl_Process_Tracker *tracker,
+                                            pid_t pid,
+                                            Dwfl *(*callback) 
(Dwfl_Process_Tracker *tracker,
+                                                               pid_t pid,
+                                                               void *arg),
+                                            void *arg)
+  __nonnull_attribute__ (1);
+
 /* End a multi-process session.  */
 extern void dwfl_process_tracker_end (Dwfl_Process_Tracker *tracker);
 
-- 
2.47.0

Reply via email to