master
c 146 lines 3.7 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "../libnetdata.h"
4
5 size_t os_get_system_cpus_cached(bool cache) {
6 static size_t processors = 0;
7
8 if(likely(cache && processors > 0))
9 return processors;
10
11 SPINLOCK spinlock = SPINLOCK_INITIALIZER;
12 spinlock_lock(&spinlock);
13
14 long p = 0;
15
16 #if defined(_SC_NPROCESSORS_ONLN)
17 // currently online processors
18 p = sysconf(_SC_NPROCESSORS_ONLN);
19 if(p > 1) goto done; // if it is 1, we will try harder below
20 #endif
21
22 #if defined(_SC_NPROCESSORS_CONF)
23 // all configured processors (online and offline)
24 p = sysconf(_SC_NPROCESSORS_CONF);
25 if(p > 1) goto done; // if it is 1, we will try harder below
26 #endif
27
28 #if defined(OS_FREEBSD) || defined(OS_MACOS)
29 #if defined(OS_MACOS)
30 #define HW_CPU_NAME "hw.logicalcpu"
31 #else
32 #define HW_CPU_NAME "kern.smp.cpus"
33 #endif
34
35 if (unlikely(GETSYSCTL_BY_NAME(HW_CPU_NAME, p) || p < 1))
36 goto error;
37
38 #elif defined(OS_LINUX)
39 // we will count the number of cpus in /proc/stat
40
41 char filename[FILENAME_MAX + 1];
42 snprintfz(filename, FILENAME_MAX, "%s/proc/stat",
43 (netdata_configured_host_prefix) ? netdata_configured_host_prefix : "");
44
45 procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
46 if(!ff || !(ff = procfile_readall(ff))) goto error;
47
48 p = 0;
49 unsigned int i;
50 for(i = 0; i < procfile_lines(ff); i++) {
51 if(!procfile_linewords(ff, i)) continue;
52
53 const char *starting = procfile_lineword(ff, i, 0);
54 if(strncmp(starting, "cpu", 3) == 0 && isdigit((uint8_t)starting[3]))
55 p++;
56 }
57 procfile_close(ff);
58 if(p < 1) goto error;
59
60 #elif defined(OS_WINDOWS)
61
62 SYSTEM_INFO sysInfo;
63 GetSystemInfo(&sysInfo);
64 p = sysInfo.dwNumberOfProcessors;
65 if(p < 1) goto error;
66
67 #else
68
69 p = 1;
70
71 #endif
72
73 done:
74 processors = (size_t)p;
75 spinlock_unlock(&spinlock);
76 return processors;
77
78 error:
79 spinlock_unlock(&spinlock);
80 processors = 1;
81 netdata_log_error("Cannot detect number of CPU cores. Assuming the system has %zu processors.", processors);
82 return processors;
83 }
84
85 // --------------------------------------------------------------------------------------------------------------------
86 // cpuset cpus
87
88 static inline unsigned long cpuset_str2ul(char **s) {
89 unsigned long n = 0;
90 char c;
91 for(c = **s; c >= '0' && c <= '9' ; c = *(++*s)) {
92 n *= 10;
93 n += c - '0';
94 }
95 return n;
96 }
97
98 #if defined(OS_LINUX)
99 size_t os_read_cpuset_cpus(const char *filename, size_t system_cpus) {
100 static char *buf = NULL;
101 static size_t buf_size = 0;
102
103 if(unlikely(!system_cpus))
104 system_cpus = os_get_system_cpus_uncached();
105
106 size_t required_buf_size = 100U + 6 * system_cpus + 1; // taken from kernel/cgroup/cpuset.c
107 if(unlikely(buf_size < required_buf_size)) {
108 buf_size = required_buf_size;
109 buf = reallocz(buf, buf_size);
110 }
111
112 int ret = read_txt_file(filename, buf, buf_size);
113
114 if(!ret) {
115 char *s = buf;
116 unsigned long ncpus = 0;
117
118 // parse the cpuset string and calculate the number of cpus the cgroup is allowed to use
119 while (*s) {
120 if (isspace((uint8_t)*s)) {
121 s++;
122 continue;
123 }
124 unsigned long n = cpuset_str2ul(&s);
125 ncpus++;
126 if(*s == ',') {
127 s++;
128 continue;
129 }
130 if(*s == '-') {
131 s++;
132 unsigned long m = cpuset_str2ul(&s);
133 ncpus += m - n; // calculate the number of cpus in the region
134 }
135 s++;
136 }
137
138 if(!ncpus)
139 return 0;
140
141 return ncpus;
142 }
143
144 return 0;
145 }
146 #endif