[gnome-talos] Add support for Intel GPU snapshotting
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-talos] Add support for Intel GPU snapshotting
- Date: Mon, 26 Sep 2011 21:13:53 +0000 (UTC)
commit 9c73e2ade87817eab6000810dcd9cf816ca36076
Author: Colin Walters <walters verbum org>
Date: Mon Sep 26 17:13:01 2011 -0400
Add support for Intel GPU snapshotting
Makefile-src.am | 6 +-
configure.ac | 13 +++
src/gnome-talos-gpu.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++++
src/gnome-talos-gpu.h | 29 ++++++
src/gnome-talos-meta.c | 2 +
src/gnome-talos.c | 26 +++++-
src/util.c | 128 ++++++++++++++++++++++++++-
src/util.h | 40 +++++++++
8 files changed, 463 insertions(+), 8 deletions(-)
---
diff --git a/Makefile-src.am b/Makefile-src.am
index 9672d63..71dd416 100644
--- a/Makefile-src.am
+++ b/Makefile-src.am
@@ -10,10 +10,14 @@ gnome-talos-session-%.desktop: src/gnome-talos-session.desktop.in
bin_PROGRAMS += gnome-talos
gnome_talos_SOURCES = src/gnome-talos.c \
+ src/gnome-talos-gpu.c \
+ src/gnome-talos-gpu.h \
src/gnome-talos-procinfo.c \
src/gnome-talos-procinfo.h \
src/gnome-talos-meta.c \
- src/gnome-talos-meta.h
+ src/gnome-talos-meta.h \
+ src/util.c \
+ src/util.h
gnome_talos_CPPFLAGS = $(GNOME_TALOS_CFLAGS) -I $(top_srcdir) -I $(top_builddir)
gnome_talos_LDADD = $(GNOME_TALOS_LIBS)
diff --git a/configure.ac b/configure.ac
index 6474c6c..6ac905a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -54,6 +54,19 @@ AC_DEFINE_UNQUOTED([GIT_VERSION], "$GIT_VERSION", [Output of git describe if ava
LT_PREREQ([2.2.6])
LT_INIT([disable-static])
+changequote(,)dnl
+if test "x$GCC" = "xyes"; then
+ case " $CFLAGS " in
+ *[\ \ ]-Wall[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -Wall" ;;
+ esac
+ case " $CFLAGS " in
+ *[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
+ *) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
+ esac
+fi
+changequote([,])dnl
+
PKG_PROG_PKG_CONFIG([0.22])
PKG_CHECK_MODULES(GLIB, [glib-2.0])
diff --git a/src/gnome-talos-gpu.c b/src/gnome-talos-gpu.c
new file mode 100644
index 0000000..768970c
--- /dev/null
+++ b/src/gnome-talos-gpu.c
@@ -0,0 +1,227 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters verbum org>
+ */
+
+#include "config.h"
+
+#include <gio/gio.h>
+
+#include <string.h>
+#include <stdio.h>
+
+#include "gnome-talos-gpu.h"
+#include "util.h"
+
+#define GPU_BASE_PATH "/sys/kernel/debug/dri"
+
+static char *gpudir;
+static gboolean is_i915;
+static GRegex *i915_gem_objects_regex;
+
+static void
+init_gpu_dir_unlocked (void)
+{
+ const char *filename;
+ GDir *dir;
+ GSList *names = NULL;
+ GSList *iter;
+
+ dir = g_dir_open (GPU_BASE_PATH, 0, NULL);
+ if (!dir)
+ {
+ gpudir = NULL;
+ return;
+ }
+
+ while ((filename = g_dir_read_name (dir)) != NULL)
+ {
+ names = g_slist_prepend (names, g_strdup (filename));
+ }
+ g_dir_close (dir);
+
+ for (iter = names; iter; iter = iter->next)
+ {
+ gboolean name_exists;
+ char *name;
+ char *contents;
+
+ name = g_build_filename (GPU_BASE_PATH, iter->data, "name", NULL);
+ if (g_file_test (name, G_FILE_TEST_EXISTS)
+ && g_file_get_contents (name, &contents, NULL, NULL))
+ {
+ name_exists = strlen (contents) > 0;
+ g_free (contents);
+ }
+ else
+ name_exists = FALSE;
+ g_free (name);
+
+ if (name_exists)
+ {
+ gpudir = g_build_filename (GPU_BASE_PATH, iter->data, NULL);
+ break;
+ }
+ }
+
+ for (iter = names->next; iter; iter = iter->next)
+ {
+ if (iter->data != gpudir)
+ g_free (iter->data);
+ }
+}
+
+
+static void
+init_gpu_static (void)
+{
+ static gsize statics_initialized = 0;
+ char *filename;
+
+ if (!g_once_init_enter (&statics_initialized))
+ return;
+
+ init_gpu_dir_unlocked ();
+
+ filename = g_build_filename (gpudir, "i915_capabilities", NULL);
+ is_i915 = g_file_test (filename, G_FILE_TEST_EXISTS);
+ g_free (filename);
+
+ i915_gem_objects_regex = g_regex_new ("([0-9]+) objects, ([0-9]+) bytes", 0, 0, NULL);
+
+ g_once_init_leave (&statics_initialized, 1);
+}
+
+
+GVariant *
+gnome_talos_acquire_gpu_meta (GError **error)
+{
+ char *name;
+ GVariantBuilder builder;
+
+ init_gpu_static ();
+
+ if (gpudir == NULL)
+ return NULL;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+ name = talos_util_build_filename_get_utf8_contents_sync (error,
+ gpudir,
+ "name",
+ NULL);
+ if (!name)
+ goto failed;
+
+ g_variant_builder_add (&builder, "{sv}",
+ "name",
+ g_variant_new_string (name));
+ g_free (name);
+
+ if (is_i915)
+ {
+ GVariantBuilder i915_builder;
+ GVariant *i915_capabilities;
+ char *filename;
+
+ filename = g_build_filename (gpudir, "i915_capabilities", NULL);
+ i915_capabilities = talos_util_rfc822_file_to_variant (filename, error);
+ g_free (filename);
+ if (!i915_capabilities)
+ goto failed;
+
+ g_variant_builder_init (&i915_builder, G_VARIANT_TYPE ("a{sv}"));
+
+ g_variant_builder_add (&i915_builder, "{sv}",
+ "capabilities",
+ g_variant_new_variant (i915_capabilities));
+
+ g_variant_builder_add (&builder, "{sv}",
+ "i915",
+ g_variant_new_variant (g_variant_builder_end (&i915_builder)));
+ }
+
+ return g_variant_builder_end (&builder);
+
+ failed:
+ g_variant_builder_clear (&builder);
+ return NULL;
+}
+
+static gboolean
+i915_gpu_snapshot (GVariantBuilder *builder,
+ GError **error)
+{
+ char *contents;
+ GMatchInfo *match;
+
+ contents = talos_util_build_filename_get_utf8_contents_sync (error, gpudir, "i915_gem_objects", NULL);
+ if (!contents)
+ return FALSE;
+
+ if (g_regex_match (i915_gem_objects_regex, contents, 0, &match))
+ {
+ char *count;
+
+ count = g_match_info_fetch (match, 1);
+ g_variant_builder_add (builder, "{sv}",
+ "gem-object-count",
+ g_variant_new_int64 (g_ascii_strtoll (count, NULL, 10)));
+ g_free (count);
+ count = g_match_info_fetch (match, 2);
+ g_variant_builder_add (builder, "{sv}",
+ "gem-object-bytes",
+ g_variant_new_int64 (g_ascii_strtoll (count, NULL, 10)));
+ g_free (count);
+ g_match_info_free (match);
+ }
+
+ return TRUE;
+}
+
+GVariant *
+gnome_talos_acquire_gpu_snapshot (GError **error)
+{
+ GVariantBuilder builder;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+ if (is_i915)
+ {
+ GVariantBuilder i915_builder;
+
+ g_variant_builder_init (&i915_builder, G_VARIANT_TYPE ("a{sv}"));
+
+ if (!i915_gpu_snapshot (&i915_builder, error))
+ {
+ g_variant_builder_clear (&i915_builder);
+ goto failed;
+ }
+
+ g_variant_builder_add (&builder, "{sv}",
+ "i915",
+ g_variant_new_variant (g_variant_builder_end (&i915_builder)));
+ }
+
+ return g_variant_builder_end (&builder);
+
+ failed:
+ g_variant_builder_clear (&builder);
+ return NULL;
+}
diff --git a/src/gnome-talos-gpu.h b/src/gnome-talos-gpu.h
new file mode 100644
index 0000000..8ebf9c5
--- /dev/null
+++ b/src/gnome-talos-gpu.h
@@ -0,0 +1,29 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters verbum org>
+ */
+
+#ifndef __GNOME_TALOS_GPU__
+#define __GNOME_TALOS_GPU__ 1
+
+GVariant * gnome_talos_acquire_gpu_meta (GError **error);
+
+GVariant * gnome_talos_acquire_gpu_snapshot (GError **error);
+
+#endif
diff --git a/src/gnome-talos-meta.c b/src/gnome-talos-meta.c
index 37b1ab9..ed003cc 100644
--- a/src/gnome-talos-meta.c
+++ b/src/gnome-talos-meta.c
@@ -23,6 +23,8 @@
#include <gio/gio.h>
+#include "gnome-talos-meta.h"
+
#include <string.h>
GVariant *
diff --git a/src/gnome-talos.c b/src/gnome-talos.c
index d3667a9..656dc2d 100644
--- a/src/gnome-talos.c
+++ b/src/gnome-talos.c
@@ -28,6 +28,7 @@
#include <string.h>
#include "gnome-talos-procinfo.h"
+#include "gnome-talos-gpu.h"
#include "gnome-talos-meta.h"
#include "report.html.h"
@@ -48,17 +49,22 @@ static gint timeout = 5;
static char *log_file_path = NULL;
static char *to_html_file_path = NULL;
-GVariant *
+static GVariant *
gather_snapshot (void)
{
+ GError *error = NULL;
gint64 start_timestamp, end_timestamp;
GVariant *proc_data;
+ GVariant *gpu_data;
GVariantBuilder builder;
GVariant *data;
start_timestamp = g_get_monotonic_time ();
proc_data = gnome_talos_acquire_procinfo ();
+ gpu_data = gnome_talos_acquire_gpu_snapshot (&error);
+ if (gpu_data == NULL)
+ fatal_gerror (&error);
end_timestamp = g_get_monotonic_time ();
@@ -78,6 +84,7 @@ gather_snapshot (void)
g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&builder, "{sv}", "processes", proc_data);
+ g_variant_builder_add (&builder, "{sv}", "gpu", gpu_data);
g_variant_builder_close (&builder);
@@ -149,6 +156,8 @@ on_interrupt_received (gpointer user_data)
fatal_gerror (&error);
g_main_loop_quit (app->loop);
+
+ return FALSE;
}
static void
@@ -156,13 +165,14 @@ run_collection (GnomeTalosApp *app)
{
GError *error = NULL;
GVariant *sysinfo;
+ GVariant *gpu_meta;
g_unix_signal_add (SIGINT,
on_interrupt_received,
- &app);
+ app);
g_unix_signal_add (SIGTERM,
on_interrupt_received,
- &app);
+ app);
app->out = g_file_replace (app->log_file, NULL, FALSE,
G_FILE_CREATE_REPLACE_DESTINATION,
@@ -179,11 +189,18 @@ run_collection (GnomeTalosApp *app)
fatal_gerror (&error);
g_variant_unref (sysinfo);
+ gpu_meta = gnome_talos_acquire_gpu_meta (&error);
+ if (!gpu_meta)
+ fatal_gerror (&error);
+ if (!write_variant (gpu_meta, NULL, (GOutputStream*)app->out, &error))
+ fatal_gerror (&error);
+ g_variant_unref (gpu_meta);
+
if (!g_output_stream_write_all ((GOutputStream*)app->out,
",\n", 2, NULL, NULL, &error))
fatal_gerror (&error);
- g_idle_add (timeout_gather_data, &app);
+ g_idle_add (timeout_gather_data, app);
}
static char *
@@ -222,7 +239,6 @@ convert_to_html (GnomeTalosApp *app)
GFileOutputStream *out;
char *data_string;
char *buf;
- GRegex *regex;
parser = json_parser_new ();
diff --git a/src/util.c b/src/util.c
index a37c10f..c61894a 100644
--- a/src/util.c
+++ b/src/util.c
@@ -19,10 +19,134 @@
* Author: Colin Walters <walters verbum org>
*/
+#include "config.h"
+
+#include "util.h"
+
+#include <gio/gio.h>
+
+#include <string.h>
+
char *
-gnome_talos_util_build_filenamea (const char *name,
- ...)
+talos_util_build_filename_get_utf8_contents_sync (GError **error,
+ const char *filename,
+ ...)
{
+ GPtrArray *filenames;
+ va_list args;
+ char *full_filename;
+ char *content;
+
+ va_start (args, filename);
+
+ filenames = g_ptr_array_new ();
+ g_ptr_array_add (filenames, (char*)filename);
+
+ while ((filename = va_arg (args, const char*)) != NULL)
+ g_ptr_array_add (filenames, (char*)filename);
+ g_ptr_array_add (filenames, NULL);
+ full_filename = g_build_filenamev ((char**)filenames->pdata);
+
+ g_ptr_array_free (filenames, TRUE);
+ va_end (args);
+
+ content = talos_util_get_file_contents_utf8_sync (full_filename, error);
+
+ g_free (full_filename);
+
+ return content;
}
+
+/**
+ * talos_util_get_file_contents_utf8_sync:
+ * @path: UTF-8 encoded filename path
+ * @error: a #GError
+ *
+ * Synchronously load the contents of a file as a NUL terminated
+ * string, validating it as UTF-8. Embedded NUL characters count as
+ * invalid content.
+ *
+ * Returns: (transfer full): File contents
+ */
+char *
+talos_util_get_file_contents_utf8_sync (const char *path,
+ GError **error)
+{
+ char *contents;
+ gsize len;
+ if (!g_file_get_contents (path, &contents, &len, error))
+ return NULL;
+ if (!g_utf8_validate (contents, len, NULL))
+ {
+ g_free (contents);
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "File %s contains invalid UTF-8",
+ path);
+ return NULL;
+ }
+ return contents;
+}
+
+GVariant *
+talos_util_rfc822_file_to_variant (const char *path,
+ GError **error)
+{
+ GVariantBuilder builder;
+ GVariant *res = NULL;
+ GFile *file;
+ GFileInputStream *in = NULL;
+ GDataInputStream *datain = NULL;
+ char *line = NULL;
+ GError *temp_error = NULL;
+
+ file = g_file_new_for_path (path);
+ in = g_file_read (file, NULL, error);
+ g_object_unref (file);
+ if (!in)
+ return NULL;
+ datain = g_data_input_stream_new ((GInputStream*)in);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+ while ((line = g_data_input_stream_read_line_utf8 (datain, NULL, NULL, &temp_error)) != NULL)
+ {
+ char *colon;
+ colon = strchr (line, ':');
+ if (colon)
+ {
+ char *key;
+ char *value;
+
+ key = line;
+ *colon = '\0';
+ value = colon + 1;
+ g_strstrip (key);
+ g_strstrip (value);
+
+ g_variant_builder_add (&builder, "{sv}",
+ key, g_variant_new_string (value));
+ }
+ g_free (line);
+ line = NULL;
+ }
+
+ if (temp_error != NULL)
+ {
+ g_free (line);
+ g_variant_builder_clear (&builder);
+ g_propagate_error (error, temp_error);
+ goto out;
+ }
+ else
+ res = g_variant_builder_end (&builder);
+
+ out:
+ g_object_unref (in);
+ g_object_unref (datain);
+ return res;
+}
+
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 0000000..befd426
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,40 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters verbum org>
+ */
+
+#ifndef __GNOME_TALOS_UTIL__
+#define __GNOME_TALOS_UTIL__ 1
+
+#include <glib.h>
+
+char *
+talos_util_build_filename_get_utf8_contents_sync (GError **error,
+ const char *arg0,
+ ...) G_GNUC_NULL_TERMINATED;
+
+char *
+talos_util_get_file_contents_utf8_sync (const char *path,
+ GError **error);
+
+GVariant *
+talos_util_rfc822_file_to_variant (const char *path,
+ GError **error);
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]