Commit 195a0cb6 authored by Philip Withnall's avatar Philip Withnall Committed by Philip Withnall

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
parent cfb69282
......@@ -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 \
......
......@@ -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>
......
......@@ -391,6 +391,7 @@ libgio_2_0_la_SOURCES = \
ginetsocketaddress.c \
ginitable.c \
ginputstream.c \
gio_trace.h \
gioenums.h \
gioerror.c \
giomodule.c \
......@@ -755,6 +756,40 @@ dist_schema_DATA = gschema.dtd
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
......
/**
* 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);
}
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);
};
/* 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__ */
......@@ -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;
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment