From 55abdd5e4a4c5d05468380615fe563f000816d5c Mon Sep 17 00:00:00 2001 From: Allison Karlitskaya Date: Wed, 26 Oct 2011 12:00:42 -0400 Subject: [PATCH] GVariant: add probes for SystemTap https://bugzilla.gnome.org/show_bug.cgi?id=662779 Fixes: #473 --- glib/glib.stp.in | 203 ++++++++++++++++++++++++++++++++++++++++ glib/glib_probes.d | 11 +++ glib/gvariant-core.c | 15 +++ glib/gvarianttypeinfo.c | 9 ++ 4 files changed, 238 insertions(+) diff --git a/glib/glib.stp.in b/glib/glib.stp.in index 5714fc171..4ca889fa4 100644 --- a/glib/glib.stp.in +++ b/glib/glib.stp.in @@ -1,4 +1,5 @@ global glib_quarks_2_0_@LT_CURRENT@_@LT_REVISION@ +global gvarianttypeinfo_2_0_@LT_CURRENT@_@LT_REVISION@ /* This is needed to keep track of gquark for use in other probes.*/ probe process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("quark__new") @@ -643,3 +644,205 @@ probe glib.rcbox_free = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_ mem = $arg1; /* ARG: @mem: Raw memory pointer */ probestr = sprintf("glib.rcbox_free(mem=%p)", mem); } + +/** + * probe glib.variant_type_info_new: + * @info: Raw info structure pointer + * @typestr: GVariant type string + **/ +probe glib.variant_type_info_new = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("variant__type_info_new") +{ + info = $arg1; + typestr = user_string($arg2); + gvarianttypeinfo[pid(), info] = typestr; +} + +/** + * probe glib.variant_type_info_free: + * @info: Raw info structure pointer + **/ +probe glib.variant_type_info_free = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("variant__type_info_free") +{ + info = $arg1; + delete gvarianttypeinfo[pid(), info]; +} + +/** + * probe glib.variant_start_serialise: + * @value: pointer to #GVariant + * @typeinfo: the raw typeinfo structure pointer + * @typestr: the type string of the #GVariant + * + * Indicates that a @value has started the process of serialising + * itself. This involves dropping references on the child elements of + * @value, so when mixed with the end_serialise probe, it is possible to + * see the context in which the unrefs are occuring. + **/ +probe glib.variant_start_serialise = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("variant__start_serialise") +{ + value = $arg1; + typeinfo = $arg2; + typestr = gvarianttypeinfo[pid(), typeinfo]; +} + +/** + * probe glib.variant_end_serialise: + * @value: pointer to #GVariant + * @typeinfo: the raw typeinfo structure pointer + * @typestr: the type string of the #GVariant + * + * Indicates that a @value has ended the process of serialising itself. + **/ +probe glib.variant_end_serialise = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("variant__end_serialise") +{ + value = $arg1; + typeinfo = $arg2; + typestr = gvarianttypeinfo[pid(), typeinfo]; +} + +/** + * probe glib.variant_from_buffer: + * @value: pointer to #GVariant + * @typeinfo: the raw typeinfo structure pointer + * @typestr: the type string of the #GVariant + * @ref_count: the initial reference count + * @state: the internal state bitfield + * + * Reports that a serialised #GVariant has been created from a buffer. + * This can happen in two cases. The first is when a leaf value is + * created (with g_variant_new_string(), for example). The second is + * when a container #GVariant is created by loading from serialised data + * (with g_variant_new_from_data(), for example). + **/ +probe glib.variant_from_buffer = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("variant__from_buffer") +{ + value = $arg1; + typeinfo = $arg2; + typestr = gvarianttypeinfo[pid(), typeinfo]; + ref_count = $arg3; + state = $arg4; +} + +/** + * probe glib.variant_from_children: + * @value: pointer to #GVariant + * @typeinfo: the raw typeinfo structure pointer + * @typestr: the type string of the #GVariant + * @ref_count: the initial reference count + * @state: the internal state bitfield + * + * Reports that a tree-form #GVariant has been created from a number of + * child elements. This happens in response to the calls like + * g_variant_new_array() and also for g_variant_builder_end(). + **/ +probe glib.variant_from_children = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("variant__from_children") +{ + value = $arg1; + typeinfo = $arg2; + typestr = gvarianttypeinfo[pid(), typeinfo]; + ref_count = $arg3; + state = $arg4; +} + +/** + * probe glib.variant_unref: + * @value: pointer to #GVariant + * @typeinfo: the raw typeinfo structure pointer + * @typestr: the type string of the #GVariant + * @ref_count: the reference count before the call + * @state: the internal state bitfield + * + * Reports that g_variant_unref() has been called on a value. + **/ +probe glib.variant_unref = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("variant__unref") +{ + value = $arg1; + typeinfo = $arg2; + typestr = gvarianttypeinfo[pid(), typeinfo]; + old_ref_count = $arg3; + new_ref_count = old_ref_count - 1; + state = $arg4; +} + +/** + * probe glib.variant_ref: + * @value: pointer to #GVariant + * @typeinfo: the raw typeinfo structure pointer + * @typestr: the type string of the #GVariant + * @ref_count: the reference count before the call + * @state: the internal state bitfield + * + * Reports that g_variant_ref() has been called on a value. + **/ +probe glib.variant_ref = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("variant__ref") +{ + value = $arg1; + typeinfo = $arg2; + typestr = gvarianttypeinfo[pid(), typeinfo]; + old_ref_count = $arg3; + new_ref_count = $arg3 + 1; + state = $arg4; +} + +/** + * probe glib.variant_ref_sink: + * @value: pointer to #GVariant + * @typeinfo: the raw typeinfo structure pointer + * @typestr: the type string of the #GVariant + * @ref_count: the reference count before the call + * @state: the internal state bitfield + * @floating: the floating bit of @state + * + * Reports that g_variant_ref_sink() has been called on a value. + **/ +probe glib.variant_ref_sink = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("variant__ref_sink") +{ + value = $arg1; + typeinfo = $arg2; + typestr = gvarianttypeinfo[pid(), typeinfo]; + ref_count = $arg3; + state = $arg4; + floating = $arg5; +} + +/** + * probe glib.variant_take_ref: + * @value: pointer to #GVariant + * @typeinfo: the raw typeinfo structure pointer + * @typestr: the type string of the #GVariant + * @ref_count: the reference count before the call + * @state: the internal state bitfield + * @floating: the floating bit of @state + * + * Reports that g_variant_take_ref() has been called on a value. + **/ +probe glib.variant_take_ref = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("variant__take_ref") +{ + value = $arg1; + typeinfo = $arg2; + typestr = gvarianttypeinfo[pid(), typeinfo]; + ref_count = $arg3; + state = $arg4; + floating = $arg5; +} + +/** + * probe glib.variant_from_parent: + * @value: pointer to #GVariant + * @typeinfo: the raw typeinfo structure pointer + * @typestr: the type string of the #GVariant + * @ref_count: the initial reference count + * @state: the internal state bitfield + * + * Reports that a #GVariant has been created as a result of calling + * g_variant_get_child_value() on a serialised #GVariant (ie: + * deserialisation has occured). + **/ +probe glib.variant_from_parent = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("variant__from_parent") +{ + value = $arg1; + typeinfo = $arg2; + typestr = gvarianttypeinfo[pid(), typeinfo]; + ref_count = $arg3; + state = $arg4; +} diff --git a/glib/glib_probes.d b/glib/glib_probes.d index 14bb8f1ec..d663b81bf 100644 --- a/glib/glib_probes.d +++ b/glib/glib_probes.d @@ -47,4 +47,15 @@ provider glib { probe rcbox__acquire(void*, unsigned int); probe rcbox__release(void*, unsigned int); probe rcbox__free(void*); + probe variant__type_info_new(void*, const char*); + probe variant__type_info_free(void*); + probe variant__start_serialise(void*, const char*); + probe variant__end_serialise(void*, const char*); + probe variant__from_buffer(void*, const char*, int, int); + probe variant__from_children(void*, const char*, int, int); + probe variant__unref(void*, const char*, int, int); + probe variant__ref(void*, const char*, int, int); + probe variant__ref_sink(void*, const char*, int, int, int); + probe variant__take_ref(void*, const char*, int, int, int); + probe variant__from_parent(void*, const char*, int, int, void*); }; diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c index f5e9dddfe..06e857bde 100644 --- a/glib/gvariant-core.c +++ b/glib/gvariant-core.c @@ -34,6 +34,7 @@ #include #include +#include "glib_trace.h" /* * This file includes the structure definition for GVariant and a small @@ -528,6 +529,7 @@ g_variant_ensure_serialised (GVariant *value) GBytes *bytes; gpointer data; + TRACE(GLIB_VARIANT_START_SERIALISE(value, value->type_info)); g_variant_ensure_size (value); data = g_malloc (value->size); g_variant_serialise (value, data); @@ -540,6 +542,7 @@ g_variant_ensure_serialised (GVariant *value) value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE; value->contents.serialised.checked_offsets_up_to = G_MAXSIZE; value->state |= STATE_SERIALISED; + TRACE(GLIB_VARIANT_END_SERIALISE(value, value->type_info)); } } @@ -676,6 +679,8 @@ g_variant_new_from_bytes (const GVariantType *type, g_clear_pointer (&owned_bytes, g_bytes_unref); + TRACE(GLIB_VARIANT_FROM_BUFFER(value, value->type_info, value->ref_count, value->state)); + return value; } @@ -708,6 +713,7 @@ g_variant_new_from_children (const GVariantType *type, value = g_variant_alloc (type, FALSE, trusted); value->contents.tree.children = children; value->contents.tree.n_children = n_children; + TRACE(GLIB_VARIANT_FROM_CHILDREN(value, value->type_info, value->ref_count, value->state)); return value; } @@ -781,6 +787,8 @@ g_variant_unref (GVariant *value) { g_return_if_fail (value != NULL); + TRACE(GLIB_VARIANT_UNREF(value, value->type_info, value->ref_count, value->state)); + if (g_atomic_ref_count_dec (&value->ref_count)) { if G_UNLIKELY (value->state & STATE_LOCKED) @@ -816,6 +824,8 @@ g_variant_ref (GVariant *value) { g_return_val_if_fail (value != NULL, NULL); + TRACE(GLIB_VARIANT_REF(value, value->type_info, value->ref_count, value->state)); + g_atomic_ref_count_inc (&value->ref_count); return value; @@ -860,6 +870,8 @@ g_variant_ref_sink (GVariant *value) g_variant_lock (value); + TRACE(GLIB_VARIANT_REF_SINK(value, value->type_info, value->ref_count, value->state, value->state & STATE_FLOATING)); + if (~value->state & STATE_FLOATING) g_variant_ref (value); else @@ -915,6 +927,7 @@ g_variant_take_ref (GVariant *value) g_return_val_if_fail (value != NULL, NULL); g_return_val_if_fail (!g_atomic_ref_count_compare (&value->ref_count, 0), NULL); + TRACE(GLIB_VARIANT_TAKE_REF(value, value->type_info, value->ref_count, value->state, value->state & STATE_FLOATING)); g_atomic_int_and (&value->state, ~STATE_FLOATING); return value; @@ -1203,6 +1216,8 @@ g_variant_get_child_value (GVariant *value, child->contents.serialised.ordered_offsets_up_to = (value->state & STATE_TRUSTED) ? G_MAXSIZE : s_child.ordered_offsets_up_to; child->contents.serialised.checked_offsets_up_to = (value->state & STATE_TRUSTED) ? G_MAXSIZE : s_child.checked_offsets_up_to; + TRACE(GLIB_VARIANT_FROM_PARENT(child, child->type_info, child->ref_count, child->state, value)); + return child; } } diff --git a/glib/gvarianttypeinfo.c b/glib/gvarianttypeinfo.c index 4e2e9c5b4..d2df7fd89 100644 --- a/glib/gvarianttypeinfo.c +++ b/glib/gvarianttypeinfo.c @@ -30,6 +30,8 @@ #include #include +#include "glib_trace.h" + /* < private > * GVariantTypeInfo: * @@ -793,6 +795,8 @@ g_variant_type_info_get (const GVariantType *type) container->type_string = type_string; g_atomic_ref_count_init (&container->ref_count); + TRACE(GLIB_VARIANT_TYPE_INFO_NEW(info, container->type_string)); + g_hash_table_insert (g_variant_type_info_table, type_string, info); type_string = NULL; } @@ -818,6 +822,8 @@ g_variant_type_info_get (const GVariantType *type) info = g_variant_type_info_basic_table + index; g_variant_type_info_check (info, 0); + TRACE(GLIB_VARIANT_TYPE_INFO_NEW(info, g_variant_type_info_basic_chars[index])); + return (GVariantTypeInfo *) info; } } @@ -862,6 +868,9 @@ g_variant_type_info_unref (GVariantTypeInfo *info) g_rec_mutex_lock (&g_variant_type_info_lock); if (g_atomic_ref_count_dec (&container->ref_count)) { + + TRACE(GLIB_VARIANT_TYPE_INFO_FREE(info)); + g_hash_table_remove (g_variant_type_info_table, container->type_string); if (g_hash_table_size (g_variant_type_info_table) == 0)