[mutter/gbsneto/tracing: 63/68] cogl: Add libsysprof capture based tracing



commit 8c1deda9aa160d09a6d963a24bf496e6940aadc3
Author: Jonas Ådahl <jadahl gmail com>
Date:   Tue May 15 16:31:29 2018 +0100

    cogl: Add libsysprof capture based tracing
    
    Add the ability to add tracing instrumentation to the code. When
    enabled, trace entries will generate a file with timing information
    that will be processable by sysprof for generating visualization of
    traces over time.
    
    While enabled by default at compile time, it is possible to disable the
    expansion of the macros completely by passing --disable-tracing to
    ./configure.
    
    Tracing is so far only actually done if actually enabled on explicitly
    specified threads.
    
    This will be used by Mutter passing the write end of a pipe, where the
    read end is sent to Sysprof itself via the D-Bus method 'Capture()'.
    
    By passing that, we have to detect EPIPE that is sent when Sysprof stops
    recording. To do that, SEGPIPE is ignored.

 clutter/configure.ac   |  14 +++-
 cogl/cogl/Makefile.am  |   2 +
 cogl/cogl/cogl-trace.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++
 cogl/cogl/cogl-trace.h | 138 +++++++++++++++++++++++++++++++++++++
 cogl/configure.ac      |  16 ++++-
 configure.ac           |   9 +++
 6 files changed, 356 insertions(+), 4 deletions(-)
---
diff --git a/clutter/configure.ac b/clutter/configure.ac
index 6ad5d9285..5b4112442 100644
--- a/clutter/configure.ac
+++ b/clutter/configure.ac
@@ -163,6 +163,15 @@ AC_ARG_ENABLE([Bsymbolic],
                 LDFLAGS="${saved_LDFLAGS}"
               ])
 
+AC_ARG_ENABLE(tracing,
+             AC_HELP_STRING([--disable-tracing],
+                            [disable performance tracin]),,
+             enable_tracing=yes)
+if test x$enable_tracing = xyes; then
+    AC_DEFINE(HAVE_TRACING,1,[Enable tracing])
+    CLUTTER_TRACING_PC_FILES="sysprof-capture-2"
+fi
+
 AS_IF([test "x$enable_Bsymbolic" = "xyes"], [CLUTTER_LINK_FLAGS=-Wl[,]-Bsymbolic-functions])
 AC_SUBST(CLUTTER_LINK_FLAGS)
 
@@ -656,7 +665,6 @@ AS_IF([test "x$enable_Werror" = xyes], [
                              -Werror=format-security
                              -Werror=format-nonliteral
                              -Werror=init-self
-                             -Werror=declaration-after-statement
                              -Werror=vla"
 ])
 
