|
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(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 #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 { |
|
62 return PR_DIRECTORY_SEPARATOR; |
|
63 } /* PR_GetDirectorySeparator */ |
|
64 |
|
65 /* |
|
66 ** OBSOLETE -- the function name is misspelled. |
|
67 */ |
|
68 PR_IMPLEMENT(char) PR_GetDirectorySepartor(void) |
|
69 { |
|
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 } /* PR_GetDirectorySepartor */ |
|
79 |
|
80 PR_IMPLEMENT(char) PR_GetPathSeparator(void) |
|
81 { |
|
82 return PR_PATH_SEPARATOR; |
|
83 } /* PR_GetPathSeparator */ |
|
84 |
|
85 PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 buflen) |
|
86 { |
|
87 PRUintn len = 0; |
|
88 |
|
89 if (!_pr_initialized) _PR_ImplicitInitialization(); |
|
90 |
|
91 switch(cmd) |
|
92 { |
|
93 case PR_SI_HOSTNAME: |
|
94 case PR_SI_HOSTNAME_UNTRUNCATED: |
|
95 if (PR_FAILURE == _PR_MD_GETHOSTNAME(buf, (PRUintn)buflen)) |
|
96 return PR_FAILURE; |
|
97 |
|
98 if (cmd == PR_SI_HOSTNAME_UNTRUNCATED) |
|
99 break; |
|
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 #ifndef _PR_GET_HOST_ADDR_AS_NAME |
|
106 /* Return the unqualified hostname */ |
|
107 while (buf[len] && (len < buflen)) { |
|
108 if (buf[len] == '.') { |
|
109 buf[len] = '\0'; |
|
110 break; |
|
111 } |
|
112 len += 1; |
|
113 } |
|
114 #endif |
|
115 break; |
|
116 |
|
117 case PR_SI_SYSNAME: |
|
118 /* Return the operating system name */ |
|
119 #if defined(XP_UNIX) || defined(WIN32) |
|
120 if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) |
|
121 return PR_FAILURE; |
|
122 #else |
|
123 (void)PR_snprintf(buf, buflen, _PR_SI_SYSNAME); |
|
124 #endif |
|
125 break; |
|
126 |
|
127 case PR_SI_RELEASE: |
|
128 /* Return the version of the operating system */ |
|
129 #if defined(XP_UNIX) || defined(WIN32) |
|
130 if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) |
|
131 return PR_FAILURE; |
|
132 #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 break; |
|
152 |
|
153 case PR_SI_ARCHITECTURE: |
|
154 /* Return the architecture of the machine (ie. x86, mips, alpha, ...)*/ |
|
155 (void)PR_snprintf(buf, buflen, _PR_SI_ARCHITECTURE); |
|
156 break; |
|
157 default: |
|
158 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); |
|
159 return PR_FAILURE; |
|
160 } |
|
161 return PR_SUCCESS; |
|
162 } |
|
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 { |
|
180 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 actually hotplug their cpus in heavy load, try to figure out |
|
218 the real number of CPUs */ |
|
219 char buf[MAX_LINE]; |
|
220 FILE *fin; |
|
221 const char *cpu_present = "/sys/devices/system/cpu/present"; |
|
222 size_t strsize; |
|
223 numCpus = 0; |
|
224 fin = fopen(cpu_present, "r"); |
|
225 if (fin != NULL) { |
|
226 if (fgets(buf, MAX_LINE, fin) != NULL) { |
|
227 /* check that the format is what we expect */ |
|
228 if (buf[0] == '0') { |
|
229 strsize = strlen(buf); |
|
230 if (strsize == 1) { |
|
231 /* single core */ |
|
232 numCpus = 1; |
|
233 } else if (strsize >= 3 && strsize <= 5) { |
|
234 /* should be of the form 0-999 */ |
|
235 /* parse the part after the 0-, note count is 0-based */ |
|
236 if (buf[1] == '-' && isdigit(buf[2])) { |
|
237 numCpus = 1 + atoi(buf + 2); |
|
238 } |
|
239 } |
|
240 } |
|
241 } |
|
242 fclose(fin); |
|
243 } |
|
244 /* if that fails, fall back to more standard methods */ |
|
245 if (!numCpus) { |
|
246 numCpus = sysconf( _SC_NPROCESSORS_CONF ); |
|
247 } |
|
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 } /* 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 { |
|
269 PRUint64 bytes = 0; |
|
270 |
|
271 #if defined(LINUX) || defined(SOLARIS) |
|
272 |
|
273 long pageSize = sysconf(_SC_PAGESIZE); |
|
274 long pageCount = sysconf(_SC_PHYS_PAGES); |
|
275 if (pageSize >= 0 && pageCount >= 0) |
|
276 bytes = (PRUint64) pageSize * pageCount; |
|
277 |
|
278 #elif defined(NETBSD) || defined(OPENBSD) |
|
279 |
|
280 int mib[2]; |
|
281 int rc; |
|
282 uint64_t memSize; |
|
283 size_t len = sizeof(memSize); |
|
284 |
|
285 mib[0] = CTL_HW; |
|
286 mib[1] = HW_PHYSMEM64; |
|
287 rc = sysctl(mib, 2, &memSize, &len, NULL, 0); |
|
288 if (-1 != rc) { |
|
289 bytes = memSize; |
|
290 } |
|
291 |
|
292 #elif defined(HPUX) |
|
293 |
|
294 struct pst_static info; |
|
295 int result = pstat_getstatic(&info, sizeof(info), 1, 0); |
|
296 if (result == 1) |
|
297 bytes = (PRUint64) info.physical_memory * info.page_size; |
|
298 |
|
299 #elif defined(DARWIN) |
|
300 |
|
301 mach_port_t mach_host = mach_host_self(); |
|
302 struct host_basic_info hInfo; |
|
303 mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; |
|
304 |
|
305 int result = host_info(mach_host, |
|
306 HOST_BASIC_INFO, |
|
307 (host_info_t) &hInfo, |
|
308 &count); |
|
309 mach_port_deallocate(mach_task_self(), mach_host); |
|
310 if (result == KERN_SUCCESS) |
|
311 bytes = hInfo.max_mem; |
|
312 |
|
313 #elif defined(WIN32) |
|
314 |
|
315 MEMORYSTATUSEX memStat; |
|
316 memStat.dwLength = sizeof(memStat); |
|
317 if (GlobalMemoryStatusEx(&memStat)) |
|
318 bytes = memStat.ullTotalPhys; |
|
319 |
|
320 #elif defined(OS2) |
|
321 |
|
322 ULONG ulPhysMem; |
|
323 DosQuerySysInfo(QSV_TOTPHYSMEM, |
|
324 QSV_TOTPHYSMEM, |
|
325 &ulPhysMem, |
|
326 sizeof(ulPhysMem)); |
|
327 bytes = ulPhysMem; |
|
328 |
|
329 #elif defined(AIX) |
|
330 |
|
331 if (odm_initialize() == 0) { |
|
332 int how_many; |
|
333 struct CuAt *obj = getattr("sys0", "realmem", 0, &how_many); |
|
334 if (obj != NULL) { |
|
335 bytes = (PRUint64) atoi(obj->value) * 1024; |
|
336 free(obj); |
|
337 } |
|
338 odm_terminate(); |
|
339 } |
|
340 |
|
341 #else |
|
342 |
|
343 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); |
|
344 |
|
345 #endif |
|
346 |
|
347 return bytes; |
|
348 } /* end PR_GetPhysicalMemorySize() */ |