/src/pango/subprojects/glib/gio/gmemorymonitorbase.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* GIO - GLib Input, Output and Streaming Library |
2 | | * |
3 | | * Copyright 2025 Red Hat, Inc. |
4 | | * |
5 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
6 | | * |
7 | | * This library is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * This library is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General |
18 | | * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #include "config.h" |
22 | | |
23 | | #include "gcancellable.h" |
24 | | #include "ginitable.h" |
25 | | #include "gioerror.h" |
26 | | #include "giomodule-priv.h" |
27 | | #include "glib/gstdio.h" |
28 | | #include "glibintl.h" |
29 | | #include "gmemorymonitor.h" |
30 | | #include "gmemorymonitorbase.h" |
31 | | |
32 | | #ifdef HAVE_SYSINFO |
33 | | #include <sys/sysinfo.h> |
34 | | #endif |
35 | | |
36 | | /** |
37 | | * GMemoryMonitorBase: |
38 | | * |
39 | | * An abstract base class for implementations of [iface@Gio.MemoryMonitor] which |
40 | | * provides several defined warning levels (`GLowMemoryLevel`) and tracks how |
41 | | * often they are notified to the user via [signal@Gio.MemoryMonitor::low-memory-warning] |
42 | | * to limit the number of signal emissions to one every 15 seconds for each level. |
43 | | * [method@Gio.MemoryMonitorBase.send_event_to_user] is provided for this purpose. |
44 | | */ |
45 | | |
46 | | /* The interval between sending a signal in second */ |
47 | 0 | #define RECOVERY_INTERVAL_SEC 15 |
48 | | |
49 | | #define G_MEMORY_MONITOR_BASE_GET_INITABLE_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), G_TYPE_INITABLE, GInitable)) |
50 | | |
51 | | static void g_memory_monitor_base_iface_init (GMemoryMonitorInterface *iface); |
52 | | static void g_memory_monitor_base_initable_iface_init (GInitableIface *iface); |
53 | | |
54 | | typedef struct |
55 | | { |
56 | | GObject parent_instance; |
57 | | |
58 | | guint64 last_trigger_us[G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_COUNT]; |
59 | | } GMemoryMonitorBasePrivate; |
60 | | |
61 | | |
62 | | G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GMemoryMonitorBase, g_memory_monitor_base, G_TYPE_OBJECT, |
63 | | G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, |
64 | | g_memory_monitor_base_initable_iface_init) |
65 | | G_IMPLEMENT_INTERFACE (G_TYPE_MEMORY_MONITOR, |
66 | | g_memory_monitor_base_iface_init) |
67 | | G_ADD_PRIVATE (GMemoryMonitorBase)) |
68 | | |
69 | | gdouble |
70 | | g_memory_monitor_base_query_mem_ratio (void) |
71 | 0 | { |
72 | 0 | #ifdef HAVE_SYSINFO |
73 | 0 | struct sysinfo info; |
74 | |
|
75 | 0 | if (sysinfo (&info)) |
76 | 0 | return -1.0; |
77 | | |
78 | 0 | if (info.totalram == 0) |
79 | 0 | return -1.0; |
80 | | |
81 | 0 | return (gdouble) ((gdouble) info.freeram / (gdouble) info.totalram); |
82 | | #else |
83 | | return -1.0; |
84 | | #endif |
85 | 0 | } |
86 | | |
87 | | GMemoryMonitorWarningLevel |
88 | | g_memory_monitor_base_level_enum_to_byte (GMemoryMonitorLowMemoryLevel level) |
89 | 0 | { |
90 | 0 | const GMemoryMonitorWarningLevel level_bytes[G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_COUNT] = { |
91 | 0 | [G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_LOW] = 50, |
92 | 0 | [G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_MEDIUM] = 100, |
93 | 0 | [G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_CRITICAL] = 255 |
94 | 0 | }; |
95 | |
|
96 | 0 | if ((int) level < G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_INVALID || |
97 | 0 | (int) level >= G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_COUNT) |
98 | 0 | g_assert_not_reached (); |
99 | | |
100 | 0 | if (level == G_MEMORY_MONITOR_LOW_MEMORY_LEVEL_INVALID) |
101 | 0 | return 0; |
102 | | |
103 | 0 | return level_bytes[level]; |
104 | 0 | } |
105 | | |
106 | | void |
107 | | g_memory_monitor_base_send_event_to_user (GMemoryMonitorBase *monitor, |
108 | | GMemoryMonitorLowMemoryLevel warning_level) |
109 | 0 | { |
110 | 0 | gint64 current_time; |
111 | 0 | GMemoryMonitorBasePrivate *priv = g_memory_monitor_base_get_instance_private (monitor); |
112 | |
|
113 | 0 | current_time = g_get_monotonic_time (); |
114 | |
|
115 | 0 | if (priv->last_trigger_us[warning_level] == 0 || |
116 | 0 | (current_time - priv->last_trigger_us[warning_level]) > (RECOVERY_INTERVAL_SEC * G_USEC_PER_SEC)) |
117 | 0 | { |
118 | 0 | g_debug ("Send low memory signal with warning level %u", warning_level); |
119 | |
|
120 | 0 | g_signal_emit_by_name (monitor, "low-memory-warning", |
121 | 0 | g_memory_monitor_base_level_enum_to_byte (warning_level)); |
122 | 0 | priv->last_trigger_us[warning_level] = current_time; |
123 | 0 | } |
124 | 0 | } |
125 | | |
126 | | static gboolean |
127 | | g_memory_monitor_base_initable_init (GInitable *initable, |
128 | | GCancellable *cancellable, |
129 | | GError **error) |
130 | 0 | { |
131 | 0 | return TRUE; |
132 | 0 | } |
133 | | |
134 | | static void |
135 | | g_memory_monitor_base_init (GMemoryMonitorBase *monitor) |
136 | 0 | { |
137 | 0 | } |
138 | | |
139 | | static void |
140 | | g_memory_monitor_base_class_init (GMemoryMonitorBaseClass *klass) |
141 | 0 | { |
142 | 0 | } |
143 | | |
144 | | static void |
145 | | g_memory_monitor_base_iface_init (GMemoryMonitorInterface *monitor_iface) |
146 | 0 | { |
147 | 0 | } |
148 | | |
149 | | static void |
150 | | g_memory_monitor_base_initable_iface_init (GInitableIface *iface) |
151 | 0 | { |
152 | 0 | iface->init = g_memory_monitor_base_initable_init; |
153 | 0 | } |