summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Hergert <chergert@redhat.com>2023-02-21 14:30:58 -0800
committerChristian Hergert <chergert@redhat.com>2023-02-21 14:30:58 -0800
commitdf80f432f0f9cdeb161b01bb5abd5aac4743509a (patch)
tree95e514e0a1a1fec358f5808c1d6136403180fe8c
parent378f1421f0a290d753eea672fb49a2545c3788c8 (diff)
downloadgtk+-wip/chergert/profiler-stack.tar.gz
-rw-r--r--gdk/backtrace-helper.h81
-rw-r--r--gdk/gdkprofiler.c19
-rw-r--r--gdk/gdkprofilerprivate.h4
-rw-r--r--gtk/gtkrange.c34
-rw-r--r--meson.build1
5 files changed, 124 insertions, 15 deletions
diff --git a/gdk/backtrace-helper.h b/gdk/backtrace-helper.h
new file mode 100644
index 0000000000..04e5263550
--- /dev/null
+++ b/gdk/backtrace-helper.h
@@ -0,0 +1,81 @@
+/* backtrace-helper.h
+ *
+ * Copyright 2020-2023 Christian Hergert <chergert@redhat.com>
+ *
+ * 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.1 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 General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include <sysprof-capture.h>
+
+#ifdef HAVE_EXECINFO_H
+# include <execinfo.h>
+#endif
+#ifdef ENABLE_LIBUNWIND
+# define UNW_LOCAL_ONLY
+# include <libunwind.h>
+#endif
+
+static void
+backtrace_init (void)
+{
+#ifdef ENABLE_LIBUNWIND
+ unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD);
+# ifdef HAVE_UNW_SET_CACHE_SIZE
+ unw_set_cache_size (unw_local_addr_space, 1024, 0);
+#endif
+#endif
+}
+
+static int
+backtrace_func (SysprofCaptureAddress *addrs,
+ guint n_addrs,
+ G_GNUC_UNUSED gpointer user_data)
+{
+#if defined(ENABLE_LIBUNWIND)
+# if GLIB_SIZEOF_VOID_P == 8
+ /* We know that collector will overwrite fields *AFTER* it
+ * has called the backtrace function allowing us to cheat
+ * and subtract an offset from addrs to avoid having to
+ * copy frame pointers around.
+ */
+ return unw_backtrace ((void **)addrs - 2, n_addrs) - 2;
+# else
+ static const int skip = 2;
+ void **stack = alloca (n_addrs * sizeof (gpointer));
+ int n = unw_backtrace (stack, n_addrs);
+ for (guint i = skip; i < n; i++)
+ addrs[i-skip] = GPOINTER_TO_SIZE (stack[i]);
+ return MAX (0, n - skip);
+# endif
+#elif defined(HAVE_EXECINFO_H)
+# if GLIB_SIZEOF_VOID_P == 8
+ /* See note on unw_backtrace() */
+ return backtrace ((void **)addrs - 2, n_addrs) - 2;
+# else /* GLIB_SIZEOF_VOID_P != 8 */
+ static const int skip = 2;
+ void **stack = alloca (n_addrs * sizeof (gpointer));
+ int n = backtrace (stack, n_addrs);
+ for (guint i = skip; i < n; i++)
+ addrs[i-skip] = GPOINTER_TO_SIZE (stack[i]);
+ return MAX (0, n - skip);
+# endif /* GLIB_SIZEOF_VOID_P */
+#else
+ return 0;
+#endif
+}
+
diff --git a/gdk/gdkprofiler.c b/gdk/gdkprofiler.c
index b51cd7eb37..015fd9957d 100644
--- a/gdk/gdkprofiler.c
+++ b/gdk/gdkprofiler.c
@@ -32,6 +32,9 @@
#include "gdkversionmacros.h"
#include "gdkframeclockprivate.h"
+#ifdef HAVE_SYSPROF
+# include "backtrace-helper.h"
+#endif
gboolean
gdk_profiler_is_running (void)
@@ -160,3 +163,19 @@ void
sysprof_collector_set_counters (&id, &value, 1);
#endif
}
+
+void
+(gdk_profiler_add_stacktrace) (void)
+{
+#ifdef HAVE_SYSPROF
+ static gsize did_init;
+
+ if (!did_init)
+ {
+ did_init = TRUE;
+ backtrace_init ();
+ }
+
+ sysprof_collector_sample (backtrace_func, NULL);
+#endif
+}
diff --git a/gdk/gdkprofilerprivate.h b/gdk/gdkprofilerprivate.h
index 897f4f804e..96fb26531c 100644
--- a/gdk/gdkprofilerprivate.h
+++ b/gdk/gdkprofilerprivate.h
@@ -63,6 +63,8 @@ void gdk_profiler_end_markf (gint64 begin_time,
const gchar *message_format,
...) G_GNUC_PRINTF (3, 4);
+void gdk_profiler_add_stacktrace (void);
+
guint gdk_profiler_define_counter (const char *name,
const char *description);
guint gdk_profiler_define_int_counter (const char *name,
@@ -86,6 +88,8 @@ void gdk_profiler_set_int_counter (guint id,
/* no varargs macro support; the call will have to be optimised out by the compiler */
#endif
+#define gdk_profiler_add_stacktrace() G_STMT_START {} G_STMT_END
+
#define gdk_profiler_define_counter(n, d) 0
#define gdk_profiler_define_int_counter(n, d) 0
#define gdk_profiler_set_counter(i, v) G_STMT_START {} G_STMT_END
diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c
index ebe4cb706b..9876ea1966 100644
--- a/gtk/gtkrange.c
+++ b/gtk/gtkrange.c
@@ -20,13 +20,15 @@
* Modified by the GTK+ Team and others 1997-2004. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
#include "gtkrangeprivate.h"
+#include "gdkprofilerprivate.h"
+
#include "gtkaccessible.h"
#include "gtkaccessiblerange.h"
#include "gtkadjustmentprivate.h"
@@ -688,7 +690,7 @@ gtk_range_set_adjustment (GtkRange *range,
priv->adjustment = adjustment;
g_object_ref_sink (adjustment);
-
+
g_signal_connect (adjustment, "changed",
G_CALLBACK (gtk_range_adjustment_changed),
range);
@@ -1069,7 +1071,7 @@ gtk_range_set_range (GtkRange *range,
GtkRangePrivate *priv = gtk_range_get_instance_private (range);
GtkAdjustment *adjustment;
double value;
-
+
g_return_if_fail (GTK_IS_RANGE (range));
g_return_if_fail (min <= max);
@@ -1548,7 +1550,7 @@ clamp_dimensions (int range_width,
*width += extra;
}
}
-
+
/* See if we can fit rect, if not kill the border */
shortage = *width - range_width;
if (shortage > 0)
@@ -1585,7 +1587,7 @@ clamp_dimensions (int range_width,
border->bottom += extra / 2 + extra % 2;
}
}
-
+
/* See if we can fit rect, if not kill the border */
shortage = *height - range_height;
if (shortage > 0)
@@ -2348,6 +2350,8 @@ gtk_range_adjustment_changed (GtkAdjustment *adjustment,
double upper = gtk_adjustment_get_upper (priv->adjustment);
double lower = gtk_adjustment_get_lower (priv->adjustment);
+ gdk_profiler_add_stacktrace ();
+
gtk_widget_set_visible (priv->slider_widget, upper != lower || !GTK_IS_SCALE (range));
gtk_widget_queue_allocate (priv->trough_widget);
@@ -2391,7 +2395,7 @@ gtk_range_adjustment_value_changed (GtkAdjustment *adjustment,
}
static void
-apply_marks (GtkRange *range,
+apply_marks (GtkRange *range,
double oldval,
double *newval)
{
@@ -2502,7 +2506,7 @@ gtk_range_scroll (GtkRange *range,
else
step_back (range);
break;
-
+
case GTK_SCROLL_STEP_UP:
if (should_invert_move (range, GTK_ORIENTATION_VERTICAL))
step_forward (range);
@@ -2516,18 +2520,18 @@ gtk_range_scroll (GtkRange *range,
else
step_forward (range);
break;
-
+
case GTK_SCROLL_STEP_DOWN:
if (should_invert_move (range, GTK_ORIENTATION_VERTICAL))
step_back (range);
else
step_forward (range);
break;
-
+
case GTK_SCROLL_STEP_BACKWARD:
step_back (range);
break;
-
+
case GTK_SCROLL_STEP_FORWARD:
step_forward (range);
break;
@@ -2538,7 +2542,7 @@ gtk_range_scroll (GtkRange *range,
else
page_back (range);
break;
-
+
case GTK_SCROLL_PAGE_UP:
if (should_invert_move (range, GTK_ORIENTATION_VERTICAL))
page_forward (range);
@@ -2552,18 +2556,18 @@ gtk_range_scroll (GtkRange *range,
else
page_forward (range);
break;
-
+
case GTK_SCROLL_PAGE_DOWN:
if (should_invert_move (range, GTK_ORIENTATION_VERTICAL))
page_back (range);
else
page_forward (range);
break;
-
+
case GTK_SCROLL_PAGE_BACKWARD:
page_back (range);
break;
-
+
case GTK_SCROLL_PAGE_FORWARD:
page_forward (range);
break;
@@ -2853,7 +2857,7 @@ _gtk_range_set_stop_values (GtkRange *range,
priv->n_marks = n_values;
- for (i = 0; i < n_values; i++)
+ for (i = 0; i < n_values; i++)
priv->marks[i] = values[i];
gtk_range_calc_marks (range);
diff --git a/meson.build b/meson.build
index 81c5a459eb..e7254d329c 100644
--- a/meson.build
+++ b/meson.build
@@ -156,6 +156,7 @@ check_headers = [
'crt/externs.h',
'dev/evdev/input.h',
'dlfcn.h',
+ 'execinfo.h',
'ftw.h',
'inttypes.h',
'linux/input.h',