[sysprof/wip/chergert/control-fd] capture: simplify collector interface



commit cc2c202cd868840112029eeacd843f1e8ffaf54e
Author: Christian Hergert <chergert redhat com>
Date:   Sat Feb 8 09:31:16 2020 -0800

    capture: simplify collector interface
    
    This allows us to discover a few scenarios for which might require locking
    among contributor threads (when a single capture file is necessary). The
    common case, however, should be a multi-threaded capture writing without
    locking (using a writer in TLS) which is muxed by Sysprof after the
    capture has completed.

 src/libsysprof-capture/sysprof-collector.c | 354 ++++++++++++++---------------
 src/libsysprof-capture/sysprof-collector.h |  77 +++----
 2 files changed, 207 insertions(+), 224 deletions(-)
---
diff --git a/src/libsysprof-capture/sysprof-collector.c b/src/libsysprof-capture/sysprof-collector.c
index e60655c..8239dc0 100644
--- a/src/libsysprof-capture/sysprof-collector.c
+++ b/src/libsysprof-capture/sysprof-collector.c
@@ -75,12 +75,13 @@
 #include "sysprof-capture-writer.h"
 #include "sysprof-collector.h"
 
-struct _SysprofCollector
+typedef struct
 {
   SysprofCaptureWriter *writer;
+  gboolean is_shared;
   int tid;
   int pid;
-};
+} SysprofCollector;
 
 #ifdef __linux__
 # define sysprof_current_cpu (sched_getcpu())
@@ -88,21 +89,27 @@ struct _SysprofCollector
 # define sysprof_current_cpu (-1)
 #endif
 
-static SysprofCaptureWriter *request_writer         (void);
-static void                  sysprof_collector_free (gpointer data);
-static SysprofCollector     *sysprof_collector_get  (void);
+static SysprofCaptureWriter   *request_writer         (void);
+static void                    sysprof_collector_free (gpointer data);
+static const SysprofCollector *sysprof_collector_get  (void);
 
+static G_LOCK_DEFINE (control_fd);
 static GPrivate collector_key = G_PRIVATE_INIT (sysprof_collector_free);
+static GPrivate single_trace_key = G_PRIVATE_INIT (NULL);
+static SysprofCollector *shared_collector;
+
+static inline gboolean
+use_single_trace (void)
+{
+  return GPOINTER_TO_INT (g_private_get (&single_trace_key));
+}
 
 static SysprofCaptureWriter *
 request_writer (void)
 {
-  static G_LOCK_DEFINE (control_fd);
   static GDBusConnection *peer;
   SysprofCaptureWriter *writer = NULL;
 
-  G_LOCK (control_fd);
-
   if (peer == NULL)
     {
       const gchar *fdstr = g_getenv ("SYSPROF_CONTROL_FD");
@@ -171,8 +178,6 @@ request_writer (void)
         }
     }
 
-  G_UNLOCK (control_fd);
-
   return g_steal_pointer (&writer);
 }
 
@@ -189,228 +194,221 @@ sysprof_collector_free (gpointer data)
     }
 }
 
-static SysprofCollector *
+static const SysprofCollector *
 sysprof_collector_get (void)
 {
-  SysprofCollector *collector = g_private_get (&collector_key);
+  const SysprofCollector *collector = g_private_get (&collector_key);
 
-  if G_UNLIKELY (collector == NULL)
-    {
-      collector = g_slice_new0 (SysprofCollector);
-      collector->writer = request_writer ();
-      collector->pid = getpid ();
+  if G_LIKELY (collector != NULL)
+    return collector;
+
+  if (use_single_trace () && shared_collector != NULL)
+    return shared_collector;
+
+  {
+    SysprofCollector *self;
+
+    G_LOCK (control_fd);
+
+    self = g_slice_new0 (SysprofCollector);
+    self->pid = getpid ();
 #ifdef __linux__
-      collector->tid = syscall (__NR_gettid, 0);
+    self->tid = syscall (__NR_gettid, 0);
 #endif
-      g_private_replace (&collector_key, collector);
-    }
 
-  return collector;
+    /* If we are not profiling under Sysprof directly, then we want to
+     * require synchronization from our threads to a single writer which
+     * matches "capture.$pid.syscap".
+     */
+    if (g_getenv ("SYSPROF_CONTROL_FD") != NULL)
+      {
+        self->writer = request_writer ();
+      }
+    else
+      {
+        /* TODO: Fix envvar name */
+        const gchar *trace_fd = g_getenv ("SYSPROF_TRACE_FD");
+
+        if (trace_fd != NULL)
+          {
+            int fd = atoi (trace_fd);
+
+            if (fd > 0)
+              {
+                self->writer = sysprof_capture_writer_new_from_fd (fd, 0);
+                self->is_shared = TRUE;
+              }
+          }
+
+        if (self->writer == NULL && g_getenv ("SYSPROF_TRACE") != NULL)
+          {
+            g_autofree gchar *filename = g_strdup_printf ("capture.%d.syscap", (int)getpid ());
+
+            self->writer = sysprof_capture_writer_new (filename, 0);
+            self->is_shared = TRUE;
+          }
+      }
+
+    if (self->is_shared)
+      shared_collector = self;
+    else
+      g_private_replace (&collector_key, self);
+
+    G_UNLOCK (control_fd);
+
+    return self;
+  }
 }
 
-SysprofCollector *
-sysprof_collector_get_thread_default (void)
-{
-  return sysprof_collector_get ();
-}
+#define ADD_TO_COLLECTOR(func)                                    \
+  G_STMT_START {                                                  \
+    const SysprofCollector *collector = sysprof_collector_get (); \
+    if (collector->is_shared) { G_LOCK (control_fd); }            \
+    if (collector->writer != NULL) { func; }                      \
+    if (collector->is_shared) { G_UNLOCK (control_fd); }          \
+  } G_STMT_END
 
 void
-sysprof_collector_embed_file (SysprofCollector *collector,
-                              const gchar      *path,
-                              const guint8     *data,
-                              gsize             data_len)
+sysprof_collector_embed_file (const gchar  *path,
+                              const guint8 *data,
+                              gsize         data_len)
 {
-  if (collector == NULL)
-    collector = sysprof_collector_get ();
-
-  if (collector->writer != NULL)
-    sysprof_capture_writer_add_file (collector->writer,
-                                     SYSPROF_CAPTURE_CURRENT_TIME,
-                                     sysprof_current_cpu,
-                                     collector->pid,
-                                     path,
-                                     TRUE,
-                                     data,
-                                     data_len);
+  ADD_TO_COLLECTOR (sysprof_capture_writer_add_file (collector->writer,
+                                                     SYSPROF_CAPTURE_CURRENT_TIME,
+                                                     sysprof_current_cpu,
+                                                     collector->pid,
+                                                     path,
+                                                     TRUE,
+                                                     data,
+                                                     data_len));
 }
 
 void
-sysprof_collector_embed_file_fd (SysprofCollector *collector,
-                                 const gchar      *path,
-                                 int               fd)
+sysprof_collector_embed_file_fd (const gchar *path,
+                                 int          fd)
 {
-  if (collector == NULL)
-    collector = sysprof_collector_get ();
-
-  if (collector->writer != NULL)
-    sysprof_capture_writer_add_file_fd (collector->writer,
-                                        SYSPROF_CAPTURE_CURRENT_TIME,
-                                        sysprof_current_cpu,
-                                        collector->pid,
-                                        path,
-                                        fd);
+  ADD_TO_COLLECTOR(sysprof_capture_writer_add_file_fd (collector->writer,
+                                                       SYSPROF_CAPTURE_CURRENT_TIME,
+                                                       sysprof_current_cpu,
+                                                       collector->pid,
+                                                       path,
+                                                       fd));
 }
 
 void
-sysprof_collector_mark (SysprofCollector *collector,
-                        gint64            time,
-                        guint64           duration,
-                        const gchar      *group,
-                        const gchar      *name,
-                        const gchar      *message)
+sysprof_collector_mark (gint64       time,
+                        guint64      duration,
+                        const gchar *group,
+                        const gchar *name,
+                        const gchar *message)
 {
-  if (collector == NULL)
-    collector = sysprof_collector_get ();
-
-  if (collector->writer != NULL)
-    sysprof_capture_writer_add_mark (collector->writer,
-                                     SYSPROF_CAPTURE_CURRENT_TIME,
-                                     sysprof_current_cpu,
-                                     collector->pid,
-                                     duration,
-                                     group,
-                                     name,
-                                     message);
+  ADD_TO_COLLECTOR (sysprof_capture_writer_add_mark (collector->writer,
+                                                     SYSPROF_CAPTURE_CURRENT_TIME,
+                                                     sysprof_current_cpu,
+                                                     collector->pid,
+                                                     duration,
+                                                     group,
+                                                     name,
+                                                     message));
 }
 
 void
