Back to index

lightning-sunbird  0.9+nobinonly
prsystem.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "primpl.h"
00039 #include "prsystem.h"
00040 #include "prprf.h"
00041 #include "prlong.h"
00042 
00043 #if defined(BEOS)
00044 #include <kernel/OS.h>
00045 #endif
00046 
00047 #if defined(OS2)
00048 #define INCL_DOS
00049 #define INCL_DOSMISC
00050 #include <os2.h>
00051 /* define the required constant if it is not already defined in the headers */
00052 #ifndef QSV_NUMPROCESSORS
00053 #define QSV_NUMPROCESSORS 26
00054 #endif
00055 #endif
00056 
00057 /* BSD-derived systems use sysctl() to get the number of processors */
00058 #if defined(BSDI) || defined(FREEBSD) || defined(NETBSD) \
00059     || defined(OPENBSD) || defined(DARWIN)
00060 #define _PR_HAVE_SYSCTL
00061 #include <sys/param.h>
00062 #include <sys/sysctl.h>
00063 #endif
00064 
00065 #if defined(DARWIN)
00066 #include <mach/mach_init.h>
00067 #include <mach/mach_host.h>
00068 #endif
00069 
00070 #if defined(HPUX)
00071 #include <sys/mpctl.h>
00072 #include <sys/pstat.h>
00073 #endif
00074 
00075 #if defined(XP_UNIX)
00076 #include <unistd.h>
00077 #include <sys/utsname.h>
00078 #endif
00079 
00080 #if defined(AIX)
00081 #include <cf.h>
00082 #include <sys/cfgodm.h>
00083 #endif
00084 
00085 #if defined(WIN32)
00086 /* This struct is not present in VC6 headers, so declare it here */
00087 typedef struct {
00088     DWORD dwLength;
00089     DWORD dwMemoryLoad;
00090     DWORDLONG ullTotalPhys;
00091     DWORDLONG ullAvailPhys;
00092     DWORDLONG ullToalPageFile;
00093     DWORDLONG ullAvailPageFile;
00094     DWORDLONG ullTotalVirtual;
00095     DWORDLONG ullAvailVirtual;
00096     DWORDLONG ullAvailExtendedVirtual;
00097 } PR_MEMORYSTATUSEX;
00098 
00099 /* Typedef for dynamic lookup of GlobalMemoryStatusEx(). */
00100 typedef BOOL (WINAPI *GlobalMemoryStatusExFn)(PR_MEMORYSTATUSEX *);
00101 #endif
00102 
00103 PR_IMPLEMENT(char) PR_GetDirectorySeparator(void)
00104 {
00105     return PR_DIRECTORY_SEPARATOR;
00106 }  /* PR_GetDirectorySeparator */
00107 
00108 /*
00109 ** OBSOLETE -- the function name is misspelled.
00110 */
00111 PR_IMPLEMENT(char) PR_GetDirectorySepartor(void)
00112 {
00113 #if defined(DEBUG)
00114     static PRBool warn = PR_TRUE;
00115     if (warn) {
00116         warn = _PR_Obsolete("PR_GetDirectorySepartor()",
00117                 "PR_GetDirectorySeparator()");
00118     }
00119 #endif
00120     return PR_GetDirectorySeparator();
00121 }  /* PR_GetDirectorySepartor */
00122 
00123 PR_IMPLEMENT(char) PR_GetPathSeparator(void)
00124 {
00125     return PR_PATH_SEPARATOR;
00126 }  /* PR_GetPathSeparator */
00127 
00128 PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 buflen)
00129 {
00130     PRUintn len = 0;
00131 
00132     if (!_pr_initialized) _PR_ImplicitInitialization();
00133 
00134     switch(cmd)
00135     {
00136       case PR_SI_HOSTNAME:
00137       case PR_SI_HOSTNAME_UNTRUNCATED:
00138         if (PR_FAILURE == _PR_MD_GETHOSTNAME(buf, (PRUintn)buflen))
00139             return PR_FAILURE;
00140 
00141         if (cmd == PR_SI_HOSTNAME_UNTRUNCATED)
00142             break;
00143         /*
00144          * On some platforms a system does not have a hostname and
00145          * its IP address is returned instead.   The following code
00146          * should be skipped on those platforms.
00147          */
00148 #ifndef _PR_GET_HOST_ADDR_AS_NAME
00149         /* Return the unqualified hostname */
00150             while (buf[len] && (len < buflen)) {
00151                 if (buf[len] == '.') {
00152                     buf[len] = '\0';
00153                     break;
00154                 }
00155                 len += 1;
00156             }    
00157 #endif
00158          break;
00159 
00160       case PR_SI_SYSNAME:
00161         /* Return the operating system name */
00162 #if defined(XP_UNIX) || defined(WIN32)
00163         if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen))
00164             return PR_FAILURE;
00165 #else
00166         (void)PR_snprintf(buf, buflen, _PR_SI_SYSNAME);
00167 #endif
00168         break;
00169 
00170       case PR_SI_RELEASE:
00171         /* Return the version of the operating system */
00172 #if defined(XP_UNIX) || defined(WIN32)
00173         if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen))
00174             return PR_FAILURE;
00175 #endif
00176 #if defined(XP_OS2)
00177         {
00178             ULONG os2ver[2] = {0};
00179             DosQuerySysInfo(QSV_VERSION_MINOR, QSV_VERSION_REVISION,
00180                             &os2ver, sizeof(os2ver));
00181             /* Formatting for normal usage (2.11, 3.0, 4.0, 4.5); officially,
00182                Warp 4 is version 2.40.00, WSeB 2.45.00 */
00183             if (os2ver[0] < 30)
00184               (void)PR_snprintf(buf, buflen, "%s%lu",
00185                                 "2.", os2ver[0]);
00186             else if (os2ver[0] < 45)
00187               (void)PR_snprintf(buf, buflen, "%lu%s%lu",
00188                                 os2ver[0]/10, ".", os2ver[1]);
00189             else
00190               (void)PR_snprintf(buf, buflen, "%.1f",
00191                                 os2ver[0]/10.0);
00192         }
00193 #endif /* OS2 */
00194         break;
00195 
00196       case PR_SI_ARCHITECTURE:
00197         /* Return the architecture of the machine (ie. x86, mips, alpha, ...)*/
00198         (void)PR_snprintf(buf, buflen, _PR_SI_ARCHITECTURE);
00199         break;
00200          default:
00201                      PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
00202                      return PR_FAILURE;
00203     }
00204     return PR_SUCCESS;
00205 }
00206 
00207 /*
00208 ** PR_GetNumberOfProcessors()
00209 ** 
00210 ** Implementation notes:
00211 **   Every platform does it a bit different.
00212 **     numCpus is the returned value.
00213 **   for each platform's "if defined" section
00214 **     declare your local variable
00215 **     do your thing, assign to numCpus
00216 **   order of the if defined()s may be important,
00217 **     especially for unix variants. Do platform
00218 **     specific implementations before XP_UNIX.
00219 ** 
00220 */
00221 PR_IMPLEMENT(PRInt32) PR_GetNumberOfProcessors( void )
00222 {
00223     PRInt32     numCpus;
00224 #if defined(WIN32)
00225     SYSTEM_INFO     info;
00226 
00227     GetSystemInfo( &info );
00228     numCpus = info.dwNumberOfProcessors;
00229 #elif defined(XP_MAC)
00230 /* Hard-code the number of processors to 1 on the Mac
00231 ** MacOS/9 will always be 1. The MPProcessors() call is for
00232 ** MacOS/X, when issued. Leave it commented out for now. */
00233 /*  numCpus = MPProcessors(); */
00234     numCpus = 1;
00235 #elif defined(BEOS)
00236     system_info sysInfo;
00237 
00238     get_system_info(&sysInfo);
00239     numCpus = sysInfo.cpu_count;
00240 #elif defined(OS2)
00241     DosQuerySysInfo( QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &numCpus, sizeof(numCpus));
00242 #elif defined(_PR_HAVE_SYSCTL)
00243     int mib[2];
00244     int rc;
00245     size_t len = sizeof(numCpus);
00246 
00247     mib[0] = CTL_HW;
00248     mib[1] = HW_NCPU;
00249     rc = sysctl( mib, 2, &numCpus, &len, NULL, 0 );
00250     if ( -1 == rc )  {
00251         numCpus = -1; /* set to -1 for return value on error */
00252         _PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() );
00253     }
00254 #elif defined(HPUX)
00255     numCpus = mpctl( MPC_GETNUMSPUS, 0, 0 );
00256     if ( numCpus < 1 )  {
00257         numCpus = -1; /* set to -1 for return value on error */
00258         _PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() );
00259     }
00260 #elif defined(IRIX)
00261     numCpus = sysconf( _SC_NPROC_ONLN );
00262 #elif defined(RISCOS)
00263     numCpus = 1;
00264 #elif defined(XP_UNIX)
00265     numCpus = sysconf( _SC_NPROCESSORS_ONLN );
00266 #else
00267 #error "An implementation is required"
00268 #endif
00269     return(numCpus);
00270 } /* end PR_GetNumberOfProcessors() */
00271 
00272 /*
00273 ** PR_GetPhysicalMemorySize()
00274 ** 
00275 ** Implementation notes:
00276 **   Every platform does it a bit different.
00277 **     bytes is the returned value.
00278 **   for each platform's "if defined" section
00279 **     declare your local variable
00280 **     do your thing, assign to bytes.
00281 ** 
00282 */
00283 PR_IMPLEMENT(PRUint64) PR_GetPhysicalMemorySize(void)
00284 {
00285     PRUint64 bytes = 0;
00286 
00287 #if defined(LINUX) || defined(SOLARIS)
00288 
00289     long pageSize = sysconf(_SC_PAGESIZE);
00290     long pageCount = sysconf(_SC_PHYS_PAGES);
00291     bytes = (PRUint64) pageSize * pageCount;
00292 
00293 #elif defined(HPUX)
00294 
00295     struct pst_static info;
00296     int result = pstat_getstatic(&info, sizeof(info), 1, 0);
00297     if (result == 1)
00298         bytes = (PRUint64) info.physical_memory * info.page_size;
00299 
00300 #elif defined(DARWIN)
00301 
00302     struct host_basic_info hInfo;
00303     mach_msg_type_number_t count;
00304 
00305     int result = host_info(mach_host_self(),
00306                            HOST_BASIC_INFO,
00307                            (host_info_t) &hInfo,
00308                            &count);
00309     if (result == KERN_SUCCESS)
00310         bytes = hInfo.memory_size;
00311 
00312 #elif defined(WIN32)
00313 
00314     /* Try to use the newer GlobalMemoryStatusEx API for Windows 2000+. */
00315     GlobalMemoryStatusExFn globalMemory = (GlobalMemoryStatusExFn) NULL;
00316     HMODULE module = GetModuleHandle("kernel32.dll");
00317 
00318     if (module) {
00319         globalMemory = (GlobalMemoryStatusExFn)GetProcAddress(module, "GlobalMemoryStatusEx");
00320 
00321         if (globalMemory) {
00322             PR_MEMORYSTATUSEX memStat;
00323             memStat.dwLength = sizeof(memStat);
00324 
00325             if (globalMemory(&memStat))
00326                 bytes = memStat.ullTotalPhys;
00327         }
00328     }
00329 
00330     if (!bytes) {
00331         /* Fall back to the older API. */
00332         MEMORYSTATUS memStat;
00333         memset(&memStat, 0, sizeof(memStat));
00334         GlobalMemoryStatus(&memStat);
00335         bytes = memStat.dwTotalPhys;
00336     }
00337 
00338 #elif defined(OS2)
00339 
00340     ULONG ulPhysMem;
00341     DosQuerySysInfo(QSV_TOTPHYSMEM,
00342                     QSV_TOTPHYSMEM,
00343                     &ulPhysMem,
00344                     sizeof(ulPhysMem));
00345     bytes = ulPhysMem;
00346 
00347 #elif defined(AIX)
00348 
00349     if (odm_initialize() == 0) {
00350         int how_many;
00351         struct CuAt *obj = getattr("sys0", "realmem", 0, &how_many);
00352         if (obj != NULL) {
00353             bytes = (PRUint64) atoi(obj->value) * 1024;
00354             free(obj);
00355         }
00356         odm_terminate();
00357     }
00358 
00359 #else
00360 
00361     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
00362 
00363 #endif
00364 
00365     return bytes;
00366 } /* end PR_GetPhysicalMemorySize() */