1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/src/misc/prsystem.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,348 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "primpl.h" 1.10 +#include "prsystem.h" 1.11 +#include "prprf.h" 1.12 +#include "prlong.h" 1.13 + 1.14 +#if defined(BEOS) 1.15 +#include <kernel/OS.h> 1.16 +#endif 1.17 + 1.18 +#if defined(OS2) 1.19 +#define INCL_DOS 1.20 +#define INCL_DOSMISC 1.21 +#include <os2.h> 1.22 +/* define the required constant if it is not already defined in the headers */ 1.23 +#ifndef QSV_NUMPROCESSORS 1.24 +#define QSV_NUMPROCESSORS 26 1.25 +#endif 1.26 +#endif 1.27 + 1.28 +/* BSD-derived systems use sysctl() to get the number of processors */ 1.29 +#if defined(BSDI) || defined(FREEBSD) || defined(NETBSD) \ 1.30 + || defined(OPENBSD) || defined(DARWIN) 1.31 +#define _PR_HAVE_SYSCTL 1.32 +#include <sys/param.h> 1.33 +#include <sys/sysctl.h> 1.34 +#endif 1.35 + 1.36 +#if defined(DARWIN) 1.37 +#include <mach/mach_init.h> 1.38 +#include <mach/mach_host.h> 1.39 +#include <mach/mach_port.h> 1.40 +#endif 1.41 + 1.42 +#if defined(HPUX) 1.43 +#include <sys/mpctl.h> 1.44 +#include <sys/pstat.h> 1.45 +#endif 1.46 + 1.47 +#if defined(XP_UNIX) 1.48 +#include <unistd.h> 1.49 +#include <sys/utsname.h> 1.50 +#endif 1.51 + 1.52 +#if defined(LINUX) 1.53 +#include <string.h> 1.54 +#include <ctype.h> 1.55 +#define MAX_LINE 512 1.56 +#endif 1.57 + 1.58 +#if defined(AIX) 1.59 +#include <cf.h> 1.60 +#include <sys/cfgodm.h> 1.61 +#endif 1.62 + 1.63 +PR_IMPLEMENT(char) PR_GetDirectorySeparator(void) 1.64 +{ 1.65 + return PR_DIRECTORY_SEPARATOR; 1.66 +} /* PR_GetDirectorySeparator */ 1.67 + 1.68 +/* 1.69 +** OBSOLETE -- the function name is misspelled. 1.70 +*/ 1.71 +PR_IMPLEMENT(char) PR_GetDirectorySepartor(void) 1.72 +{ 1.73 +#if defined(DEBUG) 1.74 + static PRBool warn = PR_TRUE; 1.75 + if (warn) { 1.76 + warn = _PR_Obsolete("PR_GetDirectorySepartor()", 1.77 + "PR_GetDirectorySeparator()"); 1.78 + } 1.79 +#endif 1.80 + return PR_GetDirectorySeparator(); 1.81 +} /* PR_GetDirectorySepartor */ 1.82 + 1.83 +PR_IMPLEMENT(char) PR_GetPathSeparator(void) 1.84 +{ 1.85 + return PR_PATH_SEPARATOR; 1.86 +} /* PR_GetPathSeparator */ 1.87 + 1.88 +PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 buflen) 1.89 +{ 1.90 + PRUintn len = 0; 1.91 + 1.92 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.93 + 1.94 + switch(cmd) 1.95 + { 1.96 + case PR_SI_HOSTNAME: 1.97 + case PR_SI_HOSTNAME_UNTRUNCATED: 1.98 + if (PR_FAILURE == _PR_MD_GETHOSTNAME(buf, (PRUintn)buflen)) 1.99 + return PR_FAILURE; 1.100 + 1.101 + if (cmd == PR_SI_HOSTNAME_UNTRUNCATED) 1.102 + break; 1.103 + /* 1.104 + * On some platforms a system does not have a hostname and 1.105 + * its IP address is returned instead. The following code 1.106 + * should be skipped on those platforms. 1.107 + */ 1.108 +#ifndef _PR_GET_HOST_ADDR_AS_NAME 1.109 + /* Return the unqualified hostname */ 1.110 + while (buf[len] && (len < buflen)) { 1.111 + if (buf[len] == '.') { 1.112 + buf[len] = '\0'; 1.113 + break; 1.114 + } 1.115 + len += 1; 1.116 + } 1.117 +#endif 1.118 + break; 1.119 + 1.120 + case PR_SI_SYSNAME: 1.121 + /* Return the operating system name */ 1.122 +#if defined(XP_UNIX) || defined(WIN32) 1.123 + if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) 1.124 + return PR_FAILURE; 1.125 +#else 1.126 + (void)PR_snprintf(buf, buflen, _PR_SI_SYSNAME); 1.127 +#endif 1.128 + break; 1.129 + 1.130 + case PR_SI_RELEASE: 1.131 + /* Return the version of the operating system */ 1.132 +#if defined(XP_UNIX) || defined(WIN32) 1.133 + if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) 1.134 + return PR_FAILURE; 1.135 +#endif 1.136 +#if defined(XP_OS2) 1.137 + { 1.138 + ULONG os2ver[2] = {0}; 1.139 + DosQuerySysInfo(QSV_VERSION_MINOR, QSV_VERSION_REVISION, 1.140 + &os2ver, sizeof(os2ver)); 1.141 + /* Formatting for normal usage (2.11, 3.0, 4.0, 4.5); officially, 1.142 + Warp 4 is version 2.40.00, WSeB 2.45.00 */ 1.143 + if (os2ver[0] < 30) 1.144 + (void)PR_snprintf(buf, buflen, "%s%lu", 1.145 + "2.", os2ver[0]); 1.146 + else if (os2ver[0] < 45) 1.147 + (void)PR_snprintf(buf, buflen, "%lu%s%lu", 1.148 + os2ver[0]/10, ".", os2ver[1]); 1.149 + else 1.150 + (void)PR_snprintf(buf, buflen, "%.1f", 1.151 + os2ver[0]/10.0); 1.152 + } 1.153 +#endif /* OS2 */ 1.154 + break; 1.155 + 1.156 + case PR_SI_ARCHITECTURE: 1.157 + /* Return the architecture of the machine (ie. x86, mips, alpha, ...)*/ 1.158 + (void)PR_snprintf(buf, buflen, _PR_SI_ARCHITECTURE); 1.159 + break; 1.160 + default: 1.161 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.162 + return PR_FAILURE; 1.163 + } 1.164 + return PR_SUCCESS; 1.165 +} 1.166 + 1.167 +/* 1.168 +** PR_GetNumberOfProcessors() 1.169 +** 1.170 +** Implementation notes: 1.171 +** Every platform does it a bit different. 1.172 +** numCpus is the returned value. 1.173 +** for each platform's "if defined" section 1.174 +** declare your local variable 1.175 +** do your thing, assign to numCpus 1.176 +** order of the if defined()s may be important, 1.177 +** especially for unix variants. Do platform 1.178 +** specific implementations before XP_UNIX. 1.179 +** 1.180 +*/ 1.181 +PR_IMPLEMENT(PRInt32) PR_GetNumberOfProcessors( void ) 1.182 +{ 1.183 + PRInt32 numCpus; 1.184 +#if defined(WIN32) 1.185 + SYSTEM_INFO info; 1.186 + 1.187 + GetSystemInfo( &info ); 1.188 + numCpus = info.dwNumberOfProcessors; 1.189 +#elif defined(BEOS) 1.190 + system_info sysInfo; 1.191 + 1.192 + get_system_info(&sysInfo); 1.193 + numCpus = sysInfo.cpu_count; 1.194 +#elif defined(OS2) 1.195 + DosQuerySysInfo( QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &numCpus, sizeof(numCpus)); 1.196 +#elif defined(_PR_HAVE_SYSCTL) 1.197 + int mib[2]; 1.198 + int rc; 1.199 + size_t len = sizeof(numCpus); 1.200 + 1.201 + mib[0] = CTL_HW; 1.202 + mib[1] = HW_NCPU; 1.203 + rc = sysctl( mib, 2, &numCpus, &len, NULL, 0 ); 1.204 + if ( -1 == rc ) { 1.205 + numCpus = -1; /* set to -1 for return value on error */ 1.206 + _PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() ); 1.207 + } 1.208 +#elif defined(HPUX) 1.209 + numCpus = mpctl( MPC_GETNUMSPUS, 0, 0 ); 1.210 + if ( numCpus < 1 ) { 1.211 + numCpus = -1; /* set to -1 for return value on error */ 1.212 + _PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() ); 1.213 + } 1.214 +#elif defined(IRIX) 1.215 + numCpus = sysconf( _SC_NPROC_ONLN ); 1.216 +#elif defined(RISCOS) || defined(SYMBIAN) 1.217 + numCpus = 1; 1.218 +#elif defined(LINUX) 1.219 + /* for the benefit of devices with advanced power-saving, that 1.220 + actually hotplug their cpus in heavy load, try to figure out 1.221 + the real number of CPUs */ 1.222 + char buf[MAX_LINE]; 1.223 + FILE *fin; 1.224 + const char *cpu_present = "/sys/devices/system/cpu/present"; 1.225 + size_t strsize; 1.226 + numCpus = 0; 1.227 + fin = fopen(cpu_present, "r"); 1.228 + if (fin != NULL) { 1.229 + if (fgets(buf, MAX_LINE, fin) != NULL) { 1.230 + /* check that the format is what we expect */ 1.231 + if (buf[0] == '0') { 1.232 + strsize = strlen(buf); 1.233 + if (strsize == 1) { 1.234 + /* single core */ 1.235 + numCpus = 1; 1.236 + } else if (strsize >= 3 && strsize <= 5) { 1.237 + /* should be of the form 0-999 */ 1.238 + /* parse the part after the 0-, note count is 0-based */ 1.239 + if (buf[1] == '-' && isdigit(buf[2])) { 1.240 + numCpus = 1 + atoi(buf + 2); 1.241 + } 1.242 + } 1.243 + } 1.244 + } 1.245 + fclose(fin); 1.246 + } 1.247 + /* if that fails, fall back to more standard methods */ 1.248 + if (!numCpus) { 1.249 + numCpus = sysconf( _SC_NPROCESSORS_CONF ); 1.250 + } 1.251 +#elif defined(XP_UNIX) 1.252 + numCpus = sysconf( _SC_NPROCESSORS_CONF ); 1.253 +#else 1.254 +#error "An implementation is required" 1.255 +#endif 1.256 + return(numCpus); 1.257 +} /* end PR_GetNumberOfProcessors() */ 1.258 + 1.259 +/* 1.260 +** PR_GetPhysicalMemorySize() 1.261 +** 1.262 +** Implementation notes: 1.263 +** Every platform does it a bit different. 1.264 +** bytes is the returned value. 1.265 +** for each platform's "if defined" section 1.266 +** declare your local variable 1.267 +** do your thing, assign to bytes. 1.268 +** 1.269 +*/ 1.270 +PR_IMPLEMENT(PRUint64) PR_GetPhysicalMemorySize(void) 1.271 +{ 1.272 + PRUint64 bytes = 0; 1.273 + 1.274 +#if defined(LINUX) || defined(SOLARIS) 1.275 + 1.276 + long pageSize = sysconf(_SC_PAGESIZE); 1.277 + long pageCount = sysconf(_SC_PHYS_PAGES); 1.278 + if (pageSize >= 0 && pageCount >= 0) 1.279 + bytes = (PRUint64) pageSize * pageCount; 1.280 + 1.281 +#elif defined(NETBSD) || defined(OPENBSD) 1.282 + 1.283 + int mib[2]; 1.284 + int rc; 1.285 + uint64_t memSize; 1.286 + size_t len = sizeof(memSize); 1.287 + 1.288 + mib[0] = CTL_HW; 1.289 + mib[1] = HW_PHYSMEM64; 1.290 + rc = sysctl(mib, 2, &memSize, &len, NULL, 0); 1.291 + if (-1 != rc) { 1.292 + bytes = memSize; 1.293 + } 1.294 + 1.295 +#elif defined(HPUX) 1.296 + 1.297 + struct pst_static info; 1.298 + int result = pstat_getstatic(&info, sizeof(info), 1, 0); 1.299 + if (result == 1) 1.300 + bytes = (PRUint64) info.physical_memory * info.page_size; 1.301 + 1.302 +#elif defined(DARWIN) 1.303 + 1.304 + mach_port_t mach_host = mach_host_self(); 1.305 + struct host_basic_info hInfo; 1.306 + mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; 1.307 + 1.308 + int result = host_info(mach_host, 1.309 + HOST_BASIC_INFO, 1.310 + (host_info_t) &hInfo, 1.311 + &count); 1.312 + mach_port_deallocate(mach_task_self(), mach_host); 1.313 + if (result == KERN_SUCCESS) 1.314 + bytes = hInfo.max_mem; 1.315 + 1.316 +#elif defined(WIN32) 1.317 + 1.318 + MEMORYSTATUSEX memStat; 1.319 + memStat.dwLength = sizeof(memStat); 1.320 + if (GlobalMemoryStatusEx(&memStat)) 1.321 + bytes = memStat.ullTotalPhys; 1.322 + 1.323 +#elif defined(OS2) 1.324 + 1.325 + ULONG ulPhysMem; 1.326 + DosQuerySysInfo(QSV_TOTPHYSMEM, 1.327 + QSV_TOTPHYSMEM, 1.328 + &ulPhysMem, 1.329 + sizeof(ulPhysMem)); 1.330 + bytes = ulPhysMem; 1.331 + 1.332 +#elif defined(AIX) 1.333 + 1.334 + if (odm_initialize() == 0) { 1.335 + int how_many; 1.336 + struct CuAt *obj = getattr("sys0", "realmem", 0, &how_many); 1.337 + if (obj != NULL) { 1.338 + bytes = (PRUint64) atoi(obj->value) * 1024; 1.339 + free(obj); 1.340 + } 1.341 + odm_terminate(); 1.342 + } 1.343 + 1.344 +#else 1.345 + 1.346 + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 1.347 + 1.348 +#endif 1.349 + 1.350 + return bytes; 1.351 +} /* end PR_GetPhysicalMemorySize() */