/src/nspr/pr/src/misc/prsystem.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
3 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | | |
6 | | #include "primpl.h" |
7 | | #include "prsystem.h" |
8 | | #include "prprf.h" |
9 | | #include "prlong.h" |
10 | | |
11 | | /* BSD-derived systems use sysctl() to get the number of processors */ |
12 | | #if defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) || \ |
13 | | defined(DRAGONFLY) || defined(DARWIN) |
14 | | # define _PR_HAVE_SYSCTL |
15 | | # include <sys/param.h> |
16 | | # include <sys/sysctl.h> |
17 | | #endif |
18 | | |
19 | | #if defined(DARWIN) |
20 | | # include <mach/mach_init.h> |
21 | | # include <mach/mach_host.h> |
22 | | # include <mach/mach_port.h> |
23 | | #endif |
24 | | |
25 | | #if defined(HPUX) |
26 | | # include <sys/mpctl.h> |
27 | | # include <sys/pstat.h> |
28 | | #endif |
29 | | |
30 | | #if defined(XP_UNIX) |
31 | | # include <unistd.h> |
32 | | # include <sys/utsname.h> |
33 | | #endif |
34 | | |
35 | | #if defined(LINUX) |
36 | | # include <string.h> |
37 | | # include <ctype.h> |
38 | 0 | # define MAX_LINE 512 |
39 | | #endif |
40 | | |
41 | | #if defined(AIX) |
42 | | # include <cf.h> |
43 | | # include <sys/cfgodm.h> |
44 | | #endif |
45 | | |
46 | 0 | PR_IMPLEMENT(char) PR_GetDirectorySeparator(void) { |
47 | 0 | return PR_DIRECTORY_SEPARATOR; |
48 | 0 | } /* PR_GetDirectorySeparator */ |
49 | | |
50 | | /* |
51 | | ** OBSOLETE -- the function name is misspelled. |
52 | | */ |
53 | 0 | PR_IMPLEMENT(char) PR_GetDirectorySepartor(void) { |
54 | 0 | #if defined(DEBUG) |
55 | 0 | static PRBool warn = PR_TRUE; |
56 | 0 | if (warn) { |
57 | 0 | warn = |
58 | 0 | _PR_Obsolete("PR_GetDirectorySepartor()", "PR_GetDirectorySeparator()"); |
59 | 0 | } |
60 | 0 | #endif |
61 | 0 | return PR_GetDirectorySeparator(); |
62 | 0 | } /* PR_GetDirectorySepartor */ |
63 | | |
64 | 0 | PR_IMPLEMENT(char) PR_GetPathSeparator(void) { |
65 | 0 | return PR_PATH_SEPARATOR; |
66 | 0 | } /* PR_GetPathSeparator */ |
67 | | |
68 | | PR_IMPLEMENT(PRStatus) |
69 | 0 | PR_GetSystemInfo(PRSysInfo cmd, char* buf, PRUint32 buflen) { |
70 | 0 | PRUintn len = 0; |
71 | |
|
72 | 0 | if (!_pr_initialized) { |
73 | 0 | _PR_ImplicitInitialization(); |
74 | 0 | } |
75 | |
|
76 | 0 | switch (cmd) { |
77 | 0 | case PR_SI_HOSTNAME: |
78 | 0 | case PR_SI_HOSTNAME_UNTRUNCATED: |
79 | 0 | if (PR_FAILURE == _PR_MD_GETHOSTNAME(buf, (PRUintn)buflen)) { |
80 | 0 | return PR_FAILURE; |
81 | 0 | } |
82 | | |
83 | 0 | if (cmd == PR_SI_HOSTNAME_UNTRUNCATED) { |
84 | 0 | break; |
85 | 0 | } |
86 | | /* |
87 | | * On some platforms a system does not have a hostname and |
88 | | * its IP address is returned instead. The following code |
89 | | * should be skipped on those platforms. |
90 | | */ |
91 | 0 | #ifndef _PR_GET_HOST_ADDR_AS_NAME |
92 | | /* Return the unqualified hostname */ |
93 | 0 | while (buf[len] && (len < buflen)) { |
94 | 0 | if (buf[len] == '.') { |
95 | 0 | buf[len] = '\0'; |
96 | 0 | break; |
97 | 0 | } |
98 | 0 | len += 1; |
99 | 0 | } |
100 | 0 | #endif |
101 | 0 | break; |
102 | | |
103 | 0 | case PR_SI_SYSNAME: |
104 | | /* Return the operating system name */ |
105 | 0 | #if defined(XP_UNIX) || defined(WIN32) |
106 | 0 | if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) { |
107 | 0 | return PR_FAILURE; |
108 | 0 | } |
109 | | #else |
110 | | (void)PR_snprintf(buf, buflen, _PR_SI_SYSNAME); |
111 | | #endif |
112 | 0 | break; |
113 | | |
114 | 0 | case PR_SI_RELEASE: |
115 | | /* Return the version of the operating system */ |
116 | 0 | #if defined(XP_UNIX) || defined(WIN32) |
117 | 0 | if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) { |
118 | 0 | return PR_FAILURE; |
119 | 0 | } |
120 | 0 | #endif |
121 | 0 | break; |
122 | | |
123 | 0 | case PR_SI_RELEASE_BUILD: |
124 | | /* Return the version of the operating system */ |
125 | 0 | #if defined(XP_UNIX) || defined(WIN32) |
126 | 0 | if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) { |
127 | 0 | return PR_FAILURE; |
128 | 0 | } |
129 | | #else |
130 | | if (buflen) { |
131 | | *buf = 0; |
132 | | } |
133 | | #endif /* XP_UNIX || WIN32 */ |
134 | 0 | break; |
135 | | |
136 | 0 | case PR_SI_ARCHITECTURE: |
137 | | /* Return the architecture of the machine (ie. x86, mips, alpha, ...)*/ |
138 | 0 | (void)PR_snprintf(buf, buflen, _PR_SI_ARCHITECTURE); |
139 | 0 | break; |
140 | 0 | default: |
141 | 0 | PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); |
142 | 0 | return PR_FAILURE; |
143 | 0 | } |
144 | 0 | return PR_SUCCESS; |
145 | 0 | } |
146 | | |
147 | | /* |
148 | | ** PR_GetNumberOfProcessors() |
149 | | ** |
150 | | ** Implementation notes: |
151 | | ** Every platform does it a bit different. |
152 | | ** numCpus is the returned value. |
153 | | ** for each platform's "if defined" section |
154 | | ** declare your local variable |
155 | | ** do your thing, assign to numCpus |
156 | | ** order of the if defined()s may be important, |
157 | | ** especially for unix variants. Do platform |
158 | | ** specific implementations before XP_UNIX. |
159 | | ** |
160 | | */ |
161 | 0 | PR_IMPLEMENT(PRInt32) PR_GetNumberOfProcessors(void) { |
162 | 0 | PRInt32 numCpus; |
163 | | #if defined(WIN32) |
164 | | SYSTEM_INFO info; |
165 | | |
166 | | GetSystemInfo(&info); |
167 | | numCpus = info.dwNumberOfProcessors; |
168 | | #elif defined(_PR_HAVE_SYSCTL) |
169 | | int mib[2]; |
170 | | int rc; |
171 | | size_t len = sizeof(numCpus); |
172 | | |
173 | | mib[0] = CTL_HW; |
174 | | # ifdef HW_NCPUONLINE |
175 | | mib[1] = HW_NCPUONLINE; |
176 | | # else |
177 | | mib[1] = HW_NCPU; |
178 | | # endif |
179 | | rc = sysctl(mib, 2, &numCpus, &len, NULL, 0); |
180 | | if (-1 == rc) { |
181 | | numCpus = -1; /* set to -1 for return value on error */ |
182 | | _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); |
183 | | } |
184 | | #elif defined(HPUX) |
185 | | numCpus = mpctl(MPC_GETNUMSPUS, 0, 0); |
186 | | if (numCpus < 1) { |
187 | | numCpus = -1; /* set to -1 for return value on error */ |
188 | | _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); |
189 | | } |
190 | | #elif defined(RISCOS) |
191 | | numCpus = 1; |
192 | | #elif defined(LINUX) |
193 | | /* for the benefit of devices with advanced power-saving, that |
194 | | actually hotplug their cpus in heavy load, try to figure out |
195 | | the real number of CPUs */ |
196 | 0 | char buf[MAX_LINE]; |
197 | 0 | FILE* fin; |
198 | 0 | const char* cpu_present = "/sys/devices/system/cpu/present"; |
199 | 0 | size_t strsize; |
200 | 0 | numCpus = 0; |
201 | 0 | fin = fopen(cpu_present, "r"); |
202 | 0 | if (fin != NULL) { |
203 | 0 | if (fgets(buf, MAX_LINE, fin) != NULL) { |
204 | | /* check that the format is what we expect */ |
205 | 0 | if (buf[0] == '0') { |
206 | 0 | strsize = strlen(buf); |
207 | 0 | if (strsize == 1) { |
208 | | /* single core */ |
209 | 0 | numCpus = 1; |
210 | 0 | } else if (strsize >= 3 && strsize <= 5) { |
211 | | /* should be of the form 0-999 */ |
212 | | /* parse the part after the 0-, note count is 0-based */ |
213 | 0 | if (buf[1] == '-' && isdigit(buf[2])) { |
214 | 0 | numCpus = 1 + atoi(buf + 2); |
215 | 0 | } |
216 | 0 | } |
217 | 0 | } |
218 | 0 | } |
219 | 0 | fclose(fin); |
220 | 0 | } |
221 | | /* if that fails, fall back to more standard methods */ |
222 | 0 | if (!numCpus) { |
223 | 0 | numCpus = sysconf(_SC_NPROCESSORS_CONF); |
224 | 0 | } |
225 | | #elif defined(XP_UNIX) |
226 | | numCpus = sysconf(_SC_NPROCESSORS_CONF); |
227 | | #else |
228 | | # error "An implementation is required" |
229 | | #endif |
230 | 0 | return (numCpus); |
231 | 0 | } /* end PR_GetNumberOfProcessors() */ |
232 | | |
233 | | /* |
234 | | ** PR_GetPhysicalMemorySize() |
235 | | ** |
236 | | ** Implementation notes: |
237 | | ** Every platform does it a bit different. |
238 | | ** bytes is the returned value. |
239 | | ** for each platform's "if defined" section |
240 | | ** declare your local variable |
241 | | ** do your thing, assign to bytes. |
242 | | ** |
243 | | */ |
244 | 0 | PR_IMPLEMENT(PRUint64) PR_GetPhysicalMemorySize(void) { |
245 | 0 | PRUint64 bytes = 0; |
246 | |
|
247 | 0 | #if defined(LINUX) || defined(SOLARIS) |
248 | |
|
249 | 0 | long pageSize = sysconf(_SC_PAGESIZE); |
250 | 0 | long pageCount = sysconf(_SC_PHYS_PAGES); |
251 | 0 | if (pageSize >= 0 && pageCount >= 0) { |
252 | 0 | bytes = (PRUint64)pageSize * pageCount; |
253 | 0 | } |
254 | |
|
255 | | #elif defined(NETBSD) || defined(OPENBSD) || defined(FREEBSD) || \ |
256 | | defined(DRAGONFLY) |
257 | | |
258 | | int mib[2]; |
259 | | int rc; |
260 | | # ifdef HW_PHYSMEM64 |
261 | | uint64_t memSize; |
262 | | # else |
263 | | unsigned long memSize; |
264 | | # endif |
265 | | size_t len = sizeof(memSize); |
266 | | |
267 | | mib[0] = CTL_HW; |
268 | | # ifdef HW_PHYSMEM64 |
269 | | mib[1] = HW_PHYSMEM64; |
270 | | # else |
271 | | mib[1] = HW_PHYSMEM; |
272 | | # endif |
273 | | rc = sysctl(mib, 2, &memSize, &len, NULL, 0); |
274 | | if (-1 != rc) { |
275 | | bytes = memSize; |
276 | | } |
277 | | |
278 | | #elif defined(HPUX) |
279 | | |
280 | | struct pst_static info; |
281 | | int result = pstat_getstatic(&info, sizeof(info), 1, 0); |
282 | | if (result == 1) { |
283 | | bytes = (PRUint64)info.physical_memory * info.page_size; |
284 | | } |
285 | | |
286 | | #elif defined(DARWIN) |
287 | | |
288 | | mach_port_t mach_host = mach_host_self(); |
289 | | struct host_basic_info hInfo; |
290 | | mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; |
291 | | |
292 | | int result = |
293 | | host_info(mach_host, HOST_BASIC_INFO, (host_info_t)&hInfo, &count); |
294 | | mach_port_deallocate(mach_task_self(), mach_host); |
295 | | if (result == KERN_SUCCESS) { |
296 | | bytes = hInfo.max_mem; |
297 | | } |
298 | | |
299 | | #elif defined(WIN32) |
300 | | |
301 | | MEMORYSTATUSEX memStat; |
302 | | memStat.dwLength = sizeof(memStat); |
303 | | if (GlobalMemoryStatusEx(&memStat)) { |
304 | | bytes = memStat.ullTotalPhys; |
305 | | } |
306 | | |
307 | | #elif defined(AIX) |
308 | | |
309 | | if (odm_initialize() == 0) { |
310 | | int how_many; |
311 | | struct CuAt* obj = getattr("sys0", "realmem", 0, &how_many); |
312 | | if (obj != NULL) { |
313 | | bytes = (PRUint64)atoi(obj->value) * 1024; |
314 | | free(obj); |
315 | | } |
316 | | odm_terminate(); |
317 | | } |
318 | | |
319 | | #else |
320 | | |
321 | | PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); |
322 | | |
323 | | #endif |
324 | |
|
325 | 0 | return bytes; |
326 | 0 | } /* end PR_GetPhysicalMemorySize() */ |