diff --git a/src/libsysprof/meson.build b/src/libsysprof/meson.build index 806b86ae..9945852b 100644 --- a/src/libsysprof/meson.build +++ b/src/libsysprof/meson.build @@ -9,6 +9,7 @@ libsysprof_public_sources = [ 'sysprof-capture-symbol-resolver.c', 'sysprof-elf-symbol-resolver.c', 'sysprof-gjs-source.c', + 'sysprof-governor-source.c', 'sysprof-hostinfo-source.c', 'sysprof-jitmap-symbol-resolver.c', 'sysprof-kernel-symbol.c', @@ -35,6 +36,7 @@ libsysprof_public_headers = [ 'sysprof-capture-symbol-resolver.h', 'sysprof-elf-symbol-resolver.h', 'sysprof-gjs-source.h', + 'sysprof-governor-source.h', 'sysprof-hostinfo-source.h', 'sysprof-jitmap-symbol-resolver.h', 'sysprof-kernel-symbol.h', diff --git a/src/libsysprof/sysprof-governor-source.c b/src/libsysprof/sysprof-governor-source.c new file mode 100644 index 00000000..ca33f2d5 --- /dev/null +++ b/src/libsysprof/sysprof-governor-source.c @@ -0,0 +1,266 @@ +/* sysprof-governor-source.c + * + * Copyright 2019 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 + */ + +#define G_LOG_DOMAIN "sysprof-governor-source" + +#include "config.h" + +#include "sysprof-governor-source.h" +#include "sysprof-helpers.h" + +struct _SysprofGovernorSource +{ + GObject parent_instance; + gchar *old_governor; + guint disable_governor : 1; +}; + +enum { + PROP_0, + PROP_DISABLE_GOVERNOR, + N_PROPS +}; + +static void source_iface_init (SysprofSourceInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (SysprofGovernorSource, sysprof_governor_source, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (SYSPROF_TYPE_SOURCE, source_iface_init)) + +static GParamSpec *properties [N_PROPS]; + +static void +sysprof_governor_source_finalize (GObject *object) +{ + SysprofGovernorSource *self = (SysprofGovernorSource *)object; + + g_clear_pointer (&self->old_governor, g_free); + + G_OBJECT_CLASS (sysprof_governor_source_parent_class)->finalize (object); +} + +static void +sysprof_governor_source_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SysprofGovernorSource *self = SYSPROF_GOVERNOR_SOURCE (object); + + switch (prop_id) + { + case PROP_DISABLE_GOVERNOR: + g_value_set_boolean (value, sysprof_governor_source_get_disable_governor (self)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +sysprof_governor_source_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SysprofGovernorSource *self = SYSPROF_GOVERNOR_SOURCE (object); + + switch (prop_id) + { + case PROP_DISABLE_GOVERNOR: + sysprof_governor_source_set_disable_governor (self, g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +sysprof_governor_source_class_init (SysprofGovernorSourceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = sysprof_governor_source_finalize; + object_class->get_property = sysprof_governor_source_get_property; + object_class->set_property = sysprof_governor_source_set_property; + + properties [PROP_DISABLE_GOVERNOR] = + g_param_spec_boolean ("disable-governor", + "Disable Governor", + "Disable Governor", + TRUE, + (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, N_PROPS, properties); +} + +static void +sysprof_governor_source_init (SysprofGovernorSource *self) +{ + self->disable_governor = TRUE; +} + +SysprofSource * +sysprof_governor_source_new (void) +{ + return g_object_new (SYSPROF_TYPE_GOVERNOR_SOURCE, NULL); +} + +gboolean +sysprof_governor_source_get_disable_governor (SysprofGovernorSource *self) +{ + g_return_val_if_fail (SYSPROF_IS_GOVERNOR_SOURCE (self), FALSE); + + return self->disable_governor; +} + +void +sysprof_governor_source_set_disable_governor (SysprofGovernorSource *self, + gboolean disable_governor) +{ + g_return_if_fail (SYSPROF_IS_GOVERNOR_SOURCE (self)); + + disable_governor = !!disable_governor; + + if (disable_governor != self->disable_governor) + { + self->disable_governor = disable_governor; + g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DISABLE_GOVERNOR]); + } +} + +static void +sysprof_governor_source_serialize (SysprofSource *source, + GKeyFile *keyfile, + const gchar *group) +{ + SysprofGovernorSource *self = (SysprofGovernorSource *)source; + + g_assert (SYSPROF_IS_GOVERNOR_SOURCE (self)); + g_assert (keyfile != NULL); + g_assert (group != NULL); + + g_key_file_set_boolean (keyfile, group, "disable-governor", self->disable_governor); +} + +static void +sysprof_governor_source_deserialize (SysprofSource *source, + GKeyFile *keyfile, + const gchar *group) +{ + SysprofGovernorSource *self = (SysprofGovernorSource *)source; + + g_assert (SYSPROF_IS_GOVERNOR_SOURCE (self)); + g_assert (keyfile != NULL); + g_assert (group != NULL); + + sysprof_governor_source_set_disable_governor (self, + g_key_file_get_boolean (keyfile, group, "disable-governor", NULL)); +} + +static void +disable_governor_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + SysprofHelpers *helpers = (SysprofHelpers *)object; + g_autoptr(SysprofGovernorSource) self = user_data; + g_autoptr(GError) error = NULL; + g_autofree gchar *old_governor = NULL; + + g_assert (SYSPROF_IS_HELPERS (helpers)); + g_assert (G_IS_ASYNC_RESULT (result)); + g_assert (SYSPROF_IS_GOVERNOR_SOURCE (self)); + + if (!sysprof_helpers_set_governor_finish (helpers, result, &old_governor, &error)) + g_warning ("Failed to change governor: %s", error->message); + else + self->old_governor = g_steal_pointer (&old_governor); + + sysprof_source_emit_ready (SYSPROF_SOURCE (self)); +} + +static void +enable_governor_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + SysprofHelpers *helpers = (SysprofHelpers *)object; + g_autoptr(SysprofGovernorSource) self = user_data; + g_autoptr(GError) error = NULL; + g_autofree gchar *old_governor = NULL; + + g_assert (SYSPROF_IS_HELPERS (helpers)); + g_assert (G_IS_ASYNC_RESULT (result)); + g_assert (SYSPROF_IS_GOVERNOR_SOURCE (self)); + + if (!sysprof_helpers_set_governor_finish (helpers, result, &old_governor, &error)) + g_warning ("Failed to change governor: %s", error->message); + + g_clear_pointer (&self->old_governor, g_free); + + sysprof_source_emit_finished (SYSPROF_SOURCE (self)); +} + +static void +sysprof_governor_source_prepare (SysprofSource *source) +{ + SysprofGovernorSource *self = (SysprofGovernorSource *)source; + SysprofHelpers *helpers = sysprof_helpers_get_default (); + + g_assert (SYSPROF_IS_GOVERNOR_SOURCE (self)); + + if (!self->disable_governor) + sysprof_source_emit_ready (source); + else + sysprof_helpers_set_governor_async (helpers, + "performance", + NULL, + disable_governor_cb, + g_object_ref (self)); +} + +static void +sysprof_governor_source_stop (SysprofSource *source) +{ + SysprofGovernorSource *self = (SysprofGovernorSource *)source; + SysprofHelpers *helpers = sysprof_helpers_get_default (); + + g_assert (SYSPROF_IS_GOVERNOR_SOURCE (self)); + + if (self->old_governor == NULL) + sysprof_source_emit_finished (source); + else + sysprof_helpers_set_governor_async (helpers, + self->old_governor, + NULL, + enable_governor_cb, + g_object_ref (self)); +} + +static void +source_iface_init (SysprofSourceInterface *iface) +{ + iface->deserialize = sysprof_governor_source_deserialize; + iface->prepare = sysprof_governor_source_prepare; + iface->serialize = sysprof_governor_source_serialize; + iface->stop = sysprof_governor_source_stop; +} diff --git a/src/libsysprof/sysprof-governor-source.h b/src/libsysprof/sysprof-governor-source.h new file mode 100644 index 00000000..77968883 --- /dev/null +++ b/src/libsysprof/sysprof-governor-source.h @@ -0,0 +1,40 @@ +/* sysprof-governor-source.h + * + * Copyright 2019 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 "sysprof-source.h" + +G_BEGIN_DECLS + +#define SYSPROF_TYPE_GOVERNOR_SOURCE (sysprof_governor_source_get_type()) + +SYSPROF_AVAILABLE_IN_ALL +G_DECLARE_FINAL_TYPE (SysprofGovernorSource, sysprof_governor_source, SYSPROF, GOVERNOR_SOURCE, GObject) + +SYSPROF_AVAILABLE_IN_ALL +SysprofSource *sysprof_governor_source_new (void); +SYSPROF_AVAILABLE_IN_ALL +gboolean sysprof_governor_source_get_disable_governor (SysprofGovernorSource *self); +SYSPROF_AVAILABLE_IN_ALL +void sysprof_governor_source_set_disable_governor (SysprofGovernorSource *self, + gboolean disable_governor); + +G_END_DECLS diff --git a/src/libsysprof/sysprof.h b/src/libsysprof/sysprof.h index 10b38b2e..1a00bc61 100644 --- a/src/libsysprof/sysprof.h +++ b/src/libsysprof/sysprof.h @@ -30,6 +30,7 @@ G_BEGIN_DECLS # include "sysprof-capture-symbol-resolver.h" # include "sysprof-elf-symbol-resolver.h" # include "sysprof-gjs-source.h" +# include "sysprof-governor-source.h" # include "sysprof-jitmap-symbol-resolver.h" # include "sysprof-kernel-symbol-resolver.h" # include "sysprof-kernel-symbol.h"