[glib] gio: Add SystemTap and DTrace probes for GTask



commit 195a0cb6bb8cc8739902fcf3245bfe256c980c60
Author: Philip Withnall <philip tecnocode co uk>
Date:   Wed Dec 23 16:35:24 2015 +0000

    gio: Add SystemTap and DTrace probes for GTask
    
    This adds a basic tapset for GIO, covering various interesting parts of
    GTask.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=759813

 docs/reference/gio/Makefile.am  |    1 +
 docs/reference/glib/running.xml |    3 +-
 gio/Makefile.am                 |   35 +++++++++++++
 gio/gio.stp.in                  |  107 +++++++++++++++++++++++++++++++++++++++
 gio/gio_probes.d                |   10 ++++
 gio/gio_trace.h                 |   41 +++++++++++++++
 gio/gtask.c                     |   34 +++++++++++-
 7 files changed, 227 insertions(+), 4 deletions(-)
---
diff --git a/docs/reference/gio/Makefile.am b/docs/reference/gio/Makefile.am
index 38666b4..ff201cd 100644
--- a/docs/reference/gio/Makefile.am
+++ b/docs/reference/gio/Makefile.am
@@ -51,6 +51,7 @@ IGNORE_HFILES = \
        gfileattribute-priv.h           \
        gfileinfo-priv.h                \
        ghttpproxy.h                    \
+       gio_trace.h                     \
        giomodule-priv.h                \
        gioprivate.h                    \
        giowin32-priv.h                 \
diff --git a/docs/reference/glib/running.xml b/docs/reference/glib/running.xml
index a00369b..c05820b 100644
--- a/docs/reference/glib/running.xml
+++ b/docs/reference/glib/running.xml
@@ -310,7 +310,8 @@ Which would print the contents of each widget in a list of widgets.
 <ulink url="http://sourceware.org/systemtap/";>SystemTap</ulink> is a dynamic whole-system
 analysis toolkit.  GLib ships with a file <filename>glib.stp</filename> which defines a
 set of probe points, which you can hook into with custom SystemTap scripts.
-See the files <filename>glib.stp</filename> and <filename>gobject.stp</filename> which
+See the files <filename>glib.stp</filename>, <filename>gobject.stp</filename>
+and <filename>gio.stp</filename> which
 are in your shared SystemTap scripts directory.
 </para>
 
diff --git a/gio/Makefile.am b/gio/Makefile.am
index e911d91..18e0ca1 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -391,6 +391,7 @@ libgio_2_0_la_SOURCES =             \
        ginetsocketaddress.c    \
        ginitable.c             \
        ginputstream.c          \
+       gio_trace.h             \
        gioenums.h              \
        gioerror.c              \
        giomodule.c             \
@@ -756,6 +757,40 @@ itsdir = $(datadir)/gettext/its
 dist_its_DATA = gschema.loc gschema.its
 
 # ------------------------------------------------------------------------
+# SystemTap and dtrace
+
+if ENABLE_DTRACE
+DTCOMPILE = $(patsubst -W%,,$(LTCOMPILE))
+DTCFLAGS = $(patsubst -W%,,$(CFLAGS))
+
+gio_probes.h: gio_probes.d
+       $(AM_V_GEN) $(DTRACE) -C -h -s $< -o $  tmp
+       @$(SED) -e "s,define STAP_HAS_SEMAPHORES 1,undef STAP_HAS_SEMAPHORES," < $  tmp > $@ && rm -f $  tmp
+
+gio_probes.lo: gio_probes.d
+       $(AM_V_GEN) env CC="$(DTCOMPILE)" CFLAGS="$(DTCFLAGS)" $(DTRACE) -G -s $< -o $@
+
+BUILT_SOURCES += gio_probes.h gio_probes.lo
+CLEANFILES += gio_probes.h gio_probes.h.tmp
+libgio_2_0_la_LIBADD += gio_probes.lo
+endif
+
+if ENABLE_SYSTEMTAP
+tapset_in_files = gio.stp.in
+tapsetdir   = @ABS_TAPSET_DIR@
+tapset_DATA = $(tapset_in_files:.stp.in=.stp)
+EXTRA_DIST += $(tapset_in_files)
+CLEANFILES += $(tapset_in_files:.stp.in=.stp)
+
+$(tapset_DATA): %.stp: %.stp.in Makefile
+       $(AM_V_GEN)$(SED) \
+               -e 's|[ ]ABS_GLIB_RUNTIME_LIBDIR[@]|$(ABS_GLIB_RUNTIME_LIBDIR)|g' \
+               -e 's|[ ]LT_CURRENT[@]|$(LT_CURRENT)|g' \
+               -e 's|[ ]LT_REVISION[@]|$(LT_REVISION)|g' \
+               $< > $@
+endif
+
+# ------------------------------------------------------------------------
 # gdbus(1) tool
 
 bin_PROGRAMS += gdbus
diff --git a/gio/gio.stp.in b/gio/gio.stp.in
new file mode 100644
index 0000000..3ca0cd3
--- /dev/null
+++ b/gio/gio.stp.in
@@ -0,0 +1,107 @@
+/**
+ * probe gio.task_new - Called when a new #GTask is created
+ * @task: the new #GTask object
+ * @source_object: the source object
+ * @cancellable: the #GCancellable
+ * @callback: the task’s callback
+ * @callback_data: data for @callback
+ */
+probe gio.task_new = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgio-2 0 so 0  LT_CURRENT@  
LT_REVISION@").mark("task__new")
+{
+  task = $arg1;
+  source_object = $arg2;
+  cancellable = $arg3;
+  callback = $arg4;
+  callback_data = $arg5;
+  probestr = sprintf("gio.task_new(%p, %p, %p, %p) -> %p", source_object, cancellable, callback, 
callback_data, task);
+}
+
+/**
+ * probe gio.task_set_task_data - Called when the task data is set on a #GTask
+ * @task: the #GTask object
+ * @task_data: the task data
+ * @task_data_destroy: the destroy notify function for the data
+ */
+probe gio.task_set_task_data = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgio-2 0 so 0  LT_CURRENT@  
LT_REVISION@").mark("task__set_task_data")
+{
+  task = $arg1;
+  task_data = $arg2;
+  task_data_destroy = $arg3;
+  probestr = sprintf("gio.task_set_task_data(%p, %p, %p)", task, task_data, task_data_destroy);
+}
+
+/**
+ * probe gio.task_set_priority - Called when the priority of a #GTask is set
+ * @task: the #GTask object
+ * @priority: the priority
+ */
+probe gio.task_set_priority = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgio-2 0 so 0  LT_CURRENT@  
LT_REVISION@").mark("task__set_priority")
+{
+  task = $arg1;
+  priority = $arg2;
+  probestr = sprintf("gio.task_set_priority(%p, %i)", task, priority);
+}
+
+/**
+ * probe gio.task_set_source_tag - Called when the source tag of a #GTask is set
+ * @task: the #GTask object
+ * @source_tag: the source tag
+ */
+probe gio.task_set_source_tag = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgio-2 0 so 0  LT_CURRENT@  
LT_REVISION@").mark("task__set_source_tag")
+{
+  task = $arg1;
+  source_tag = $arg2;
+  probestr = sprintf("gio.task_set_source_tag(%p, %p)", task, source_tag);
+}
+
+/**
+ * probe gio.task_before_return - Called before a #GTask invokes its callback or returns from 
g_task_run_in_thread_sync()
+ * @task: the #GTask object
+ * @source_object: the source object passed to the callback
+ * @callback: the callback about to be invoked
+ * @callback_data: data passed to @callback
+ */
+probe gio.task_before_return = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgio-2 0 so 0  LT_CURRENT@  
LT_REVISION@").mark("task__before_return")
+{
+  task = $arg1;
+  source_object = $arg2;
+  callback = $arg3;
+  callback_data = $arg4;
+  probestr = sprintf("gio.task_before_return(%p, %p, %p, %p)", task, source_object, callback, callback_data);
+}
+
+/**
+ * probe gio.task_propagate - Called when a #GTask’s result is propagated
+ * @task: the #GTask object
+ * @error_set: %TRUE if propagating an error, %FALSE otherwise
+ */
+probe gio.task_propagate = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgio-2 0 so 0  LT_CURRENT@  
LT_REVISION@").mark("task__propagate")
+{
+  task = $arg1;
+  error_set = $arg2;
+  probestr = sprintf("gio.task_propagate(%p) -> %u", task, error_set);
+}
+
+/**
+ * probe gio.task_before_run_in_thread - Called before a #GTask’s function is run in a thread
+ * @task: the #GTask object
+ * @task_func: the task function being run
+ */
+probe gio.task_before_run_in_thread = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgio-2 0 so 0  LT_CURRENT@  
LT_REVISION@").mark("task__before_run_in_thread")
+{
+  task = $arg1;
+  task_func = $arg2;
+  probestr = sprintf("gio.task_before_run_in_thread(%p, %p)", task, task_func);
+}
+
+/**
+ * probe gio.task_after_run_in_thread - Called after a #GTask’s function is run in a thread
+ * @task: the #GTask object
+ * @thread_cancelled: %TRUE if the thread was cancelled, %FALSE otherwise
+ */
+probe gio.task_after_run_in_thread = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgio-2 0 so 0  LT_CURRENT@  
LT_REVISION@").mark("task__after_run_in_thread")
+{
+  task = $arg1;
+  thread_cancelled = $arg2;
+  probestr = sprintf("gio.task_after_run_in_thread(%p) -> %u", task, thread_cancelled);
+}
diff --git a/gio/gio_probes.d b/gio/gio_probes.d
new file mode 100644
index 0000000..8747d8d
--- /dev/null
+++ b/gio/gio_probes.d
@@ -0,0 +1,10 @@
+provider gio {
+       probe task__new(void*, void*, void*, void*, void*);
+       probe task__set_task_data(void*, void*, void*);
+       probe task__set_priority(void*, int);
+       probe task__set_source_tag(void*, void*);
+       probe task__before_return(void*, void*, void*, void*);
+       probe task__propagate(void*, unsigned int);
+       probe task__before_run_in_thread(void*, void*);
+       probe task__after_run_in_thread(void*, unsigned int);
+};
diff --git a/gio/gio_trace.h b/gio/gio_trace.h
new file mode 100644
index 0000000..ba69a6e
--- /dev/null
+++ b/gio/gio_trace.h
@@ -0,0 +1,41 @@
+/* GLIB - Library of useful routines for C programming
+ * 
+ * Copyright (C) 2009,2010 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Alexander Larsson <alexl redhat com>
+ */
+
+#ifndef __GIOTRACE_H__
+#define __GIOTRACE_H__
+
+#ifndef SIZEOF_CHAR
+#error "config.h must be included prior to gio_trace.h"
+#endif
+
+#ifdef HAVE_DTRACE
+
+/* include the generated probes header and put markers in code */
+#include "gio_probes.h"
+#define TRACE(probe) probe
+
+#else
+
+/* Wrap the probe to allow it to be removed when no systemtap available */
+#define TRACE(probe)
+
+#endif
+
+#endif /* __GIOTRACE_H__ */
diff --git a/gio/gtask.c b/gio/gtask.c
index 042e047..4af4237 100644
--- a/gio/gtask.c
+++ b/gio/gtask.c
@@ -17,6 +17,7 @@
  */
 
 #include "config.h"