-sysprof_collector_set_metadata (SysprofCollector *collector,
-                                const gchar      *id,
-                                const gchar      *value,
-                                gssize            value_len)
+sysprof_collector_set_metadata (const gchar *id,
+                                const gchar *value,
+                                gssize       value_len)
 {
-  if (collector == NULL)
-    collector = sysprof_collector_get ();
-
-  if (collector->writer != NULL)
-    sysprof_capture_writer_add_metadata (collector->writer,
-                                         SYSPROF_CAPTURE_CURRENT_TIME,
-                                         sysprof_current_cpu,
-                                         collector->pid,
-                                         id,
-                                         value,
-                                         value_len);
+  ADD_TO_COLLECTOR (sysprof_capture_writer_add_metadata (collector->writer,
+                                                         SYSPROF_CAPTURE_CURRENT_TIME,
+                                                         sysprof_current_cpu,
+                                                         collector->pid,
+                                                         id,
+                                                         value,
+                                                         value_len));
 }
 
 void
-sysprof_collector_sample (SysprofCollector            *collector,
-                          gint64                       time,
+sysprof_collector_sample (gint64                       time,
                           const SysprofCaptureAddress *addrs,
                           guint                        n_addrs)
 {
-  if (collector == NULL)
-    collector = sysprof_collector_get ();
-
-  if (collector->writer != NULL)
-    sysprof_capture_writer_add_sample (collector->writer,
-                                       time,
-                                       sysprof_current_cpu,
-                                       collector->pid,
-                                       collector->tid,
-                                       addrs,
-                                       n_addrs);
+  ADD_TO_COLLECTOR (sysprof_capture_writer_add_sample (collector->writer,
+                                                       time,
+                                                       sysprof_current_cpu,
+                                                       collector->pid,
+                                                       collector->tid,
+                                                       addrs,
+                                                       n_addrs));
 }
 
 void
-sysprof_collector_log (SysprofCollector *collector,
-                       GLogLevelFlags    severity,
-                       const gchar      *domain,
-                       const gchar      *message)
+sysprof_collector_log (GLogLevelFlags          severity,
+                       const gchar            *domain,
+                       const gchar            *message)
 {
-  if (collector == NULL)
-    collector = sysprof_collector_get ();
-
-  if (collector->writer != NULL)
-    sysprof_capture_writer_add_log (collector->writer,
-                                    SYSPROF_CAPTURE_CURRENT_TIME,
-                                    sysprof_current_cpu,
-                                    collector->pid,
-                                    severity,
-                                    domain,
-                                    message);
+  ADD_TO_COLLECTOR (sysprof_capture_writer_add_log (collector->writer,
+                                                    SYSPROF_CAPTURE_CURRENT_TIME,
+                                                    sysprof_current_cpu,
+                                                    collector->pid,
+                                                    severity,
+                                                    domain,
+                                                    message));
 }
 
 SysprofCaptureAddress
-sysprof_collector_map_jitted_ip (SysprofCollector *collector,
-                                 const gchar      *name)
+sysprof_collector_map_jitted_ip (const gchar *name)
 {
-  if (collector == NULL)
-    collector = sysprof_collector_get ();
-
-  if (collector->writer != NULL)
-    return sysprof_capture_writer_add_jitmap (collector->writer, name);
-
-  return 0;
+  SysprofCaptureAddress ret = 0;
+  ADD_TO_COLLECTOR ((ret = sysprof_capture_writer_add_jitmap (collector->writer, name)));
+  return ret;
 }
 
 void
-sysprof_collector_allocate (SysprofCollector      *collector,
-                            SysprofCaptureAddress  alloc_addr,
-                            gint64                 alloc_size,
-                            SysprofBacktraceFunc   backtrace_func,
-                            gpointer               backtrace_data)
+sysprof_collector_allocate (SysprofCaptureAddress   alloc_addr,
+                            gint64                  alloc_size,
+                            SysprofBacktraceFunc    backtrace_func,
+                            gpointer                backtrace_data)
 {
-  if (collector == NULL)
-    collector = sysprof_collector_get ();
-
-  if (collector->writer != NULL)
-    sysprof_capture_writer_add_allocation (collector->writer,
-                                           SYSPROF_CAPTURE_CURRENT_TIME,
-                                           sysprof_current_cpu,
-                                           collector->pid,
-                                           collector->tid,
-                                           alloc_addr,
-                                           alloc_size,
-                                           backtrace_func,
-                                           backtrace_data);
+  ADD_TO_COLLECTOR (sysprof_capture_writer_add_allocation (collector->writer,
+                                                           SYSPROF_CAPTURE_CURRENT_TIME,
+                                                           sysprof_current_cpu,
+                                                           collector->pid,
+                                                           collector->tid,
+                                                           alloc_addr,
+                                                           alloc_size,
+                                                           backtrace_func,
+                                                           backtrace_data));
 }
 
 guint
-sysprof_collector_reserve_counters (SysprofCollector *collector,
-                                    guint             n_counters)
+sysprof_collector_reserve_counters (guint n_counters)
 {
-  if (collector == NULL)
-    collector = sysprof_collector_get ();
-
-  if (collector->writer != NULL)
-    return sysprof_capture_writer_request_counter (collector->writer,
-                                                   n_counters);
-
-  return 1;
+  guint ret = 1;
+  ADD_TO_COLLECTOR ((ret = sysprof_capture_writer_request_counter (collector->writer, n_counters)));
+  return ret;
 }
 
 void
-sysprof_collector_define_counters (SysprofCollector            *collector,
-                                   const SysprofCaptureCounter *counters,
+sysprof_collector_define_counters (const SysprofCaptureCounter *counters,
                                    guint                        n_counters)
 {
-  if (collector == NULL)
-    collector = sysprof_collector_get ();
-
-  if (collector->writer != NULL)
-    sysprof_capture_writer_define_counters (collector->writer,
-                                            SYSPROF_CAPTURE_CURRENT_TIME,
-                                            sysprof_current_cpu,
-                                            collector->pid,
-                                            counters,
-                                            n_counters);
+  ADD_TO_COLLECTOR (sysprof_capture_writer_define_counters (collector->writer,
+                                                            SYSPROF_CAPTURE_CURRENT_TIME,
+                                                            sysprof_current_cpu,
+                                                            collector->pid,
+                                                            counters,
+                                                            n_counters));
 }
 
 void
-sysprof_collector_publish_counters (SysprofCollector                 *collector,
-                                    const guint                      *counters_ids,
+sysprof_collector_publish_counters (const guint                      *counters_ids,
                                     const SysprofCaptureCounterValue *values,
                                     guint                             n_counters)
 {
-  if (collector == NULL)
-    collector = sysprof_collector_get ();
-
-  if (collector->writer != NULL)
-    sysprof_capture_writer_set_counters (collector->writer,
-                                         SYSPROF_CAPTURE_CURRENT_TIME,
-                                         sysprof_current_cpu,
-                                         collector->pid,
-                                         counters_ids,
-                                         values,
-                                         n_counters);
+  ADD_TO_COLLECTOR (sysprof_capture_writer_set_counters (collector->writer,
+                                                         SYSPROF_CAPTURE_CURRENT_TIME,
+                                                         sysprof_current_cpu,
+                                                         collector->pid,
+                                                         counters_ids,
+                                                         values,
+                                                         n_counters));
 }
diff --git a/src/libsysprof-capture/sysprof-collector.h b/src/libsysprof-capture/sysprof-collector.h
index 143dde4..ca7b1d5 100644
--- a/src/libsysprof-capture/sysprof-collector.h
+++ b/src/libsysprof-capture/sysprof-collector.h
@@ -57,65 +57,50 @@
 #pragma once
 
 #include "sysprof-capture-types.h"
-#include "sysprof-version-macros.h"
+#include "sysprof-capture-writer.h"
 
 G_BEGIN_DECLS
 
-typedef struct _SysprofCollector SysprofCollector;
-
-SYSPROF_AVAILABLE_IN_3_36
-SysprofCollector      *sysprof_collector_get_thread_default (void);
 SYSPROF_AVAILABLE_IN_3_36
-void                   sysprof_collector_embed_file         (SysprofCollector                 *collector,
-                                                             const gchar                      *path,
-                                                             const guint8                     *data,
-                                                             gsize                             data_len);
+void                  sysprof_collector_embed_file       (const gchar                      *path,
+                                                          const guint8                     *data,
+                                                          gsize                             data_len);
 SYSPROF_AVAILABLE_IN_3_36
-void                   sysprof_collector_embed_file_fd      (SysprofCollector                 *collector,
-                                                             const gchar                      *path,
-                                                             gint                              fd);
+void                  sysprof_collector_embed_file_fd    (const gchar                      *path,
+                                                          gint                              fd);
 SYSPROF_AVAILABLE_IN_3_36
-void                   sysprof_collector_mark               (SysprofCollector                 *collector,
-                                                             gint64                            time,
-                                                             guint64                           duration,
-                                                             const gchar                      *group,
-                                                             const gchar                      *name,
-                                                             const gchar                      *mesage);
+void                  sysprof_collector_mark             (gint64                            time,
+                                                          guint64                           duration,
+                                                          const gchar                      *group,
+                                                          const gchar                      *name,
+                                                          const gchar                      *mesage);
 SYSPROF_AVAILABLE_IN_3_36
-void                   sysprof_collector_set_metadata       (SysprofCollector                 *collector,
-                                                             const gchar                      *id,
-                                                             const gchar                      *value,
-                                                             gssize                            value_len);
+void                  sysprof_collector_set_metadata     (const gchar                      *id,
+                                                          const gchar                      *value,
+                                                          gssize                            value_len);
 SYSPROF_AVAILABLE_IN_3_36
-void                   sysprof_collector_sample             (SysprofCollector                 *collector,
-                                                             gint64                            time,
-                                                             const SysprofCaptureAddress      *addrs,
-                                                             guint                             n_addrs);
+void                  sysprof_collector_sample           (gint64                            time,
+                                                          const SysprofCaptureAddress      *addrs,
+                                                          guint                             n_addrs);
 SYSPROF_AVAILABLE_IN_3_36
-void                   sysprof_collector_log                (SysprofCollector                 *collector,
-                                                             GLogLevelFlags                    severity,
-                                                             const gchar                      *domain,
-                                                             const gchar                      *message);
+void                  sysprof_collector_log              (GLogLevelFlags                    severity,
+                                                          const gchar                      *domain,
+                                                          const gchar                      *message);
 SYSPROF_AVAILABLE_IN_3_36
-SysprofCaptureAddress  sysprof_collector_map_jitted_ip      (SysprofCollector                 *collector,
-                                                             const gchar                      *name);
+SysprofCaptureAddress sysprof_collector_map_jitted_ip    (const gchar                      *name);
 SYSPROF_AVAILABLE_IN_3_36
-void                   sysprof_collector_allocate           (SysprofCollector                 *collector,
-                                                             SysprofCaptureAddress             alloc_addr,
-                                                             gint64                            alloc_size,
-                                                             SysprofBacktraceFunc              
backtrace_func,
-                                                             gpointer                          
backtrace_data);
+void                  sysprof_collector_allocate         (SysprofCaptureAddress             alloc_addr,
+                                                          gint64                            alloc_size,
+                                                          SysprofBacktraceFunc              backtrace_func,
+                                                          gpointer                          backtrace_data);
 SYSPROF_AVAILABLE_IN_3_36
-guint                  sysprof_collector_reserve_counters   (SysprofCollector                 *collector,
-                                                             guint                             n_counters);
+guint                 sysprof_collector_reserve_counters (guint                             n_counters);
 SYSPROF_AVAILABLE_IN_3_36
-void                   sysprof_collector_define_counters    (SysprofCollector                 *collector,
-                                                             const SysprofCaptureCounter      *counters,
-                                                             guint                             n_counters);
+void                  sysprof_collector_define_counters  (const SysprofCaptureCounter      *counters,
+                                                          guint                             n_counters);
 SYSPROF_AVAILABLE_IN_3_36
-void                   sysprof_collector_publish_counters   (SysprofCollector                 *collector,
-                                                             const guint                      *counters_ids,
-                                                             const SysprofCaptureCounterValue *values,
-                                                             guint                             n_counters);
+void                  sysprof_collector_publish_counters (const guint                      *counters_ids,
+                                                          const SysprofCaptureCounterValue *values,
+                                                          guint                             n_counters);
 
 G_END_DECLS


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]