~lttng/lttng-ust/lttng-ust

« back to all changes in this revision

Viewing changes to src/common/smp.c

  • Committer: Mathieu Desnoyers
  • Author(s): Michael Jeanson
  • Date: 2022-07-29 14:33:10 UTC
  • Revision ID: git-v1:fb0f6ca9385e1813311cfd917c130b40bec04970
Add more unit tests for possible_cpus_array_len

Change-Id: If0b7fb9183936f00ac90349fb32f1db57f124602
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
static int possible_cpus_array_len_cache;
29
29
 
30
30
/*
31
 
 * As a fallback to parsing the CPU mask in "/sys/devices/system/cpu/possible",
32
 
 * iterate on all the folders in "/sys/devices/system/cpu" that start with
 
31
 * Get the highest CPU id from sysfs.
 
32
 *
 
33
 * Iterate on all the folders in "/sys/devices/system/cpu" that start with
33
34
 * "cpu" followed by an integer, keep the highest CPU id encountered during
34
35
 * this iteration and add 1 to get a number of CPUs.
35
36
 *
36
 
 * Then get the value from sysconf(_SC_NPROCESSORS_CONF) as a fallback and
37
 
 * return the highest one.
38
 
 *
39
 
 * On Linux, using the value from sysconf can be unreliable since the way it
40
 
 * counts CPUs varies between C libraries and even between versions of the same
41
 
 * library. If we used it directly, getcpu() could return a value greater than
42
 
 * this sysconf, in which case the arrays indexed by processor would overflow.
43
 
 *
44
 
 * As another example, the MUSL libc implementation of the _SC_NPROCESSORS_CONF
45
 
 * sysconf does not return the number of configured CPUs in the system but
46
 
 * relies on the cpu affinity mask of the current task.
47
 
 *
48
 
 * Returns 0 or less on error.
 
37
 * Returns the highest CPU id, or -1 on error.
49
38
 */
50
 
int get_num_possible_cpus_fallback(void)
 
39
int get_max_cpuid_from_sysfs(void)
 
40
{
 
41
        return _get_max_cpuid_from_sysfs("/sys/devices/system/cpu");
 
42
}
 
43
 
 
44
int _get_max_cpuid_from_sysfs(const char *path)
51
45
{
52
46
        long max_cpuid = -1;
53
47
 
54
48
        DIR *cpudir;
55
49
        struct dirent *entry;
56
50
 
57
 
        cpudir = opendir("/sys/devices/system/cpu");
 
51
        assert(path);
 
52
 
 
53
        cpudir = opendir(path);
58
54
        if (cpudir == NULL)
59
55
                goto end;
60
56
 
85
81
                max_cpuid = -1;
86
82
 
87
83
end:
 
84
        return max_cpuid;
 
85
}
 
86
 
 
87
/*
 
88
 * As a fallback to parsing the CPU mask in "/sys/devices/system/cpu/possible",
 
89
 * iterate on all the folders in "/sys/devices/system/cpu" that start with
 
90
 * "cpu" followed by an integer, keep the highest CPU id encountered during
 
91
 * this iteration and add 1 to get a number of CPUs.
 
92
 *
 
93
 * Then get the value from sysconf(_SC_NPROCESSORS_CONF) as a fallback and
 
94
 * return the highest one.
 
95
 *
 
96
 * On Linux, using the value from sysconf can be unreliable since the way it
 
97
 * counts CPUs varies between C libraries and even between versions of the same
 
98
 * library. If we used it directly, getcpu() could return a value greater than
 
99
 * this sysconf, in which case the arrays indexed by processor would overflow.
 
100
 *
 
101
 * As another example, the MUSL libc implementation of the _SC_NPROCESSORS_CONF
 
102
 * sysconf does not return the number of configured CPUs in the system but
 
103
 * relies on the cpu affinity mask of the current task.
 
104
 *
 
105
 * Returns 0 or less on error.
 
106
 */
 
107
int get_num_possible_cpus_fallback(void)
 
108
{
88
109
        /*
89
110
         * Get the sysconf value as a last resort. Keep the highest number.
90
111
         */
91
 
        return __max(sysconf(_SC_NPROCESSORS_CONF), max_cpuid + 1);
 
112
        return __max(sysconf(_SC_NPROCESSORS_CONF), get_max_cpuid_from_sysfs() + 1);
92
113
}
93
114
 
94
115
/*
101
122
 */
102
123
int get_possible_cpu_mask_from_sysfs(char *buf, size_t max_bytes)
103
124
{
 
125
        return get_cpu_mask_from_sysfs(buf, max_bytes,
 
126
                        "/sys/devices/system/cpu/possible");
 
127
}
 
128
 
 
129
/*
 
130
 * Get a CPU mask string from sysfs.
 
131
 *
 
132
 * buf: the buffer where the mask will be read.
 
133
 * max_bytes: the maximum number of bytes to write in the buffer.
 
134
 * path: file path to read the mask from.
 
135
 *
 
136
 * Returns the number of bytes read or -1 on error.
 
137
 */
 
138
int get_cpu_mask_from_sysfs(char *buf, size_t max_bytes, const char *path)
 
139
{
104
140
        ssize_t bytes_read = 0;
105
141
        size_t total_bytes_read = 0;
106
142
        int fd = -1, ret = -1;
107
143
 
 
144
        assert(path);
 
145
 
108
146
        if (buf == NULL)
109
147
                goto end;
110
148
 
111
 
        fd = open("/sys/devices/system/cpu/possible", O_RDONLY);
 
149
        fd = open(path, O_RDONLY);
112
150
        if (fd < 0)
113
151
                goto end;
114
152