Upload Tizen:Base source
[toolchains/nspr.git] / mozilla / nsprpub / pr / src / misc / prsystem.c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  * http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  *
15  * The Original Code is the Netscape Portable Runtime (NSPR).
16  *
17  * The Initial Developer of the Original Code is
18  * Netscape Communications Corporation.
19  * Portions created by the Initial Developer are Copyright (C) 1998-2000
20  * the Initial Developer. All Rights Reserved.
21  *
22  * Contributor(s):
23  *
24  * Alternatively, the contents of this file may be used under the terms of
25  * either the GNU General Public License Version 2 or later (the "GPL"), or
26  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27  * in which case the provisions of the GPL or the LGPL are applicable instead
28  * of those above. If you wish to allow use of your version of this file only
29  * under the terms of either the GPL or the LGPL, and not to allow others to
30  * use your version of this file under the terms of the MPL, indicate your
31  * decision by deleting the provisions above and replace them with the notice
32  * and other provisions required by the GPL or the LGPL. If you do not delete
33  * the provisions above, a recipient may use your version of this file under
34  * the terms of any one of the MPL, the GPL or the LGPL.
35  *
36  * ***** END LICENSE BLOCK ***** */
37
38 #include "primpl.h"
39 #include "prsystem.h"
40 #include "prprf.h"
41 #include "prlong.h"
42
43 #if defined(BEOS)
44 #include <kernel/OS.h>
45 #endif
46
47 #if defined(OS2)
48 #define INCL_DOS
49 #define INCL_DOSMISC
50 #include <os2.h>
51 /* define the required constant if it is not already defined in the headers */
52 #ifndef QSV_NUMPROCESSORS
53 #define QSV_NUMPROCESSORS 26
54 #endif
55 #endif
56
57 /* BSD-derived systems use sysctl() to get the number of processors */
58 #if defined(BSDI) || defined(FREEBSD) || defined(NETBSD) \
59     || defined(OPENBSD) || defined(DARWIN)
60 #define _PR_HAVE_SYSCTL
61 #include <sys/param.h>
62 #include <sys/sysctl.h>
63 #endif
64
65 #if defined(DARWIN)
66 #include <mach/mach_init.h>
67 #include <mach/mach_host.h>
68 #endif
69
70 #if defined(HPUX)
71 #include <sys/mpctl.h>
72 #include <sys/pstat.h>
73 #endif
74
75 #if defined(XP_UNIX)
76 #include <unistd.h>
77 #include <sys/utsname.h>
78 #endif
79
80 #if defined(AIX)
81 #include <cf.h>
82 #include <sys/cfgodm.h>
83 #endif
84
85 #if defined(WIN32)
86 /* This struct is not present in VC6 headers, so declare it here */
87 typedef struct {
88     DWORD dwLength;
89     DWORD dwMemoryLoad;
90     DWORDLONG ullTotalPhys;
91     DWORDLONG ullAvailPhys;
92     DWORDLONG ullToalPageFile;
93     DWORDLONG ullAvailPageFile;
94     DWORDLONG ullTotalVirtual;
95     DWORDLONG ullAvailVirtual;
96     DWORDLONG ullAvailExtendedVirtual;
97 } PR_MEMORYSTATUSEX;
98
99 /* Typedef for dynamic lookup of GlobalMemoryStatusEx(). */
100 typedef BOOL (WINAPI *GlobalMemoryStatusExFn)(PR_MEMORYSTATUSEX *);
101 #endif
102
103 PR_IMPLEMENT(char) PR_GetDirectorySeparator(void)
104 {
105     return PR_DIRECTORY_SEPARATOR;
106 }  /* PR_GetDirectorySeparator */
107
108 /*
109 ** OBSOLETE -- the function name is misspelled.
110 */
111 PR_IMPLEMENT(char) PR_GetDirectorySepartor(void)
112 {
113 #if defined(DEBUG)
114     static PRBool warn = PR_TRUE;
115     if (warn) {
116         warn = _PR_Obsolete("PR_GetDirectorySepartor()",
117                 "PR_GetDirectorySeparator()");
118     }
119 #endif
120     return PR_GetDirectorySeparator();
121 }  /* PR_GetDirectorySepartor */
122
123 PR_IMPLEMENT(char) PR_GetPathSeparator(void)
124 {
125     return PR_PATH_SEPARATOR;
126 }  /* PR_GetPathSeparator */
127
128 PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 buflen)
129 {
130     PRUintn len = 0;
131
132     if (!_pr_initialized) _PR_ImplicitInitialization();
133
134     switch(cmd)
135     {
136       case PR_SI_HOSTNAME:
137       case PR_SI_HOSTNAME_UNTRUNCATED:
138         if (PR_FAILURE == _PR_MD_GETHOSTNAME(buf, (PRUintn)buflen))
139             return PR_FAILURE;
140
141         if (cmd == PR_SI_HOSTNAME_UNTRUNCATED)
142             break;
143         /*
144          * On some platforms a system does not have a hostname and
145          * its IP address is returned instead.   The following code
146          * should be skipped on those platforms.
147          */
148 #ifndef _PR_GET_HOST_ADDR_AS_NAME
149         /* Return the unqualified hostname */
150             while (buf[len] && (len < buflen)) {
151                 if (buf[len] == '.') {
152                     buf[len] = '\0';
153                     break;
154                 }
155                 len += 1;
156             }    
157 #endif
158          break;
159
160       case PR_SI_SYSNAME:
161         /* Return the operating system name */
162 #if defined(XP_UNIX) || defined(WIN32)
163         if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen))
164             return PR_FAILURE;
165 #else
166         (void)PR_snprintf(buf, buflen, _PR_SI_SYSNAME);
167 #endif
168         break;
169
170       case PR_SI_RELEASE:
171         /* Return the version of the operating system */
172 #if defined(XP_UNIX) || defined(WIN32)
173         if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen))
174             return PR_FAILURE;
175 #endif
176 #if defined(XP_OS2)
177         {
178             ULONG os2ver[2] = {0};
179             DosQuerySysInfo(QSV_VERSION_MINOR, QSV_VERSION_REVISION,
180                             &os2ver, sizeof(os2ver));
181             /* Formatting for normal usage (2.11, 3.0, 4.0, 4.5); officially,
182                Warp 4 is version 2.40.00, WSeB 2.45.00 */
183             if (os2ver[0] < 30)
184               (void)PR_snprintf(buf, buflen, "%s%lu",
185                                 "2.", os2ver[0]);
186             else if (os2ver[0] < 45)
187               (void)PR_snprintf(buf, buflen, "%lu%s%lu",
188                                 os2ver[0]/10, ".", os2ver[1]);
189             else
190               (void)PR_snprintf(buf, buflen, "%.1f",
191                                 os2ver[0]/10.0);
192         }
193 #endif /* OS2 */
194         break;
195
196       case PR_SI_ARCHITECTURE:
197         /* Return the architecture of the machine (ie. x86, mips, alpha, ...)*/
198         (void)PR_snprintf(buf, buflen, _PR_SI_ARCHITECTURE);
199         break;
200           default:
201                         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
202                         return PR_FAILURE;
203     }
204     return PR_SUCCESS;
205 }
206
207 /*
208 ** PR_GetNumberOfProcessors()
209 ** 
210 ** Implementation notes:
211 **   Every platform does it a bit different.
212 **     numCpus is the returned value.
213 **   for each platform's "if defined" section
214 **     declare your local variable
215 **     do your thing, assign to numCpus
216 **   order of the if defined()s may be important,
217 **     especially for unix variants. Do platform
218 **     specific implementations before XP_UNIX.
219 ** 
220 */
221 PR_IMPLEMENT(PRInt32) PR_GetNumberOfProcessors( void )
222 {
223     PRInt32     numCpus;
224 #if defined(WIN32)
225     SYSTEM_INFO     info;
226
227     GetSystemInfo( &info );
228     numCpus = info.dwNumberOfProcessors;
229 #elif defined(BEOS)
230     system_info sysInfo;
231
232     get_system_info(&sysInfo);
233     numCpus = sysInfo.cpu_count;
234 #elif defined(OS2)
235     DosQuerySysInfo( QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &numCpus, sizeof(numCpus));
236 #elif defined(_PR_HAVE_SYSCTL)
237     int mib[2];
238     int rc;
239     size_t len = sizeof(numCpus);
240
241     mib[0] = CTL_HW;
242     mib[1] = HW_NCPU;
243     rc = sysctl( mib, 2, &numCpus, &len, NULL, 0 );
244     if ( -1 == rc )  {
245         numCpus = -1; /* set to -1 for return value on error */
246         _PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() );
247     }
248 #elif defined(HPUX)
249     numCpus = mpctl( MPC_GETNUMSPUS, 0, 0 );
250     if ( numCpus < 1 )  {
251         numCpus = -1; /* set to -1 for return value on error */
252         _PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() );
253     }
254 #elif defined(IRIX)
255     numCpus = sysconf( _SC_NPROC_ONLN );
256 #elif defined(RISCOS) || defined(SYMBIAN)
257     numCpus = 1;
258 #elif defined(XP_UNIX)
259     numCpus = sysconf( _SC_NPROCESSORS_ONLN );
260 #else
261 #error "An implementation is required"
262 #endif
263     return(numCpus);
264 } /* end PR_GetNumberOfProcessors() */
265
266 /*
267 ** PR_GetPhysicalMemorySize()
268 ** 
269 ** Implementation notes:
270 **   Every platform does it a bit different.
271 **     bytes is the returned value.
272 **   for each platform's "if defined" section
273 **     declare your local variable
274 **     do your thing, assign to bytes.
275 ** 
276 */
277 PR_IMPLEMENT(PRUint64) PR_GetPhysicalMemorySize(void)
278 {
279     PRUint64 bytes = 0;
280
281 #if defined(LINUX) || defined(SOLARIS)
282
283     long pageSize = sysconf(_SC_PAGESIZE);
284     long pageCount = sysconf(_SC_PHYS_PAGES);
285     bytes = (PRUint64) pageSize * pageCount;
286
287 #elif defined(NETBSD)
288
289     int mib[2];
290     int rc;
291     uint64_t memSize;
292     size_t len = sizeof(memSize);
293
294     mib[0] = CTL_HW;
295     mib[1] = HW_PHYSMEM64;
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     struct host_basic_info hInfo;
311     mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
312
313     int result = host_info(mach_host_self(),
314                            HOST_BASIC_INFO,
315                            (host_info_t) &hInfo,
316                            &count);
317     if (result == KERN_SUCCESS)
318         bytes = hInfo.max_mem;
319
320 #elif defined(WIN32)
321
322     /* Try to use the newer GlobalMemoryStatusEx API for Windows 2000+. */
323     GlobalMemoryStatusExFn globalMemory = (GlobalMemoryStatusExFn) NULL;
324     HMODULE module = GetModuleHandleW(L"kernel32.dll");
325
326     if (module) {
327         globalMemory = (GlobalMemoryStatusExFn)GetProcAddress(module, "GlobalMemoryStatusEx");
328
329         if (globalMemory) {
330             PR_MEMORYSTATUSEX memStat;
331             memStat.dwLength = sizeof(memStat);
332
333             if (globalMemory(&memStat))
334                 bytes = memStat.ullTotalPhys;
335         }
336     }
337
338     if (!bytes) {
339         /* Fall back to the older API. */
340         MEMORYSTATUS memStat;
341         memset(&memStat, 0, sizeof(memStat));
342         GlobalMemoryStatus(&memStat);
343         bytes = memStat.dwTotalPhys;
344     }
345
346 #elif defined(OS2)
347
348     ULONG ulPhysMem;
349     DosQuerySysInfo(QSV_TOTPHYSMEM,
350                     QSV_TOTPHYSMEM,
351                     &ulPhysMem,
352                     sizeof(ulPhysMem));
353     bytes = ulPhysMem;
354
355 #elif defined(AIX)
356
357     if (odm_initialize() == 0) {
358         int how_many;
359         struct CuAt *obj = getattr("sys0", "realmem", 0, &how_many);
360         if (obj != NULL) {
361             bytes = (PRUint64) atoi(obj->value) * 1024;
362             free(obj);
363         }
364         odm_terminate();
365     }
366
367 #else
368
369     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
370
371 #endif
372
373     return bytes;
374 } /* end PR_GetPhysicalMemorySize() */