diff --git a/0001-memory-add-memory-source-for-basic-mem-stats.patch b/0001-memory-add-memory-source-for-basic-mem-stats.patch deleted file mode 100644 index 20e8061..0000000 --- a/0001-memory-add-memory-source-for-basic-mem-stats.patch +++ /dev/null @@ -1,653 +0,0 @@ -From 52f411e1de44864932b320fceeb3f8ad5e7bd190 Mon Sep 17 00:00:00 2001 -From: Christian Hergert -Date: Fri, 12 Oct 2018 17:11:17 -0700 -Subject: [PATCH] memory: add memory source for basic mem stats - ---- - lib/sources/meson.build | 4 +- - lib/sources/sp-memory-source.c | 494 +++++++++++++++++++++++++++++++++ - lib/sources/sp-memory-source.h | 33 +++ - lib/sysprof.h | 1 + - src/sp-window.c | 4 + - tools/sysprof-cli.c | 9 + - 6 files changed, 544 insertions(+), 1 deletion(-) - create mode 100644 lib/sources/sp-memory-source.c - create mode 100644 lib/sources/sp-memory-source.h - -diff --git a/lib/sources/meson.build b/lib/sources/meson.build -index a5dd0fa..6a3ab64 100644 ---- a/lib/sources/meson.build -+++ b/lib/sources/meson.build -@@ -1,6 +1,7 @@ - sources_headers = [ - 'sp-gjs-source.h', - 'sp-hostinfo-source.h', -+ 'sp-memory-source.h', - 'sp-perf-source.h', - 'sp-proc-source.h', - 'sp-source.h', -@@ -9,6 +10,7 @@ sources_headers = [ - sources_sources = [ - 'sp-gjs-source.c', - 'sp-hostinfo-source.c', -+ 'sp-memory-source.c', - 'sp-perf-counter.c', - 'sp-perf-counter.h', - 'sp-perf-source.c', -@@ -20,4 +22,4 @@ libsysprof_headers += files(sources_headers) - libsysprof_sources += files(sources_sources) - - install_headers(sources_headers, -- subdir: join_paths(libsysprof_header_subdir, 'sources')) -+ subdir: join_paths(libsysprof_header_subdir, 'sources')) -\ No newline at end of file -diff --git a/lib/sources/sp-memory-source.c b/lib/sources/sp-memory-source.c -new file mode 100644 -index 0000000..2da7f0c ---- /dev/null -+++ b/lib/sources/sp-memory-source.c -@@ -0,0 +1,494 @@ -+/* sp-memory-source.c -+ * -+ * Copyright 2018 Christian Hergert -+ * -+ * 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 3 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, see . -+ * -+ * SPDX-License-Identifier: GPL-3.0-or-later -+ */ -+ -+#include "config.h" -+ -+#define G_LOG_DOMAIN "sp-memory-source" -+ -+#include -+#include -+#include -+#include -+ -+#include "sp-clock.h" -+ -+#include "sources/sp-memory-source.h" -+ -+#define BUF_SIZE 4096 -+ -+struct _SpMemorySource -+{ -+ GObject parent_instance; -+ -+ /* Capture writer to deliver samples */ -+ SpCaptureWriter *writer; -+ -+ /* 4k stat buffer for reading proc */ -+ gchar *stat_buf; -+ -+ /* Array of MemStat */ -+ GArray *mem_stats; -+ -+ /* Timeout to perform polling */ -+ guint timer_source; -+}; -+ -+typedef struct -+{ -+ GPid pid; -+ int stat_fd; -+ -+ /* Keep in this order, so we can address from total */ -+ SpCaptureCounterValue mem_total; -+ SpCaptureCounterValue mem_avail; -+ SpCaptureCounterValue mem_free; -+ -+ /* Keep in this order, so we can address from size */ -+ SpCaptureCounterValue mem_size; -+ SpCaptureCounterValue mem_resident; -+ SpCaptureCounterValue mem_shared; -+ SpCaptureCounterValue mem_text; -+ SpCaptureCounterValue mem_data; -+ -+ guint counter_ids[5]; -+} MemStat; -+ -+static void source_iface_init (SpSourceInterface *iface); -+ -+G_DEFINE_TYPE_WITH_CODE (SpMemorySource, sp_memory_source, G_TYPE_OBJECT, -+ G_IMPLEMENT_INTERFACE (SP_TYPE_SOURCE, source_iface_init)) -+ -+static GHashTable *keys; -+ -+static void -+mem_stat_open (MemStat *st) -+{ -+ g_assert (st != NULL); -+ g_assert (st->stat_fd == -1); -+ -+ if (st->pid != -1) -+ { -+ g_autofree gchar *path = g_strdup_printf ("/proc/%d/statm", st->pid); -+ -+ if (-1 == (st->stat_fd = open (path, O_RDONLY))) -+ g_warning ("Failed to access statm for pid %d", st->pid); -+ } -+ else -+ { -+ st->stat_fd = open ("/proc/meminfo", O_RDONLY); -+ } -+} -+ -+static void -+mem_stat_close (MemStat *st) -+{ -+ g_assert (st != NULL); -+ -+ if (st->stat_fd != -1) -+ { -+ close (st->stat_fd); -+ st->stat_fd = -1; -+ } -+} -+ -+static void -+mem_stat_parse_statm (MemStat *st, -+ gchar *buf) -+{ -+ g_assert (st != NULL); -+ -+ sscanf (buf, -+ "%"G_GINT64_FORMAT" " -+ "%"G_GINT64_FORMAT" " -+ "%"G_GINT64_FORMAT" " -+ "%"G_GINT64_FORMAT" " -+ "%*1c " -+ "%"G_GINT64_FORMAT, -+ &st->mem_size.v64, -+ &st->mem_resident.v64, -+ &st->mem_shared.v64, -+ &st->mem_text.v64, -+ &st->mem_data.v64); -+} -+ -+static void -+mem_stat_parse_meminfo (MemStat *st, -+ gchar *buf) -+{ -+ gchar *bufptr = buf; -+ gchar *save = NULL; -+ -+ g_assert (st != NULL); -+ -+ for (;;) -+ { -+ goffset off; -+ gchar *key; -+ gchar *value; -+ gchar *unit; -+ gint64 v64; -+ gint64 *v64ptr; -+ -+ /* Get the data key name */ -+ if (!(key = strtok_r (bufptr, " \n\t:", &save))) -+ break; -+ -+ bufptr = NULL; -+ -+ /* Offset from self to save value. Stop after getting to -+ * last value we care about. -+ */ -+ if (!(off = GPOINTER_TO_UINT (g_hash_table_lookup (keys, key)))) -+ break; -+ -+ /* Get the data value */ -+ if (!(value = strtok_r (bufptr, " \n\t:", &save))) -+ break; -+ -+ /* Parse the numeric value of this column */ -+ v64 = g_ascii_strtoll (value, NULL, 10); -+ if ((v64 == G_MININT64 || v64 == G_MAXINT64) && errno == ERANGE) -+ break; -+ -+ /* Get the data unit */ -+ unit = strtok_r (bufptr, " \n\t:", &save); -+ -+ if (g_strcmp0 (unit, "kB") == 0) -+ v64 *= 1024; -+ else if (g_strcmp0 (unit, "mB") == 0) -+ v64 *= 1024 * 1024; -+ -+ v64ptr = (gint64 *)(gpointer)(((gchar *)st) + off); -+ -+ *v64ptr = v64; -+ } -+} -+ -+static void -+mem_stat_poll (MemStat *st, -+ gchar *stat_buf) -+{ -+ gssize r; -+ -+ g_assert (st != NULL); -+ g_assert (st->stat_fd != -1); -+ -+ /* Seek to begin of FD to reset the proc read */ -+ if ((r = lseek (st->stat_fd, 0, SEEK_SET)) < 0) -+ return; -+ -+ /* Now read the updated proc buffer */ -+ if ((r = read (st->stat_fd, stat_buf, BUF_SIZE)) < 0) -+ return; -+ -+ if (r < BUF_SIZE) -+ stat_buf[r] = '\0'; -+ stat_buf[BUF_SIZE-1] = '\0'; -+ -+ if (st->pid == -1) -+ mem_stat_parse_meminfo (st, stat_buf); -+ else -+ mem_stat_parse_statm (st, stat_buf); -+} -+ -+static void -+mem_stat_publish (MemStat *st, -+ SpCaptureWriter *writer, -+ gint64 current_time) -+{ -+ g_assert (st != NULL); -+ g_assert (writer != NULL); -+ -+ sp_capture_writer_set_counters (writer, -+ current_time, -+ -1, -+ st->pid, -+ st->counter_ids, -+ st->pid == -1 ? &st->mem_total : &st->mem_size, -+ st->pid == -1 ? 3 : 5); -+} -+ -+/** -+ * sp_memory_source_new: -+ * -+ * Create a new #SpMemorySource. -+ * -+ * Use this source to record basic memory statistics about the system -+ * such as Available, Free, and Total Memory. -+ * -+ * Returns: (transfer full): a newly created #SpMemorySource -+ -+ * Since: 3.32 -+ */ -+SpSource * -+sp_memory_source_new (void) -+{ -+ return g_object_new (SP_TYPE_MEMORY_SOURCE, NULL); -+} -+ -+static void -+sp_memory_source_finalize (GObject *object) -+{ -+ SpMemorySource *self = (SpMemorySource *)object; -+ -+ if (self->timer_source != 0) -+ { -+ g_source_remove (self->timer_source); -+ self->timer_source = 0; -+ } -+ -+ g_clear_pointer (&self->stat_buf, g_free); -+ g_clear_pointer (&self->writer, sp_capture_writer_unref); -+ g_clear_pointer (&self->mem_stats, g_array_unref); -+ -+ G_OBJECT_CLASS (sp_memory_source_parent_class)->finalize (object); -+} -+ -+static void -+sp_memory_source_class_init (SpMemorySourceClass *klass) -+{ -+ GObjectClass *object_class = G_OBJECT_CLASS (klass); -+ -+ object_class->finalize = sp_memory_source_finalize; -+ -+ keys = g_hash_table_new (g_str_hash, g_str_equal); -+ -+#define ADD_OFFSET(n,o) \ -+ g_hash_table_insert (keys, (gchar *)n, GUINT_TO_POINTER (o)) -+ ADD_OFFSET ("MemTotal", G_STRUCT_OFFSET (MemStat, mem_total)); -+ ADD_OFFSET ("MemFree", G_STRUCT_OFFSET (MemStat, mem_free)); -+ ADD_OFFSET ("MemAvailable", G_STRUCT_OFFSET (MemStat, mem_avail)); -+#undef ADD_OFFSET -+} -+ -+static void -+sp_memory_source_init (SpMemorySource *self) -+{ -+ self->stat_buf = g_malloc (BUF_SIZE); -+ self->mem_stats = g_array_new (FALSE, FALSE, sizeof (MemStat)); -+} -+ -+static void -+sp_memory_source_set_writer (SpSource *source, -+ SpCaptureWriter *writer) -+{ -+ SpMemorySource *self = (SpMemorySource *)source; -+ -+ g_assert (SP_IS_SOURCE (self)); -+ g_assert (writer != NULL); -+ g_assert (self->writer == NULL); -+ -+ self->writer = sp_capture_writer_ref (writer); -+} -+ -+static void -+sp_memory_source_prepare (SpSource *source) -+{ -+ SpMemorySource *self = (SpMemorySource *)source; -+ -+ g_assert (SP_IS_MEMORY_SOURCE (self)); -+ g_assert (self->writer != NULL); -+ -+ /* If no pids are registered, setup a system memory stat */ -+ if (self->mem_stats->len == 0) -+ { -+ MemStat st = {0}; -+ -+ st.pid = -1; -+ st.stat_fd = -1; -+ -+ g_array_append_val (self->mem_stats, st); -+ } -+ -+ /* Open FDs to all the necessary files in proc. We will re-use -+ * them to avoid re-opening files later. -+ */ -+ for (guint i = 0; i < self->mem_stats->len; i++) -+ { -+ MemStat *st = &g_array_index (self->mem_stats, MemStat, i); -+ SpCaptureCounter counters[5]; -+ guint base; -+ -+ mem_stat_open (st); -+ -+ for (guint j = 0; j < G_N_ELEMENTS (counters); j++) -+ g_strlcpy (counters[j].category, "Memory", sizeof counters[j].category); -+ -+ if (st->pid == -1) -+ { -+ base = sp_capture_writer_request_counter (self->writer, 3); -+ -+ g_strlcpy (counters[0].name, "Total", sizeof counters[0].name); -+ g_strlcpy (counters[1].name, "Available", sizeof counters[1].name); -+ g_strlcpy (counters[2].name, "Free", sizeof counters[2].name); -+ -+ g_strlcpy (counters[0].description, "", sizeof counters[0].description); -+ g_strlcpy (counters[1].description, "", sizeof counters[1].description); -+ g_strlcpy (counters[2].description, "", sizeof counters[2].description); -+ -+ counters[0].id = st->counter_ids[0] = base; -+ counters[1].id = st->counter_ids[1] = base + 1; -+ counters[2].id = st->counter_ids[2] = base + 2; -+ -+ counters[0].type = SP_CAPTURE_COUNTER_INT64; -+ counters[1].type = SP_CAPTURE_COUNTER_INT64; -+ counters[2].type = SP_CAPTURE_COUNTER_INT64; -+ -+ counters[0].value.v64 = 0; -+ counters[1].value.v64 = 0; -+ counters[2].value.v64 = 0; -+ -+ -+ sp_capture_writer_define_counters (self->writer, -+ SP_CAPTURE_CURRENT_TIME, -+ -1, -+ -1, -+ counters, -+ 3); -+ } -+ else -+ { -+ base = sp_capture_writer_request_counter (self->writer, 5); -+ -+ g_strlcpy (counters[0].name, "Size", sizeof counters[0].name); -+ g_strlcpy (counters[1].name, "Resident", sizeof counters[1].name); -+ g_strlcpy (counters[2].name, "Shared", sizeof counters[2].name); -+ g_strlcpy (counters[3].name, "Text", sizeof counters[3].name); -+ g_strlcpy (counters[4].name, "Data", sizeof counters[4].name); -+ -+ g_strlcpy (counters[0].description, "", sizeof counters[0].description); -+ g_strlcpy (counters[1].description, "", sizeof counters[1].description); -+ g_strlcpy (counters[2].description, "", sizeof counters[2].description); -+ g_strlcpy (counters[3].description, "", sizeof counters[3].description); -+ g_strlcpy (counters[4].description, "", sizeof counters[4].description); -+ -+ counters[0].id = st->counter_ids[0] = base; -+ counters[1].id = st->counter_ids[1] = base + 1; -+ counters[2].id = st->counter_ids[2] = base + 2; -+ counters[3].id = st->counter_ids[3] = base + 3; -+ counters[4].id = st->counter_ids[4] = base + 4; -+ -+ counters[0].type = SP_CAPTURE_COUNTER_INT64; -+ counters[1].type = SP_CAPTURE_COUNTER_INT64; -+ counters[2].type = SP_CAPTURE_COUNTER_INT64; -+ counters[3].type = SP_CAPTURE_COUNTER_INT64; -+ counters[4].type = SP_CAPTURE_COUNTER_INT64; -+ -+ counters[0].value.v64 = 0; -+ counters[1].value.v64 = 0; -+ counters[2].value.v64 = 0; -+ counters[3].value.v64 = 0; -+ counters[4].value.v64 = 0; -+ -+ sp_capture_writer_define_counters (self->writer, -+ SP_CAPTURE_CURRENT_TIME, -+ -1, -+ st->pid, -+ counters, -+ 5); -+ } -+ } -+ -+ sp_source_emit_ready (SP_SOURCE (self)); -+} -+ -+static gboolean -+sp_memory_source_timer_cb (SpMemorySource *self) -+{ -+ gint64 current_time; -+ -+ g_assert (SP_IS_MEMORY_SOURCE (self)); -+ g_assert (self->writer != NULL); -+ -+ current_time = sp_clock_get_current_time (); -+ -+ for (guint i = 0; i < self->mem_stats->len; i++) -+ { -+ MemStat *st = &g_array_index (self->mem_stats, MemStat, i); -+ -+ mem_stat_poll (st, self->stat_buf); -+ mem_stat_publish (st, self->writer, current_time); -+ } -+ -+ return G_SOURCE_CONTINUE; -+} -+ -+static void -+sp_memory_source_start (SpSource *source) -+{ -+ SpMemorySource *self = (SpMemorySource *)source; -+ -+ g_assert (SP_IS_MEMORY_SOURCE (self)); -+ -+ /* Poll 20x/sec for memory stats */ -+ self->timer_source = g_timeout_add_full (G_PRIORITY_HIGH, -+ 1000 / 20, -+ (GSourceFunc)sp_memory_source_timer_cb, -+ self, -+ NULL); -+} -+ -+static void -+sp_memory_source_stop (SpSource *source) -+{ -+ SpMemorySource *self = (SpMemorySource *)source; -+ -+ g_assert (SP_IS_MEMORY_SOURCE (self)); -+ -+ if (self->timer_source != 0) -+ { -+ g_source_remove (self->timer_source); -+ self->timer_source = 0; -+ } -+ -+ for (guint i = 0; i < self->mem_stats->len; i++) -+ { -+ MemStat *st = &g_array_index (self->mem_stats, MemStat, i); -+ -+ mem_stat_close (st); -+ } -+ -+ sp_source_emit_finished (source); -+} -+ -+static void -+sp_memory_source_add_pid (SpSource *source, -+ GPid pid) -+{ -+ SpMemorySource *self = (SpMemorySource *)source; -+ MemStat st = {0}; -+ -+ g_assert (SP_IS_MEMORY_SOURCE (self)); -+ -+ st.pid = pid; -+ st.stat_fd = -1; -+ -+ g_array_append_val (self->mem_stats, st); -+} -+ -+static void -+source_iface_init (SpSourceInterface *iface) -+{ -+ iface->set_writer = sp_memory_source_set_writer; -+ iface->prepare = sp_memory_source_prepare; -+ iface->start = sp_memory_source_start; -+ iface->stop = sp_memory_source_stop; -+ iface->add_pid = sp_memory_source_add_pid; -+} -diff --git a/lib/sources/sp-memory-source.h b/lib/sources/sp-memory-source.h -new file mode 100644 -index 0000000..a50636e ---- /dev/null -+++ b/lib/sources/sp-memory-source.h -@@ -0,0 +1,33 @@ -+/* sp-memory-source.h -+ * -+ * Copyright 2018 Christian Hergert -+ * -+ * 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 3 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, see . -+ * -+ * SPDX-License-Identifier: GPL-3.0-or-later -+ */ -+ -+#pragma once -+ -+#include "sources/sp-source.h" -+ -+G_BEGIN_DECLS -+ -+#define SP_TYPE_MEMORY_SOURCE (sp_memory_source_get_type()) -+ -+G_DECLARE_FINAL_TYPE (SpMemorySource, sp_memory_source, SP, MEMORY_SOURCE, GObject) -+ -+SpSource *sp_memory_source_new (void); -+ -+G_END_DECLS -diff --git a/lib/sysprof.h b/lib/sysprof.h -index be65056..a3fd633 100644 ---- a/lib/sysprof.h -+++ b/lib/sysprof.h -@@ -44,6 +44,7 @@ G_BEGIN_DECLS - - # include "sources/sp-gjs-source.h" - # include "sources/sp-hostinfo-source.h" -+# include "sources/sp-memory-source.h" - # include "sources/sp-perf-source.h" - # include "sources/sp-proc-source.h" - # include "sources/sp-source.h" -diff --git a/src/sp-window.c b/src/sp-window.c -index beab3b7..5d0485e 100644 ---- a/src/sp-window.c -+++ b/src/sp-window.c -@@ -403,6 +403,7 @@ sp_window_add_sources (SpWindow *window, - g_autoptr(SpSource) host_source = NULL; - g_autoptr(SpSource) proc_source = NULL; - g_autoptr(SpSource) perf_source = NULL; -+ g_autoptr(SpSource) memory_source = NULL; - - g_assert (SP_IS_WINDOW (window)); - g_assert (SP_IS_PROFILER (profiler)); -@@ -415,6 +416,9 @@ sp_window_add_sources (SpWindow *window, - - host_source = sp_hostinfo_source_new (); - sp_profiler_add_source (profiler, host_source); -+ -+ memory_source = sp_memory_source_new (); -+ sp_profiler_add_source (profiler, memory_source); - } - - static void -diff --git a/tools/sysprof-cli.c b/tools/sysprof-cli.c -index e433dc9..3be1b9e 100644 ---- a/tools/sysprof-cli.c -+++ b/tools/sysprof-cli.c -@@ -88,6 +88,7 @@ main (gint argc, - GError *error = NULL; - GSource *gsource; - gchar *command = NULL; -+ gboolean memory = FALSE; - gboolean version = FALSE; - gboolean force = FALSE; - int pid = -1; -@@ -97,6 +98,7 @@ main (gint argc, - { "pid", 'p', 0, G_OPTION_ARG_INT, &pid, N_("Make sysprof specific to a task"), N_("PID") }, - { "command", 'c', 0, G_OPTION_ARG_STRING, &command, N_("Run a command and profile the process"), N_("COMMAND") }, - { "force", 'f', 0, G_OPTION_ARG_NONE, &force, N_("Force overwrite the capture file") }, -+ { "memory", 'm', 0, G_OPTION_ARG_NONE, &memory, N_("Record basic memory statistics") }, - { "version", 0, 0, G_OPTION_ARG_NONE, &version, N_("Print the sysprof-cli version and exit") }, - { NULL } - }; -@@ -213,6 +215,13 @@ main (gint argc, - sp_profiler_add_source (profiler, source); - g_object_unref (source); - -+ if (memory) -+ { -+ source = sp_memory_source_new (); -+ sp_profiler_add_source (profiler, source); -+ g_object_unref (source); -+ } -+ - if (pid != -1) - { - sp_profiler_set_whole_system (profiler, FALSE); --- -2.19.1 - diff --git a/sources b/sources index 283ecc5..74ec6d6 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (sysprof-3.31.1.tar.xz) = 4aa1d8a679db9fee73e838b7d1fd3661e25bf352b2fcff37a233f623c5e2376598a73bab56f13e626d5d0db205a40fbd1c9575123afe7d38d8d2425b5d2577be +SHA512 (sysprof-3.31.90.tar.xz) = 1f3aac21d65636fe38c9ca19625db21d7b22f9817d3dfcf5df667cad78fc9cece8d1d888bb8bb251b884c7fd64612ab29c902f0a803de4810aed314142b7040f diff --git a/sysprof.spec b/sysprof.spec index 96381b5..53dc7af 100644 --- a/sysprof.spec +++ b/sysprof.spec @@ -1,13 +1,11 @@ Name: sysprof -Version: 3.31.1 -Release: 3%{?dist} +Version: 3.31.90 +Release: 1%{?dist} Summary: A system-wide Linux profiler License: GPLv3+ URL: http://www.sysprof.com Source0: https://download.gnome.org/sources/sysprof/3.31/sysprof-%{version}.tar.xz -# Backported from upstream -Patch0: 0001-memory-add-memory-source-for-basic-mem-stats.patch BuildRequires: meson BuildRequires: gcc @@ -109,6 +107,9 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/*.desktop %changelog +* Thu Feb 07 2019 Kalev Lember - 3.31.90-1 +- Update to 3.31.90 + * Sun Feb 03 2019 Fedora Release Engineering - 3.31.1-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild