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