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