• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 14554080340

19 Apr 2025 11:46AM UTC coverage: 72.101% (-0.03%) from 72.13%
14554080340

push

github

web-flow
Add two new paragraphs to coding style about header files (#37188)

296880 of 411754 relevant lines covered (72.1%)

687547.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.17
/src/basic/limits-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <unistd.h>
4

5
#include "alloc-util.h"
6
#include "cgroup-util.h"
7
#include "limits-util.h"
8
#include "log.h"
9
#include "memory-util.h"
10
#include "parse-util.h"
11
#include "process-util.h"
12
#include "procfs-util.h"
13
#include "string-util.h"
14

15
uint64_t physical_memory(void) {
4,287✔
16
        _cleanup_free_ char *root = NULL, *value = NULL;
4,287✔
17
        uint64_t mem, lim;
4,287✔
18
        size_t ps;
4,287✔
19
        long sc;
4,287✔
20
        int r;
4,287✔
21

22
        /* We return this as uint64_t in case we are running as 32-bit process on a 64-bit kernel with huge amounts of
23
         * memory.
24
         *
25
         * In order to support containers nicely that have a configured memory limit we'll take the minimum of the
26
         * physically reported amount of memory and the limit configured for the root cgroup, if there is any. */
27

28
        sc = sysconf(_SC_PHYS_PAGES);
4,287✔
29
        assert(sc > 0);
4,287✔
30

31
        ps = page_size();
4,287✔
32
        mem = (uint64_t) sc * (uint64_t) ps;
4,287✔
33

34
        r = cg_get_root_path(&root);
4,287✔
35
        if (r < 0) {
4,287✔
36
                log_debug_errno(r, "Failed to determine root cgroup, ignoring cgroup memory limit: %m");
×
37
                return mem;
×
38
        }
39

40
        r = cg_all_unified();
4,287✔
41
        if (r < 0) {
4,287✔
42
                log_debug_errno(r, "Failed to determine root unified mode, ignoring cgroup memory limit: %m");
×
43
                return mem;
×
44
        }
45
        if (r > 0) {
4,287✔
46
                r = cg_get_attribute("memory", root, "memory.max", &value);
4,287✔
47
                if (r == -ENOENT) /* Field does not exist on the system's top-level cgroup, hence don't
4,287✔
48
                                   * complain. (Note that it might exist on our own root though, if we live
49
                                   * in a cgroup namespace, hence check anyway instead of not even
50
                                   * trying.) */
51
                        return mem;
52
                if (r < 0) {
3,639✔
53
                        log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m");
×
54
                        return mem;
×
55
                }
56

57
                if (streq(value, "max"))
3,639✔
58
                        return mem;
59
        } else {
60
                r = cg_get_attribute("memory", root, "memory.limit_in_bytes", &value);
×
61
                if (r < 0) {
×
62
                        log_debug_errno(r, "Failed to read memory.limit_in_bytes cgroup attribute, ignoring cgroup memory limit: %m");
×
63
                        return mem;
×
64
                }
65
        }
66

67
        r = safe_atou64(value, &lim);
×
68
        if (r < 0) {
×
69
                log_debug_errno(r, "Failed to parse cgroup memory limit '%s', ignoring: %m", value);
×
70
                return mem;
×
71
        }
72
        if (lim == UINT64_MAX)
×
73
                return mem;
74

75
        /* Make sure the limit is a multiple of our own page size */
76
        lim /= ps;
×
77
        lim *= ps;
×
78

79
        return MIN(mem, lim);
×
80
}
81

82
uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
355✔
83
        uint64_t p, m, ps;
355✔
84

85
        /* Shortcut two special cases */
86
        if (v == 0)
355✔
87
                return 0;
88
        if (v == max)
351✔
89
                return physical_memory();
4✔
90

91
        assert(max > 0);
347✔
92

93
        /* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success
94
         * the result is a multiple of the page size (rounds down). */
95

96
        ps = page_size();
347✔
97
        assert(ps > 0);
347✔
98

99
        p = physical_memory() / ps;
347✔
100
        assert(p > 0);
347✔
101

102
        if (v > UINT64_MAX / p)
347✔
103
                return UINT64_MAX;
104

105
        m = p * v;
346✔
106
        m /= max;
346✔
107

108
        if (m > UINT64_MAX / ps)
346✔
109
                return UINT64_MAX;
110

111
        return m * ps;
346✔
112
}
113