@@ -689,7 +697,7 @@ dnl === Dependencies, compiler flags and linker libraries =====================
 BACKEND_PC_FILES=${BACKEND_PC_FILES#* }
 
 # public dependencies, will fill the Requires: field of clutter.pc
-CLUTTER_REQUIRES="$CLUTTER_BASE_PC_FILES $BACKEND_PC_FILES"
+CLUTTER_REQUIRES="$CLUTTER_BASE_PC_FILES $CLUTTER_TRACING_PC_FILES $BACKEND_PC_FILES"
 PKG_CHECK_MODULES(CLUTTER_DEPS, [$CLUTTER_REQUIRES])
 
 # private dependencies, will fill the Requires.private: field of clutter.pc
@@ -707,7 +715,7 @@ AS_IF([test "x$CLUTTER_BASE_PC_FILES_PRIVATE" = "x" && test "x$BACKEND_PC_FILES_
 AC_SUBST(CLUTTER_REQUIRES)
 AC_SUBST(CLUTTER_REQUIRES_PRIVATE)
 
-CLUTTER_CFLAGS="$FLAVOUR_CFLAGS $CLUTTER_DEPS_CFLAGS $CLUTTER_DEPS_PRIVATE_CFLAGS $GLIB_CFLAGS 
$LIBWACOM_CFLAGS"
+CLUTTER_CFLAGS="$FLAVOUR_CFLAGS $CLUTTER_DEPS_CFLAGS $CLUTTER_DEPS_PRIVATE_CFLAGS $GLIB_CFLAGS 
$LIBWACOM_CFLAGS -std=gnu11"
 CLUTTER_LIBS="$FLAVOUR_LIBS $CLUTTER_DEPS_LIBS $CLUTTER_DEPS_PRIVATE_LIBS $GLIB_LIBS $LIBWACOM_LIBS"
 AC_SUBST(CLUTTER_CFLAGS)
 AC_SUBST(CLUTTER_LIBS)
diff --git a/cogl/cogl/Makefile.am b/cogl/cogl/Makefile.am
index 66accf709..69301017a 100644
--- a/cogl/cogl/Makefile.am
+++ b/cogl/cogl/Makefile.am
@@ -215,6 +215,8 @@ cogl_sources_c = \
        cogl-i18n-private.h                     \
        cogl-debug.h                            \
        cogl-debug-options.h                    \
+       cogl-trace.c                    \
+       cogl-trace.h                    \
        cogl-gpu-info.c                 \
        cogl-gpu-info-private.h         \
        cogl-context-private.h          \
diff --git a/cogl/cogl/cogl-trace.c b/cogl/cogl/cogl-trace.c
new file mode 100644
index 000000000..eb536adf7
--- /dev/null
+++ b/cogl/cogl/cogl-trace.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "cogl-config.h"
+
+#ifdef HAVE_TRACING
+
+#include "cogl/cogl-trace.h"
+
+#include <sp-clock.h>
+#include <syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define COGL_TRACE_OUTPUT_FILE "cogl-trace-sp-capture.syscap"
+
+__thread CoglTraceThreadContext *cogl_trace_thread_context;
+CoglTraceContext *cogl_trace_context;
+GMutex cogl_trace_mutex;
+
+static CoglTraceContext *
+cogl_trace_context_new (int fd)
+{
+  CoglTraceContext *context;
+  SpCaptureWriter *writer;
+
+  g_debug ("Initializing trace context with fd=%d", fd);
+
+  if (fd == -1)
+    writer = sp_capture_writer_new (COGL_TRACE_OUTPUT_FILE,
+                                    4096 * 4);
+  else
+    writer = sp_capture_writer_new_from_fd (fd, 4096 * 4);
+
+  context = g_new0 (CoglTraceContext, 1);
+  context->writer = writer;
+  return context;
+}
+
+static void
+ensure_trace_context (int fd)
+{
+  static GMutex mutex;
+
+  g_mutex_lock (&mutex);
+  if (!cogl_trace_context)
+    cogl_trace_context = cogl_trace_context_new (fd);
+  g_mutex_unlock (&mutex);
+}
+
+static void
+ensure_sigpipe_ignored (void)
+{
+  signal (SIGPIPE, SIG_IGN);
+}
+
+static CoglTraceThreadContext *
+cogl_trace_thread_context_new (void)
+{
+  CoglTraceThreadContext *thread_context;
+  pid_t tid;
+
+  tid = (pid_t) syscall (SYS_gettid);
+
+  thread_context = g_new0 (CoglTraceThreadContext, 1);
+  thread_context->cpu_id = -1;
+  thread_context->pid = getpid ();
+  thread_context->group = g_strdup_printf ("t:%d", tid);
+
+  return thread_context;
+}
+
+static gboolean
+enable_tracing_idle_callback (gpointer user_data)
+{
+  int fd = GPOINTER_TO_INT (user_data);
+
+  ensure_sigpipe_ignored ();
+  ensure_trace_context (fd);
+
+  if (cogl_trace_thread_context)
+    {
+      g_warning ("Tracing already enabled");
+      return G_SOURCE_REMOVE;
+    }
+
+  cogl_trace_thread_context = cogl_trace_thread_context_new ();
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+cogl_trace_thread_context_free (CoglTraceThreadContext *thread_context)
+{
+  g_free (thread_context->group);
+  g_free (thread_context);
+}
+
+static gboolean
+disable_tracing_idle_callback (gpointer user_data)
+{
+  CoglTraceContext *trace_context;
+
+  if (!cogl_trace_thread_context)
+    {
+      g_warning ("Tracing not enabled");
+      return G_SOURCE_REMOVE;
+    }
+
+  g_clear_pointer (&cogl_trace_thread_context,
+                   (GDestroyNotify) cogl_trace_thread_context_free);
+
+  g_mutex_lock (&cogl_trace_mutex);
+  trace_context = cogl_trace_context;
+  sp_capture_writer_flush (trace_context->writer);
+  g_mutex_unlock (&cogl_trace_mutex);
+
+  return G_SOURCE_REMOVE;
+}
+
+void
+cogl_set_tracing_enabled_on_thread (GMainContext *main_context,
+                                    int           fd)
+{
+  GSource *source;
+
+  source = g_idle_source_new ();
+
+  g_source_set_callback (source, enable_tracing_idle_callback, GINT_TO_POINTER (fd), NULL);
+
+  g_source_attach (source, main_context);
+  g_source_unref (source);
+}
+
+void
+cogl_set_tracing_disabled_on_thread (GMainContext *main_context)
+{
+  GSource *source;
+
+  source = g_idle_source_new ();
+
+  g_source_set_callback (source, disable_tracing_idle_callback, NULL, NULL);
+
+  g_source_attach (source, main_context);
+  g_source_unref (source);
+}
+
+#else
+
+#include <string.h>
+#include <stdio.h>
+
+void
+cogl_set_tracing_enabled_on_thread (void *data,
+                                    int   fd)
+{
+  fprintf (stderr, "Tracing not enabled");
+}
+
+void
+cogl_set_tracing_disabled_on_thread (void *data)
+{
+  fprintf (stderr, "Tracing not enabled");
+}
+
+#endif /* HAVE_TRACING */
diff --git a/cogl/cogl/cogl-trace.h b/cogl/cogl/cogl-trace.h
new file mode 100644
index 000000000..8b2c1ad95
--- /dev/null
+++ b/cogl/cogl/cogl-trace.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef COGL_TRACE_H
+#define COGL_TRACE_H
+
+#include "cogl-config.h"
+
+#ifdef HAVE_TRACING
+
+#include <glib.h>
+#include <capture/sp-capture-writer.h>
+#include <sp-clock.h>
+#include <stdint.h>
+#include <errno.h>
+
+typedef struct _CoglTraceContext
+{
+  SpCaptureWriter *writer;
+} CoglTraceContext;
+
+typedef struct _CoglTraceThreadContext
+{
+  int cpu_id;
+  GPid pid;
+  char *group;
+} CoglTraceThreadContext;
+
+typedef struct _CoglTraceHead
+{
+  SpTimeStamp begin_time;
+  const char *name;
+} CoglTraceHead;
+
+extern __thread CoglTraceThreadContext *cogl_trace_thread_context;
+extern CoglTraceContext *cogl_trace_context;
+extern GMutex cogl_trace_mutex;
+
+void cogl_set_tracing_enabled_on_thread (GMainContext *main_context,
+                                         int           fd);
+
+void cogl_set_tracing_disabled_on_thread (GMainContext *main_context);
+
+static inline void
+cogl_trace_begin (CoglTraceHead *head,
+                  const char    *name)
+{
+  head->begin_time = g_get_monotonic_time () * 1000;
+  head->name = name;
+}
+
+static inline void
+cogl_trace_end (CoglTraceHead *head)
+{
+  SpTimeStamp end_time;
+  CoglTraceContext *trace_context;
+  CoglTraceThreadContext *trace_thread_context;
+
+  end_time = g_get_monotonic_time () * 1000;
+  trace_context = cogl_trace_context;
+  trace_thread_context = cogl_trace_thread_context;
+
+  g_mutex_lock (&cogl_trace_mutex);
+  if (!sp_capture_writer_add_mark (trace_context->writer,
+                                   head->begin_time,
+                                   trace_thread_context->cpu_id,
+                                   trace_thread_context->pid,
+                                   (uint64_t) end_time - head->begin_time,
+                                   trace_thread_context->group,
+                                   head->name,
+                                   NULL))
+    {
+      /* XXX: g_main_context_get_thread_default() might be wrong, it probably
+       * needs to store the GMainContext in CoglTraceThreadContext when creating
+       * and use it here.
+       */
+      if (errno == EPIPE)
+        cogl_set_tracing_disabled_on_thread (g_main_context_get_thread_default ());
+    }
+  g_mutex_unlock (&cogl_trace_mutex);
+}
+
+static inline void
+cogl_auto_trace_end_helper (CoglTraceHead **head)
+{
+  if (*head)
+    cogl_trace_end (*head);
+}
+
+#define COGL_TRACE_BEGIN(Name) \
+  CoglTraceHead CoglTrace##Name = { 0 }; \
+  if (cogl_trace_thread_context) \
+    cogl_trace_begin (&CoglTrace##Name, #Name); \
+
+#define COGL_TRACE_END(Name)\
+  if (cogl_trace_thread_context) \
+    cogl_trace_end (&CoglTrace##Name);
+
+#define COGL_TRACE_BEGIN_SCOPED(Name) \
+  CoglTraceHead CoglTrace##Name = { 0 }; \
+  __attribute__((cleanup (cogl_auto_trace_end_helper))) \
+    CoglTraceHead *ScopedCoglTrace##Name = NULL; \
+  if (cogl_trace_thread_context) \
+    { \
+      cogl_trace_begin (&CoglTrace##Name, #Name); \
+      ScopedCoglTrace##Name = &CoglTrace##Name; \
+    }
+
+#else /* HAVE_TRACING */
+
+#include <stdio.h>
+
+#define COGL_TRACE_BEGIN(Name) (void) 0
+#define COGL_TRACE_END(Name) (void) 0
+#define COGL_TRACE_BEGIN_SCOPED(Name) (void) 0
+
+void cogl_set_tracing_enabled_on_thread (void *data, int fd);
+
+void cogl_set_tracing_disabled_on_thread (void *data);
+
+#endif /* HAVE_TRACING */
+
+#endif /* COGL_TRACE_H */
diff --git a/cogl/configure.ac b/cogl/configure.ac
index 3be282fc2..c3e645e1d 100644
--- a/cogl/configure.ac
+++ b/cogl/configure.ac
@@ -297,6 +297,19 @@ AS_IF([test "x$enable_profile" = "xyes"],
       ])
 AM_CONDITIONAL(PROFILE, test "x$enable_profile" != "xno")
 
+dnl     ============================================================
+dnl     Enable tracing
+dnl     ============================================================
+AC_ARG_ENABLE(tracing,
+             AC_HELP_STRING([--disable-tracing],
+                            [disable performance tracing]),
+              [],
+             enable_tracing=yes)
+if test x$enable_tracing = xyes; then
+    AC_DEFINE(HAVE_TRACING,1,[Enable tracing])
+    COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES sysprof-capture-2"
+fi
+
 
 dnl     ============================================================
 dnl     Enable strict compiler flags
@@ -315,7 +328,7 @@ AC_ARG_ENABLE(
 MAINTAINER_COMPILER_FLAGS="-Wall -Wcast-align -Wformat -Wformat-security
                            -Werror=uninitialized -Werror=no-strict-aliasing
                            -Werror=empty-body -Werror=init-self -Werror=undef
-                           -Werror=declaration-after-statement -Werror=vla
+                           -Werror=vla
                            -Werror=pointer-arith -Werror=missing-declarations
                            -Werror=maybe-uninitialized"
 
@@ -1011,6 +1024,7 @@ echo ""
 echo " • Build options:"
 echo "        Debugging: ${enable_debug}"
 echo "        Profiling: ${enable_profile}"
+echo "        Tracing:   ${enable_tracing}"
 echo "        Enable deprecated symbols: ${enable_deprecated}"
 echo "        Compiler flags: ${CFLAGS} ${COGL_EXTRA_CFLAGS}"
 echo "        Linker flags: ${LDFLAGS} ${COGL_EXTRA_LDFLAGS}"
diff --git a/configure.ac b/configure.ac
index 542ad832f..a916c8c50 100644
--- a/configure.ac
+++ b/configure.ac
@@ -108,6 +108,15 @@ XWAYLAND_GRAB_DEFAULT_ACCESS_RULES="gnome-boxes,remote-viewer,virt-viewer,virt-m
 
 GLIB_GSETTINGS
 
+AC_ARG_ENABLE(tracing,
+  AC_HELP_STRING([--disable-tracing],
+                [disable performance tracin]),,
+  enable_tracing=yes)
+if test x$enable_tracing = xyes; then
+    AC_DEFINE(HAVE_TRACING,1,[Enable tracing])
+    MUTTER_PC_MODULES="$MUTTER_PC_MODULES sysprof-capture-2"
+fi
+
 AC_ARG_ENABLE(verbose-mode,
   AC_HELP_STRING([--disable-verbose-mode],
                  [disable mutter's ability to do verbose logging, for embedded/size-sensitive custom 
builds]),,


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