diff options
-rw-r--r-- | configure.in | 1 | ||||
-rw-r--r-- | gobject/Makefile.am | 22 | ||||
-rw-r--r-- | gobject/gobject.c | 28 | ||||
-rw-r--r-- | gobject/gobject.stp.in | 199 | ||||
-rw-r--r-- | gobject/gobject_probes.d | 13 | ||||
-rw-r--r-- | gobject/gobject_trace.h | 43 | ||||
-rw-r--r-- | gobject/gsignal.c | 11 | ||||
-rw-r--r-- | gobject/gtype.c | 9 |
8 files changed, 316 insertions, 10 deletions
diff --git a/configure.in b/configure.in index 17214d9a7..af733d836 100644 --- a/configure.in +++ b/configure.in @@ -3592,6 +3592,7 @@ glib/tests/Makefile gmodule/Makefile gmodule/gmoduleconf.h gobject/Makefile +gobject/gobject.stp gobject/glib-mkenums gobject/tests/Makefile gthread/Makefile diff --git a/gobject/Makefile.am b/gobject/Makefile.am index 9abcabc32..6bcd5ae01 100644 --- a/gobject/Makefile.am +++ b/gobject/Makefile.am @@ -6,6 +6,8 @@ include $(top_srcdir)/Makefile.decl SUBDIRS = . tests +CLEANFILES= + if HAVE_THREADS THREAD_FLAGS=-DG_THREADS_MANDATORY endif @@ -120,11 +122,13 @@ gobject_private_h_sources = \ # GObject library C sources to build the library from gobject_c_sources = \ + gobject_probes.d \ gatomicarray.c \ gboxed.c \ gclosure.c \ genums.c \ gobject.c \ + gobject_trace.h \ gparam.c \ gparamspecs.c \ gsignal.c \ @@ -140,6 +144,24 @@ gobject_c_sources = \ # these sources (also mentioned above) are generated. BUILT_SOURCES = gmarshal.h gmarshal.c gobjectalias.h gobjectaliasdef.c +if ENABLE_DTRACE +gobject_probes.h: gobject_probes.d Makefile + $(DTRACE) -C -h -s $< -o $@.tmp + sed -e "s,define STAP_HAS_SEMAPHORES 1,undef STAP_HAS_SEMAPHORES," < $@.tmp > $@ && rm -f $@.tmp +gobject_probes.o: gobject_probes.d Makefile + $(DTRACE) -G -s $< -o $@ +BUILT_SOURCES += gobject_probes.h gobject_probes.o +CLEANFILES += gobject_probes.h +libgobject_2_0_la_LIBADD += gobject_probes.o +endif + +if ENABLE_SYSTEMTAP +tapset_in_files = gobject.stp.in +tapsetdir = $(DESTDIR)@ABS_TAPSET_DIR@ +tapset_DATA = $(tapset_in_files:.stp.in=.stp) +EXTRA_DIST += $(tapset_in_files) +endif + # non-header sources (headers should be specified in the above variables) # that don't serve as direct make target sources, i.e. they don't have # their own .lo rules and don't get publically installed diff --git a/gobject/gobject.c b/gobject/gobject.c index 56e6f9e68..ddfb47b7f 100644 --- a/gobject/gobject.c +++ b/gobject/gobject.c @@ -33,6 +33,7 @@ #include "gsignal.h" #include "gparamspecs.h" #include "gvaluetypes.h" +#include "gobject_trace.h" #include "gobjectalias.h" /* This should be included after gobjectalias.h (or pltcheck.sh will fail) */ @@ -817,7 +818,9 @@ g_object_run_dispose (GObject *object) g_return_if_fail (object->ref_count > 0); g_object_ref (object); + TRACE (GOBJECT_OBJECT_DISPOSE(object,G_TYPE_FROM_INSTANCE(object), 0)); G_OBJECT_GET_CLASS (object)->dispose (object); + TRACE (GOBJECT_OBJECT_DISPOSE_END(object,G_TYPE_FROM_INSTANCE(object), 0)); g_object_unref (object); } @@ -2406,7 +2409,9 @@ g_object_ref (gpointer _object) if (old_val == 1 && OBJECT_HAS_TOGGLE_REF (object)) toggle_refs_notify (object, FALSE); - + + TRACE (GOBJECT_OBJECT_REF(object,G_TYPE_FROM_INSTANCE(object),old_val)); + return object; } @@ -2422,7 +2427,6 @@ g_object_unref (gpointer _object) { GObject *object = _object; gint old_ref; - gboolean is_zero; g_return_if_fail (G_IS_OBJECT (object)); g_return_if_fail (object->ref_count > 0); @@ -2443,6 +2447,8 @@ g_object_unref (gpointer _object) if (!g_atomic_int_compare_and_exchange ((int *)&object->ref_count, old_ref, old_ref - 1)) goto retry_atomic_decrement1; + TRACE (GOBJECT_OBJECT_UNREF(object,G_TYPE_FROM_INSTANCE(object),old_ref)); + /* if we went from 2->1 we need to notify toggle refs if any */ if (old_ref == 2 && has_toggle_ref) /* The last ref being held in this case is owned by the toggle_ref */ toggle_refs_notify (object, TRUE); @@ -2450,7 +2456,9 @@ g_object_unref (gpointer _object) else { /* we are about tp remove the last reference */ + TRACE (GOBJECT_OBJECT_DISPOSE(object,G_TYPE_FROM_INSTANCE(object), 1)); G_OBJECT_GET_CLASS (object)->dispose (object); + TRACE (GOBJECT_OBJECT_DISPOSE_END(object,G_TYPE_FROM_INSTANCE(object), 1)); /* may have been re-referenced meanwhile */ retry_atomic_decrement2: @@ -2463,25 +2471,33 @@ g_object_unref (gpointer _object) if (!g_atomic_int_compare_and_exchange ((int *)&object->ref_count, old_ref, old_ref - 1)) goto retry_atomic_decrement2; + TRACE (GOBJECT_OBJECT_UNREF(object,G_TYPE_FROM_INSTANCE(object),old_ref)); + /* if we went from 2->1 we need to notify toggle refs if any */ if (old_ref == 2 && has_toggle_ref) /* The last ref being held in this case is owned by the toggle_ref */ toggle_refs_notify (object, TRUE); return; } - + /* we are still in the process of taking away the last ref */ g_datalist_id_set_data (&object->qdata, quark_closure_array, NULL); g_signal_handlers_destroy (object); g_datalist_id_set_data (&object->qdata, quark_weak_refs, NULL); /* decrement the last reference */ - is_zero = g_atomic_int_dec_and_test ((int *)&object->ref_count); - + old_ref = g_atomic_int_exchange_and_add ((int *)&object->ref_count, -1); + + TRACE (GOBJECT_OBJECT_UNREF(object,G_TYPE_FROM_INSTANCE(object),old_ref)); + /* may have been re-referenced meanwhile */ - if (G_LIKELY (is_zero)) + if (G_LIKELY (old_ref == 1)) { + TRACE (GOBJECT_OBJECT_FINALIZE(object,G_TYPE_FROM_INSTANCE(object))); G_OBJECT_GET_CLASS (object)->finalize (object); + + TRACE (GOBJECT_OBJECT_FINALIZE_END(object,G_TYPE_FROM_INSTANCE(object))); + #ifdef G_ENABLE_DEBUG IF_DEBUG (OBJECTS) { diff --git a/gobject/gobject.stp.in b/gobject/gobject.stp.in new file mode 100644 index 000000000..edcdb5033 --- /dev/null +++ b/gobject/gobject.stp.in @@ -0,0 +1,199 @@ +global gtypes +global gtypenames +global gsignalnames + +/* These are needed to keep track of gtype and signal names for the below + * probes. + */ +probe process("@ABS_GLIB_RUNTIME_LIBDIR@/libgobject-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("type__new") +{ + gtypes[pid(),user_string($arg1)] = $arg3; + gtypenames[pid(),$arg3] = user_string($arg1); +} +probe process("@ABS_GLIB_RUNTIME_LIBDIR@/libgobject-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("signal__new") +{ + gsignalnames[pid(),$arg1] = user_string($arg2); +} + +/** + * probe gobject.type_new - Called when any entity registered with the #GType system is created + * @name: String name of type + * @parent_gtype: The parent #GType of this type + * @gtype: The #GType for this type + */ +probe gobject.type_new = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgobject-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("type__new") +{ + name = user_string($arg1); + parent_gtype = $arg2; + gtype = $arg3; + probestr = sprintf("gobject.type_new(%s, %d) -> %d", name, parent_gtype, gtype); +} + +/** + * probe gobject.object_new - Called when a #GObject is created + * @object: Raw pointer to object + * @gtype: #GType for this object + * @type: String name of object type + */ +probe gobject.object_new = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgobject-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("object__new") +{ + object = $arg1; + gtype = $arg2; + type = gtypenames[pid(),$arg2]; + probestr = sprintf("gobject.object_new(%s) -> %p", type, object); +} + +/** + * probe gobject.object_ref - Called when a new reference is added to a #GObject + * @object: Raw pointer to object + * @gtype: #GType for this object + * @type: String name of object type + * @old_refcount: Original value of the reference count + * @refcount: New value of the reference count + */ +probe gobject.object_ref = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgobject-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("object__ref") +{ + object = $arg1; + gtype = $arg2; + type = gtypenames[pid(),gtype]; + old_refcount = $arg3; + refcount = old_refcount+1; + probestr = sprintf("gobject.object_ref(%p[%s]) -> %d", object, type, refcount); +} + +/** + * probe gobject.object_unref - Called when a reference is removed from a #GObject + * @object: Raw pointer to object + * @gtype: #GType for this object + * @type: String name of object type + * @old_refcount: Original value of the reference count + */ +probe gobject.object_unref = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgobject-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("object__unref") +{ + object = $arg1; + gtype = $arg2; + type = gtypenames[pid(),gtype]; + old_refcount = $arg3; + refcount = old_refcount-1; + probestr = sprintf("gobject.object_unref(%p [%s]) -> %d", object, type, refcount); +} + +/** + * probe gobject.object_dispose - Called when a g_object_dispose() run for a #GObject is initiated + * @object: Raw pointer to object + * @gtype: #GType for this object + * @type: String name of object type + * @last_unref: FIXME + */ +probe gobject.object_dispose = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgobject-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("object__dispose") +{ + object = $arg1; + gtype = $arg2; + type = gtypenames[pid(),$arg2]; + last_unref = $arg3; + probestr = sprintf("gobject.object_dispose(%p[%s])", object, type); +} + +/** + * probe gobject.object_dispose_end - Called when a g_object_dispose() run for a #GObject is completed + * @object: Raw pointer to object + * @gtype: #GType for this object + * @type: String name of object type + * @last_unref: FIXME + */ +probe gobject.object_dispose_end = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgobject-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("object__dispose__end") +{ + object = $arg1; + gtype = $arg2; + type = gtypenames[pid(),$arg2]; + last_unref = $arg3; + probestr = sprintf("gobject.object_dispose_end(%p[%s])", object, type); +} + +/** + * probe gobject.object_finalize - Called when finalization for a #GObject is started + * @object: Raw pointer to object + * @gtype: #GType for this object + * @type: String name of object type + */ +probe gobject.object_finalize = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgobject-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("object__finalize") +{ + object = $arg1; + gtype = $arg2; + type = gtypenames[pid(),$arg2]; + probestr = sprintf("gobject.object_finalize(%p[%s])", object, type); +} + +/** + * probe gobject.object_finalize - Called when finalization for a #GObject is completed + * @object: Raw pointer to object + * @gtype: #GType for this object + * @type: String name of object type + */ +probe gobject.object_finalize_end = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgobject-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("object__finalize__end") +{ + object = $arg1; + gtype = $arg2; + type = gtypenames[pid(),$arg2]; + probestr = sprintf("gobject.object_finalize_end(%p[%s])", object, type); +} + +/** + * probe gobject.signal_new - Called when a new signal is registered for a #GObject + * @gsignal: Integer value for this signal + * @name: String name for this signal + * @gtype: #GType for the type which will gain the new signal + * @type: String name of the type which will gain the new signal + */ +probe gobject.signal_new = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgobject-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("signal__new") +{ + gsignal = $arg1; + name = user_string($arg2); + gtype = $arg3; + type = gtypenames[pid(),$arg3]; + probestr = sprintf("gobject.signal_new(%s, %s) -> %d", name, type, gsignal); +} + +/** + * probe gobject.signal_emit - Called when a signal emission for a #GObject is started + * @gsignal: Integer value for this signal + * @detail: String containing signal "detail" + * @signal: String name of the signal + * @object: Raw pointer for object emitting signal + * @gtype: #GType for the type emitting the signal + * @type: String name of the type emitting the signal + */ +probe gobject.signal_emit = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgobject-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("signal__emit") +{ + gsignal = $arg1; + detail = $arg2; + signal = gsignalnames[pid(),$arg1]; + if (detail != 0) + signal = signal . "::" . gquarks[pid(), detail] + object = $arg3; + gtype = $arg4; + type = gtypenames[pid(),$arg4]; + probestr = sprintf("gobject.signal_emit(%p[%s], %s)", object, type, signal); +} + +/** + * probe gobject.signal_emit_end - Called when a signal emission for a #GObject is completed + * @gsignal: Integer value for this signal + * @detail: String containing signal "detail" + * @signal: String name of the signal + * @object: Raw pointer for object emitting signal + * @gtype: #GType for the type emitting the signal + * @type: String name of the type emitting the signal + */ +probe gobject.signal_emit_end = process("@ABS_GLIB_RUNTIME_LIBDIR@/libgobject-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("signal__emit__end") +{ + gsignal = $arg1; + detail = $arg2; + signal = gsignalnames[pid(),$arg1]; + if (detail != 0) + signal = signal . "::" . gquarks[pid(), detail] + object = $arg3; + gtype = $arg4; + type = gtypenames[pid(),$arg4]; + probestr = sprintf("gobject.signal_emit_end(%p[%s], %s)", object, type, signal); +} diff --git a/gobject/gobject_probes.d b/gobject/gobject_probes.d new file mode 100644 index 000000000..044e68a90 --- /dev/null +++ b/gobject/gobject_probes.d @@ -0,0 +1,13 @@ +provider gobject { + probe type__new(char *, unsigned long, unsigned long); + probe object__new(void*, unsigned long); + probe object__ref(void*, unsigned long, unsigned int); + probe object__unref(void*, unsigned long, unsigned int); + probe object__dispose(void*, unsigned long, unsigned int); + probe object__dispose__end(void*, unsigned long, unsigned int); + probe object__finalize(void*, unsigned long); + probe object__finalize__end(void*, unsigned long); + probe signal__new(unsigned int, char *, unsigned long) + probe signal__emit(unsigned int, unsigned int, void *, unsigned long) + probe signal__emit__end(unsigned int, unsigned int, void *, unsigned long) +}; diff --git a/gobject/gobject_trace.h b/gobject/gobject_trace.h new file mode 100644 index 000000000..292a0e862 --- /dev/null +++ b/gobject/gobject_trace.h @@ -0,0 +1,43 @@ +/* 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, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __GOBJECTTRACE_H__ +#define __GOBJECTTRACE_H__ + +#ifndef SIZEOF_CHAR +#error "config.h must be included prior to gobject_trace.h" +#endif + +#ifdef HAVE_DTRACE + +/* include the generated probes header and put markers in code */ +#include "gobject_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 /* __GOBJECTTRACE_H__ */ diff --git a/gobject/gsignal.c b/gobject/gsignal.c index a5d35eb87..9208b6eeb 100644 --- a/gobject/gsignal.c +++ b/gobject/gsignal.c @@ -36,6 +36,7 @@ #include "gboxed.h" #include "gobject.h" #include "genums.h" +#include "gobject_trace.h" #include "gobjectalias.h" @@ -1608,6 +1609,8 @@ g_signal_newv (const gchar *signal_name, node->name = g_intern_string (name); key.quark = g_quark_from_string (name); g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key); + + TRACE(GOBJECT_SIGNAL_NEW(signal_id, name, itype)); } node->destroyed = FALSE; node->test_class_offset = 0; @@ -3124,7 +3127,9 @@ signal_emit_unlocked_R (SignalNode *node, G_BREAKPOINT (); } #endif /* G_ENABLE_DEBUG */ - + + TRACE(GOBJECT_SIGNAL_EMIT(node->signal_id, detail, instance, G_TYPE_FROM_INSTANCE (instance))); + SIGNAL_LOCK (); signal_id = node->signal_id; if (node->flags & G_SIGNAL_NO_RECURSE) @@ -3382,7 +3387,9 @@ signal_emit_unlocked_R (SignalNode *node, SIGNAL_UNLOCK (); if (accumulator) g_value_unset (&accu); - + + TRACE(GOBJECT_SIGNAL_EMIT_END(node->signal_id, detail, instance, G_TYPE_FROM_INSTANCE (instance))); + return return_value_altered; } diff --git a/gobject/gtype.c b/gobject/gtype.c index fc95253e5..49b563a14 100644 --- a/gobject/gtype.c +++ b/gobject/gtype.c @@ -32,6 +32,7 @@ #include "gbsearcharray.h" #include "gobjectalias.h" #include "gatomicarray.h" +#include "gobject_trace.h" /** @@ -481,7 +482,9 @@ type_node_any_new_W (TypeNode *pnode, pnode->children = g_renew (GType, pnode->children, pnode->n_children); pnode->children[i] = type; } - + + TRACE(GOBJECT_TYPE_NEW(name, node->supers[1], type)); + node->plugin = plugin; node->n_children = 0; node->children = NULL; @@ -1883,7 +1886,9 @@ g_type_create_instance (GType type) instance->g_class = class; if (node->data->instance.instance_init) node->data->instance.instance_init (instance, class); - + + TRACE(GOBJECT_OBJECT_NEW(instance, type)); + return instance; } |