From 94e6da0fcae1be8ca68c93edd43a2b6ca45315fd Mon Sep 17 00:00:00 2001 From: Kate Hsuan Date: Fri, 21 Mar 2025 15:31:58 +0800 Subject: [PATCH] gio: gmemorymonitorbase: parent class of GMemoryMonitor backends MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This class provides the shared functions, such as sending a signal and string and value conversion. The backend classes should inherit this class to get the shared functions. It adds a configure time check for `sysinfo()`, as some systems don’t have it. --- gio/gmemorymonitorbase.c | 153 +++++++++++++++++++++++++++++++++++++++ gio/gmemorymonitorbase.h | 53 ++++++++++++++ gio/meson.build | 1 + meson.build | 1 + 4 files changed, 208 insertions(+) create mode 100644 gio/gmemorymonitorbase.c create mode 100644 gio/gmemorymonitorbase.h diff --git a/gio/gmemorymonitorbase.c b/gio/gmemorymonitorbase.c new file mode 100644 index 000000000..ce28ebe33 --- /dev/null +++ b/gio/gmemorymonitorbase.c @@ -0,0 +1,153 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright 2025 Red Hat, Inc. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * 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 Lesser General + * Public License along with this library; if not, see . + */ + +#include "config.h" + +#include "gcancellable.h" +#include "ginitable.h" +#include "gioerror.h" +#include "giomodule-priv.h" +#include "glib/gstdio.h" +#include "glibintl.h" +#include "gmemorymonitor.h" +#include "gmemorymonitorbase.h" + +#ifdef HAVE_SYSINFO +#include +#endif + +/** + * GMemoryMonitorBase: + * + * An abstract base class for implementations of [iface@Gio.MemoryMonitor] which + * provides several defined warning levels (`GLowMemoryLevel`) and tracks how + * often they are notified to the user via [signal@Gio.MemoryMonitor::low-memory-warning] + * to limit the number of signal emissions to one every 15 seconds for each level. + * [method@Gio.MemoryMonitorBase.send_event_to_user] is provided for this purpose. + */ + +/* The interval between sending a signal in second */ +#define RECOVERY_INTERVAL_SEC 15 + +#define G_MEMORY_MONITOR_BASE_GET_INITABLE_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), G_TYPE_INITABLE, GInitable)) + +static void g_memory_monitor_base_iface_init (GMemoryMonitorInterface *iface); +static void g_memory_monitor_base_initable_iface_init (GInitableIface *iface); + +typedef struct +{ + GObject parent_instance; + + guint64 last_trigger_us[G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_COUNT]; +} GMemoryMonitorBasePrivate; + + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GMemoryMonitorBase, g_memory_monitor_base, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + g_memory_monitor_base_initable_iface_init) + G_IMPLEMENT_INTERFACE (G_TYPE_MEMORY_MONITOR, + g_memory_monitor_base_iface_init) + G_ADD_PRIVATE (GMemoryMonitorBase)) + +gdouble +g_memory_monitor_base_query_mem_ratio (void) +{ +#ifdef HAVE_SYSINFO + struct sysinfo info; + + if (sysinfo (&info)) + return -1.0; + + if (info.totalram == 0) + return -1.0; + + return (gdouble) ((gdouble) info.freeram / (gdouble) info.totalram); +#else + return -1.0; +#endif +} + +GMemoryMonitorWarningLevel +g_memory_monitor_base_level_enum_to_byte (GMemoryMonitorLowMemoryLevel level) +{ + const GMemoryMonitorWarningLevel level_bytes[G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_COUNT] = { + [G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_LOW] = 50, + [G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_MEDIUM] = 100, + [G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_CRITICAL] = 255 + }; + + if ((int) level < G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_INVALID || + (int) level >= G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_COUNT) + g_assert_not_reached (); + + if (level == G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_INVALID) + return 0; + + return level_bytes[level]; +} + +void +g_memory_monitor_base_send_event_to_user (GMemoryMonitorBase *monitor, + GMemoryMonitorLowMemoryLevel warning_level) +{ + gint64 current_time; + GMemoryMonitorBasePrivate *priv = g_memory_monitor_base_get_instance_private (monitor); + + current_time = g_get_monotonic_time (); + + if (priv->last_trigger_us[warning_level] == 0 || + (current_time - priv->last_trigger_us[warning_level]) > (RECOVERY_INTERVAL_SEC * G_USEC_PER_SEC)) + { + g_debug ("Send low memory signal with warning level %u", warning_level); + + g_signal_emit_by_name (monitor, "low-memory-warning", + g_memory_monitor_base_level_enum_to_byte (warning_level)); + priv->last_trigger_us[warning_level] = current_time; + } +} + +static gboolean +g_memory_monitor_base_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + return TRUE; +} + +static void +g_memory_monitor_base_init (GMemoryMonitorBase *monitor) +{ +} + +static void +g_memory_monitor_base_class_init (GMemoryMonitorBaseClass *klass) +{ +} + +static void +g_memory_monitor_base_iface_init (GMemoryMonitorInterface *monitor_iface) +{ +} + +static void +g_memory_monitor_base_initable_iface_init (GInitableIface *iface) +{ + iface->init = g_memory_monitor_base_initable_init; +} diff --git a/gio/gmemorymonitorbase.h b/gio/gmemorymonitorbase.h new file mode 100644 index 000000000..847d55515 --- /dev/null +++ b/gio/gmemorymonitorbase.h @@ -0,0 +1,53 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright 2025 Red Hat, Inc. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * 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 Lesser General + * Public License along with this library; if not, see . + */ + +#ifndef __G_MEMORY_MONITOR_BASE_H__ +#define __G_MEMORY_MONITOR_BASE_H__ + +#include + +G_BEGIN_DECLS + +#define G_TYPE_MEMORY_MONITOR_BASE (g_memory_monitor_base_get_type ()) + +G_DECLARE_DERIVABLE_TYPE (GMemoryMonitorBase, g_memory_monitor_base, G, MEMORY_MONITOR_BASE, GObject) + +typedef enum +{ + G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_INVALID = -1, + G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_LOW = 0, + G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_MEDIUM, + G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_CRITICAL, + G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_COUNT +} GMemoryMonitorLowMemoryLevel; + +struct _GMemoryMonitorBaseClass +{ + GObjectClass parent_class; +}; + +void g_memory_monitor_base_send_event_to_user (GMemoryMonitorBase *monitor, + GMemoryMonitorLowMemoryLevel warning_level); +GMemoryMonitorWarningLevel g_memory_monitor_base_level_enum_to_byte (GMemoryMonitorLowMemoryLevel level); +gdouble g_memory_monitor_base_query_mem_ratio (void); + +G_END_DECLS + +#endif /* __G_MEMORY_MONITOR_BASE_H__ */ diff --git a/gio/meson.build b/gio/meson.build index 854b95afa..2d0c2ee40 100644 --- a/gio/meson.build +++ b/gio/meson.build @@ -528,6 +528,7 @@ gio_base_sources = files( 'gmarshal-internal.c', 'gmount.c', 'gmemorymonitor.c', + 'gmemorymonitorbase.c', 'gmemorymonitordbus.c', 'gmemoryinputstream.c', 'gmemoryoutputstream.c', diff --git a/meson.build b/meson.build index df87f0eed..b569da1d5 100644 --- a/meson.build +++ b/meson.build @@ -759,6 +759,7 @@ functions = [ 'strtoll_l', 'strtoull_l', 'symlink', + 'sysinfo', 'timegm', 'unsetenv', 'uselocale',