+#include "gio_trace.h"
 
 #include "gtask.h"
 
@@ -700,6 +701,9 @@ g_task_new (gpointer              source_object,
   if (source)
     task->creation_time = g_source_get_time (source);
 
+  TRACE (GIO_TASK_NEW (task, source_object, cancellable,
+                       callback, callback_data));
+
   return task;
 }
 
@@ -803,6 +807,8 @@ g_task_set_task_data (GTask          *task,
 
   task->task_data = task_data;
   task->task_data_destroy = task_data_destroy;
+
+  TRACE (GIO_TASK_SET_TASK_DATA (task, task_data, task_data_destroy));
 }
 
 /**
@@ -825,6 +831,8 @@ g_task_set_priority (GTask *task,
                      gint   priority)
 {
   task->priority = priority;
+
+  TRACE (GIO_TASK_SET_PRIORITY (task, priority));
 }
 
 /**
@@ -951,6 +959,8 @@ g_task_set_source_tag (GTask    *task,
                        gpointer  source_tag)
 {
   task->source_tag = source_tag;
+
+  TRACE (GIO_TASK_SET_SOURCE_TAG (task, source_tag));
 }
 
 /**
@@ -1101,6 +1111,9 @@ g_task_get_source_tag (GTask *task)
 static void
 g_task_return_now (GTask *task)
 {
+  TRACE (GIO_TASK_BEFORE_RETURN (task, task->source_object, task->callback,
+                                 task->callback_data));
+
   g_main_context_push_thread_default (task->context);
 
   if (task->callback != NULL)
@@ -1219,6 +1232,8 @@ g_task_thread_complete (GTask *task)
       return;
     }
 
+  TRACE (GIO_TASK_AFTER_RUN_IN_THREAD (task, task->thread_cancelled));
+
   task->thread_complete = TRUE;
   g_mutex_unlock (&task->lock);
 
@@ -1338,6 +1353,8 @@ g_task_start_task_thread (GTask           *task,
 
   g_mutex_lock (&task->lock);
 
+  TRACE (GIO_TASK_BEFORE_RUN_IN_THREAD (task, task_func));
+
   task->task_func = task_func;
 
   if (task->cancellable)
@@ -1347,6 +1364,7 @@ g_task_start_task_thread (GTask           *task,
                                                 &task->error))
         {
           task->thread_cancelled = task->thread_complete = TRUE;
+          TRACE (GIO_TASK_AFTER_RUN_IN_THREAD (task, task->thread_cancelled));
           g_thread_pool_push (task_pool, g_object_ref (task), NULL);
           return;
         }
@@ -1453,6 +1471,10 @@ g_task_run_in_thread_sync (GTask           *task,
 
   g_mutex_unlock (&task->lock);
 
+  TRACE (GIO_TASK_BEFORE_RETURN (task, task->source_object,
+                                 NULL  /* callback */,
+                                 NULL  /* callback data */));
+
   /* Notify of completion in this thread. */
   task->completed = TRUE;
   g_object_notify (G_OBJECT (task), "completed");
@@ -1491,18 +1513,24 @@ static gboolean
 g_task_propagate_error (GTask   *task,
                         GError **error)
 {
+  gboolean error_set;
+
   if (task->check_cancellable &&
       g_cancellable_set_error_if_cancelled (task->cancellable, error))
-    return TRUE;
+    error_set = TRUE;
   else if (task->error)
     {
       g_propagate_error (error, task->error);
       task->error = NULL;
       task->had_error = TRUE;
-      return TRUE;
+      error_set = TRUE;
     }
   else
-    return FALSE;
+    error_set = FALSE;
+
+  TRACE (GIO_TASK_PROPAGATE (task, error_set));
+
+  return error_set;
 }
 
 /**


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