Coverage Report

Created: 2025-07-23 08:13

/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
}