2 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
3 "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
4 <!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
6 <refentry id="sd_event_add_memory_pressure" xmlns:xi="http://www.w3.org/2001/XInclude">
9 <title>sd_event_add_memory_pressure</title>
10 <productname>systemd</productname>
14 <refentrytitle>sd_event_add_memory_pressure</refentrytitle>
15 <manvolnum>3</manvolnum>
19 <refname>sd_event_add_memory_pressure</refname>
20 <refname>sd_event_source_set_memory_pressure_type</refname>
21 <refname>sd_event_source_set_memory_pressure_period</refname>
22 <refname>sd_event_trim_memory</refname>
24 <refpurpose>Add and configure an event source run as result of memory pressure</refpurpose>
29 <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
31 <funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
34 <funcdef>int <function>sd_event_add_memory_pressure</function></funcdef>
35 <paramdef>sd_event *<parameter>event</parameter></paramdef>
36 <paramdef>sd_event_source **<parameter>ret_source</parameter></paramdef>
37 <paramdef>sd_event_handler_t <parameter>handler</parameter></paramdef>
38 <paramdef>void *<parameter>userdata</parameter></paramdef>
42 <funcdef>int <function>sd_event_source_set_memory_pressure_type</function></funcdef>
43 <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
44 <paramdef>const char *<parameter>type</parameter></paramdef>
48 <funcdef>int <function>sd_event_source_set_memory_pressure_period</function></funcdef>
49 <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
50 <paramdef>uint64_t <parameter>threshold_usec</parameter></paramdef>
51 <paramdef>uint64_t <parameter>window_usec</parameter></paramdef>
55 <funcdef>int <function>sd_event_trim_memory</function></funcdef>
56 <paramdef>void</paramdef>
62 <title>Description</title>
64 <para><function>sd_event_add_memory_pressure()</function> adds a new event source that is triggered
65 whenever memory pressure is seen. This functionality is built around the Linux kernel's <ulink
66 url="https://docs.kernel.org/accounting/psi.html">Pressure Stall Information (PSI)</ulink> logic.</para>
68 <para>Expects an event loop object as first parameter, and returns the allocated event source object in
69 the second parameter, on success. The <parameter>handler</parameter> parameter is a function to call when
70 memory pressure is seen, or <constant>NULL</constant>. The handler function will be passed the
71 <parameter>userdata</parameter> pointer, which may be chosen freely by the caller. The handler may return
72 negative to signal an error (see below), other return values are ignored. If
73 <parameter>handler</parameter> is <constant>NULL</constant>, a default handler that compacts allocation
74 caches maintained by <filename>libsystemd</filename> as well as glibc (via <citerefentry
75 project='man-pages'><refentrytitle>malloc_trim</refentrytitle><manvolnum>3</manvolnum></citerefentry>)
78 <para>To destroy an event source object use
79 <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
80 but note that the event source is only removed from the event loop when all references to the event
81 source are dropped. To make sure an event source does not fire anymore, even if it is still referenced,
82 disable the event source using
83 <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
84 with <constant>SD_EVENT_OFF</constant>.</para>
86 <para>If the second parameter of <function>sd_event_add_memory_pressure()</function> is
87 <constant>NULL</constant> no reference to the event source object is returned. In this case the event
88 source is considered "floating", and will be destroyed implicitly when the event loop itself is
91 <para>The event source will fire according to the following logic:</para>
94 <listitem><para>If the
95 <varname>$MEMORY_PRESSURE_WATCH</varname>/<varname>$MEMORY_PRESSURE_WRITE</varname> environment
96 variables are set at the time the event source is established, it will watch the file, FIFO or AF_UNIX
97 socket specified via <varname>$MEMORY_PRESSURE_WATCH</varname> (which must contain an absolute path
98 name) for <constant>POLLPRI</constant> (in case it is a regular file) or <constant>POLLIN</constant>
99 events (otherwise). After opening the inode, it will write the (decoded) Base64 data provided via
100 <varname>$MEMORY_PRESSURE_WRITE</varname> into it before it starts polling on it (the variable may be
101 unset in which case this is skipped). Typically, if used, <varname>$MEMORY_PRESSURE_WATCH</varname>
102 will contain a path such as <filename>/proc/pressure/memory</filename> or a path to a specific
103 <filename>memory.pressure</filename> file in the control group file system
104 (cgroupfs).</para></listitem>
106 <listitem><para>If these environment variables are not set, the local PSI interface file
107 <filename>memory.pressure</filename> of the control group the invoking process is running in is
108 used.</para></listitem>
110 <listitem><para>If that file does not exist, the system-wide PSI interface file
111 <filename>/proc/pressure/memory</filename> is watched instead.</para></listitem>
114 <para>Or in other words: preferably any explicit configuration passed in by an invoking service manager
115 (or similar) is used as notification source, before falling back to local notifications of the service,
116 and finally to global notifications of the system.</para>
118 <para>Well-behaving services and applications are recommended to react to memory pressure events by
119 executing one or more of the following operations, in order to ensure optimal behaviour even on loaded
120 and resource-constrained systems:</para>
123 <listitem><para>Release allocation caches such as <function>malloc_trim()</function> or similar, both
124 implemented in the libraries consumed by the program and in private allocation caches of the program
125 itself.</para></listitem>
127 <listitem><para>Release any other form of in-memory caches that can easily be recovered if
128 needed (e.g. browser caches).</para></listitem>
130 <listitem><para>Terminate idle worker threads or processes, or similar.</para></listitem>
132 <listitem><para>Even exit entirely from the program if it is idle and can be automatically started when
133 needed (for example via socket or bus activation).</para></listitem>
136 <para>Any of the suggested operations should help easing memory pressure situations and allowing the
137 system to make progress by reclaiming the memory for other purposes.</para>
139 <para>This event source typically fires on memory pressure stalls, i.e. when operational latency above a
140 configured threshold already has been seen. This should be taken into consideration when discussing
141 whether later latency to re-aquire any released resources is acceptable: it's usually more important to
142 think of the latencies that already happened than those coming up in future.</para>
144 <para>The <function>sd_event_source_set_memory_pressure_type()</function> and
145 <function>sd_event_source_set_memory_pressure_period()</function> functions can be used to fine-tune the
146 PSI parameters for pressure notifications. The former takes either <literal>some</literal>,
147 <literal>full</literal> as second parameter, the latter takes threshold and period times in microseconds
148 as parameters. For details about these three parameters see the PSI documentation. Note that these two
149 calls must be invoked immediately after allocating the event source, as they must be configured before
150 polling begins. Also note that these calls will fail if memory pressure parameterization has been passed
151 in via the <varname>$MEMORY_PRESSURE_WATCH</varname>/<varname>$MEMORY_PRESSURE_WRITE</varname>
152 environment variables (or in other words: configuration supplied by a service manager wins over internal
155 <para>The <function>sd_event_trim_memory()</function> function releases various internal allocation
156 caches maintained by <filename>libsystemd</filename> and then invokes glibc's <citerefentry
157 project='man-pages'><refentrytitle>malloc_trim</refentrytitle><manvolnum>3</manvolnum></citerefentry>. This
158 makes the operation executed when the handler function parameter of
159 <function>sd_event_add_memory_pressure</function> is passed as <constant>NULL</constant> directly
160 accessible for invocation at any time (see above). This function will log a structured log message at
161 <constant>LOG_DEBUG</constant> level (with message ID f9b0be465ad540d0850ad32172d57c21) about the memory
162 pressure operation.</para>
164 <para>For further details see <ulink url="https://systemd.io/MEMORY_PRESSURE">Memory Pressure Handling in
165 systemd</ulink>.</para>
169 <title>Return Value</title>
171 <para>On success, these functions return 0 or a positive
172 integer. On failure, they return a negative errno-style error
176 <title>Errors</title>
178 <para>Returned errors may indicate the following problems:</para>
182 <term><constant>-ENOMEM</constant></term>
184 <listitem><para>Not enough memory to allocate an object.</para>
186 <xi:include href="version-info.xml" xpointer="v254"/></listitem>
190 <term><constant>-EINVAL</constant></term>
192 <listitem><para>An invalid argument has been passed.</para>
194 <xi:include href="version-info.xml" xpointer="v254"/></listitem>
198 <term><constant>-EHOSTDOWN</constant></term>
200 <listitem><para>The <varname>$MEMORY_PRESSURE_WATCH</varname> variable has been set to the literal
201 string <filename>/dev/null</filename>, in order to explicitly disable memory pressure
204 <xi:include href="version-info.xml" xpointer="v254"/></listitem>
208 <term><constant>-EBADMSG</constant></term>
210 <listitem><para>The <varname>$MEMORY_PRESSURE_WATCH</varname> variable has been set to an invalid
211 string, for example a relative rather than an absolute path.</para>
213 <xi:include href="version-info.xml" xpointer="v254"/></listitem>
217 <term><constant>-ENOTTY</constant></term>
219 <listitem><para>The <varname>$MEMORY_PRESSURE_WATCH</varname> variable points to a regular file
220 outside of the procfs or cgroupfs file systems.</para>
222 <xi:include href="version-info.xml" xpointer="v254"/></listitem>
226 <term><constant>-EOPNOTSUPP</constant></term>
228 <listitem><para>No configuration via <varname>$MEMORY_PRESSURE_WATCH</varname> has been specified
229 and the local kernel does not support the PSI interface.</para>
231 <xi:include href="version-info.xml" xpointer="v254"/></listitem>
235 <term><constant>-EBUSY</constant></term>
237 <listitem><para>This is returned by <function>sd_event_source_set_memory_pressure_type()</function>
238 and <function>sd_event_source_set_memory_pressure_period()</function> if invoked on event sources
239 at a time later than immediately after allocating them.</para>
241 <xi:include href="version-info.xml" xpointer="v254"/></listitem>
245 <term><constant>-ESTALE</constant></term>
247 <listitem><para>The event loop is already terminated.</para>
249 <xi:include href="version-info.xml" xpointer="v254"/></listitem>
253 <term><constant>-ECHILD</constant></term>
255 <listitem><para>The event loop has been created in a different process, library or module instance.</para>
257 <xi:include href="version-info.xml" xpointer="v254"/></listitem>
261 <term><constant>-EDOM</constant></term>
263 <listitem><para>The passed event source is not a signal event source.</para>
265 <xi:include href="version-info.xml" xpointer="v254"/></listitem>
272 <xi:include href="libsystemd-pkgconfig.xml" />
275 <title>History</title>
276 <para><function>sd_event_add_memory_pressure()</function>,
277 <function>sd_event_source_set_memory_pressure_type()</function>,
278 <function>sd_event_source_set_memory_pressure_period()</function>, and
279 <function>sd_event_trim_memory()</function> were added in version 254.</para>
283 <title>See Also</title>
286 <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
287 <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
288 <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
289 <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
290 <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
291 <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
292 <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
293 <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
294 <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
295 <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
296 <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
297 <citerefentry><refentrytitle>sd_event_source_set_floating</refentrytitle><manvolnum>3</manvolnum></citerefentry>