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