114
uint64_t system_tasks_max(void) {
6,701✔
115
        uint64_t a = TASKS_MAX, b = TASKS_MAX, c = TASKS_MAX;
6,701✔
116
        _cleanup_free_ char *root = NULL;
6,701✔
117
        int r;
6,701✔
118

119
        /* Determine the maximum number of tasks that may run on this system. We check three sources to
120
         * determine this limit:
121
         *
122
         * a) kernel.threads-max sysctl: the maximum number of tasks (threads) the kernel allows.
123
         *
124
         *    This puts a direct limit on the number of concurrent tasks.
125
         *
126
         * b) kernel.pid_max sysctl: the maximum PID value.
127
         *
128
         *    This limits the numeric range PIDs can take, and thus indirectly also limits the number of
129
         *    concurrent threads. It's primarily a compatibility concept: some crappy old code used a signed
130
         *    16-bit type for PIDs, hence the kernel provides a way to ensure the PIDs never go beyond
131
         *    INT16_MAX by default.
132
         *
133
         *    Also note the weird definition: PIDs assigned will be kept below this value, which means
134
         *    the number of tasks that can be created is one lower, as PID 0 is not a valid process ID.
135
         *
136
         * c) pids.max on the root cgroup: the kernel's configured maximum number of tasks.
137
         *
138
         * and then pick the smallest of the three.
139
         *
140
         * By default pid_max is set to much lower values than threads-max, hence the limit people come into
141
         * contact with first, as it's the lowest boundary they need to bump when they want higher number of
142
         * processes.
143
         */
144

145
        r = procfs_get_threads_max(&a);
6,701✔
146
        if (r < 0)
6,701✔
147
                log_debug_errno(r, "Failed to read kernel.threads-max, ignoring: %m");
×
148

149
        r = procfs_get_pid_max(&b);
6,701✔
150
        if (r < 0)
6,701✔
151
                log_debug_errno(r, "Failed to read kernel.pid_max, ignoring: %m");
×
152
        else if (b > 0)
6,701✔
153
                /* Subtract one from pid_max, since PID 0 is not a valid PID */
154
                b--;
6,701✔
155

156
        r = cg_get_root_path(&root);
6,701✔
157
        if (r < 0)
6,701✔
158
                log_debug_errno(r, "Failed to determine cgroup root path, ignoring: %m");
×
159
        else {
160
                /* We'll have the "pids.max" attribute on the our root cgroup only if we are in a
161
                 * CLONE_NEWCGROUP namespace. On the top-level namespace this attribute is missing, hence
162
                 * suppress any message about that */
163
                r = cg_get_attribute_as_uint64("pids", root, "pids.max", &c);
6,701✔
164
                if (r < 0 && r != -ENODATA)
6,701✔
165
                        log_debug_errno(r, "Failed to read pids.max attribute of root cgroup, ignoring: %m");
×
166
        }
167

168
        return MIN3(a, b, c);
6,701✔
169
}
170

171
uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
5,422✔
172
        uint64_t t, m;
5,422✔
173

174
        /* Shortcut two special cases */
175
        if (v == 0)
5,422✔
176
                return 0;
177
        if (v == max)
5,418✔
178
                return system_tasks_max();
4✔
179

180
        assert(max > 0);
5,414✔
181

182
        /* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
183
         * relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
184

185
        t = system_tasks_max();
5,414✔
186
        assert(t > 0);
5,414✔
187

188
        if (v > UINT64_MAX / t) /* overflow? */
5,414✔
189
                return UINT64_MAX;
190

191
        m = t * v;
5,413✔
192
        return m / max;
5,413✔
193
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc