michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "primpl.h" michael@0: #include "prsystem.h" michael@0: #include "prprf.h" michael@0: #include "prlong.h" michael@0: michael@0: #if defined(BEOS) michael@0: #include michael@0: #endif michael@0: michael@0: #if defined(OS2) michael@0: #define INCL_DOS michael@0: #define INCL_DOSMISC michael@0: #include michael@0: /* define the required constant if it is not already defined in the headers */ michael@0: #ifndef QSV_NUMPROCESSORS michael@0: #define QSV_NUMPROCESSORS 26 michael@0: #endif michael@0: #endif michael@0: michael@0: /* BSD-derived systems use sysctl() to get the number of processors */ michael@0: #if defined(BSDI) || defined(FREEBSD) || defined(NETBSD) \ michael@0: || defined(OPENBSD) || defined(DARWIN) michael@0: #define _PR_HAVE_SYSCTL michael@0: #include michael@0: #include michael@0: #endif michael@0: michael@0: #if defined(DARWIN) michael@0: #include michael@0: #include michael@0: #include michael@0: #endif michael@0: michael@0: #if defined(HPUX) michael@0: #include michael@0: #include michael@0: #endif michael@0: michael@0: #if defined(XP_UNIX) michael@0: #include michael@0: #include michael@0: #endif michael@0: michael@0: #if defined(LINUX) michael@0: #include michael@0: #include michael@0: #define MAX_LINE 512 michael@0: #endif michael@0: michael@0: #if defined(AIX) michael@0: #include michael@0: #include michael@0: #endif michael@0: michael@0: PR_IMPLEMENT(char) PR_GetDirectorySeparator(void) michael@0: { michael@0: return PR_DIRECTORY_SEPARATOR; michael@0: } /* PR_GetDirectorySeparator */ michael@0: michael@0: /* michael@0: ** OBSOLETE -- the function name is misspelled. michael@0: */ michael@0: PR_IMPLEMENT(char) PR_GetDirectorySepartor(void) michael@0: { michael@0: #if defined(DEBUG) michael@0: static PRBool warn = PR_TRUE; michael@0: if (warn) { michael@0: warn = _PR_Obsolete("PR_GetDirectorySepartor()", michael@0: "PR_GetDirectorySeparator()"); michael@0: } michael@0: #endif michael@0: return PR_GetDirectorySeparator(); michael@0: } /* PR_GetDirectorySepartor */ michael@0: michael@0: PR_IMPLEMENT(char) PR_GetPathSeparator(void) michael@0: { michael@0: return PR_PATH_SEPARATOR; michael@0: } /* PR_GetPathSeparator */ michael@0: michael@0: PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 buflen) michael@0: { michael@0: PRUintn len = 0; michael@0: michael@0: if (!_pr_initialized) _PR_ImplicitInitialization(); michael@0: michael@0: switch(cmd) michael@0: { michael@0: case PR_SI_HOSTNAME: michael@0: case PR_SI_HOSTNAME_UNTRUNCATED: michael@0: if (PR_FAILURE == _PR_MD_GETHOSTNAME(buf, (PRUintn)buflen)) michael@0: return PR_FAILURE; michael@0: michael@0: if (cmd == PR_SI_HOSTNAME_UNTRUNCATED) michael@0: break; michael@0: /* michael@0: * On some platforms a system does not have a hostname and michael@0: * its IP address is returned instead. The following code michael@0: * should be skipped on those platforms. michael@0: */ michael@0: #ifndef _PR_GET_HOST_ADDR_AS_NAME michael@0: /* Return the unqualified hostname */ michael@0: while (buf[len] && (len < buflen)) { michael@0: if (buf[len] == '.') { michael@0: buf[len] = '\0'; michael@0: break; michael@0: } michael@0: len += 1; michael@0: } michael@0: #endif michael@0: break; michael@0: michael@0: case PR_SI_SYSNAME: michael@0: /* Return the operating system name */ michael@0: #if defined(XP_UNIX) || defined(WIN32) michael@0: if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) michael@0: return PR_FAILURE; michael@0: #else michael@0: (void)PR_snprintf(buf, buflen, _PR_SI_SYSNAME); michael@0: #endif michael@0: break; michael@0: michael@0: case PR_SI_RELEASE: michael@0: /* Return the version of the operating system */ michael@0: #if defined(XP_UNIX) || defined(WIN32) michael@0: if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) michael@0: return PR_FAILURE; michael@0: #endif michael@0: #if defined(XP_OS2) michael@0: { michael@0: ULONG os2ver[2] = {0}; michael@0: DosQuerySysInfo(QSV_VERSION_MINOR, QSV_VERSION_REVISION, michael@0: &os2ver, sizeof(os2ver)); michael@0: /* Formatting for normal usage (2.11, 3.0, 4.0, 4.5); officially, michael@0: Warp 4 is version 2.40.00, WSeB 2.45.00 */ michael@0: if (os2ver[0] < 30) michael@0: (void)PR_snprintf(buf, buflen, "%s%lu", michael@0: "2.", os2ver[0]); michael@0: else if (os2ver[0] < 45) michael@0: (void)PR_snprintf(buf, buflen, "%lu%s%lu", michael@0: os2ver[0]/10, ".", os2ver[1]); michael@0: else michael@0: (void)PR_snprintf(buf, buflen, "%.1f", michael@0: os2ver[0]/10.0); michael@0: } michael@0: #endif /* OS2 */ michael@0: break; michael@0: michael@0: case PR_SI_ARCHITECTURE: michael@0: /* Return the architecture of the machine (ie. x86, mips, alpha, ...)*/ michael@0: (void)PR_snprintf(buf, buflen, _PR_SI_ARCHITECTURE); michael@0: break; michael@0: default: michael@0: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); michael@0: return PR_FAILURE; michael@0: } michael@0: return PR_SUCCESS; michael@0: } michael@0: michael@0: /* michael@0: ** PR_GetNumberOfProcessors() michael@0: ** michael@0: ** Implementation notes: michael@0: ** Every platform does it a bit different. michael@0: ** numCpus is the returned value. michael@0: ** for each platform's "if defined" section michael@0: ** declare your local variable michael@0: ** do your thing, assign to numCpus michael@0: ** order of the if defined()s may be important, michael@0: ** especially for unix variants. Do platform michael@0: ** specific implementations before XP_UNIX. michael@0: ** michael@0: */ michael@0: PR_IMPLEMENT(PRInt32) PR_GetNumberOfProcessors( void ) michael@0: { michael@0: PRInt32 numCpus; michael@0: #if defined(WIN32) michael@0: SYSTEM_INFO info; michael@0: michael@0: GetSystemInfo( &info ); michael@0: numCpus = info.dwNumberOfProcessors; michael@0: #elif defined(BEOS) michael@0: system_info sysInfo; michael@0: michael@0: get_system_info(&sysInfo); michael@0: numCpus = sysInfo.cpu_count; michael@0: #elif defined(OS2) michael@0: DosQuerySysInfo( QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &numCpus, sizeof(numCpus)); michael@0: #elif defined(_PR_HAVE_SYSCTL) michael@0: int mib[2]; michael@0: int rc; michael@0: size_t len = sizeof(numCpus); michael@0: michael@0: mib[0] = CTL_HW; michael@0: mib[1] = HW_NCPU; michael@0: rc = sysctl( mib, 2, &numCpus, &len, NULL, 0 ); michael@0: if ( -1 == rc ) { michael@0: numCpus = -1; /* set to -1 for return value on error */ michael@0: _PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() ); michael@0: } michael@0: #elif defined(HPUX) michael@0: numCpus = mpctl( MPC_GETNUMSPUS, 0, 0 ); michael@0: if ( numCpus < 1 ) { michael@0: numCpus = -1; /* set to -1 for return value on error */ michael@0: _PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() ); michael@0: } michael@0: #elif defined(IRIX) michael@0: numCpus = sysconf( _SC_NPROC_ONLN ); michael@0: #elif defined(RISCOS) || defined(SYMBIAN) michael@0: numCpus = 1; michael@0: #elif defined(LINUX) michael@0: /* for the benefit of devices with advanced power-saving, that michael@0: actually hotplug their cpus in heavy load, try to figure out michael@0: the real number of CPUs */ michael@0: char buf[MAX_LINE]; michael@0: FILE *fin; michael@0: const char *cpu_present = "/sys/devices/system/cpu/present"; michael@0: size_t strsize; michael@0: numCpus = 0; michael@0: fin = fopen(cpu_present, "r"); michael@0: if (fin != NULL) { michael@0: if (fgets(buf, MAX_LINE, fin) != NULL) { michael@0: /* check that the format is what we expect */ michael@0: if (buf[0] == '0') { michael@0: strsize = strlen(buf); michael@0: if (strsize == 1) { michael@0: /* single core */ michael@0: numCpus = 1; michael@0: } else if (strsize >= 3 && strsize <= 5) { michael@0: /* should be of the form 0-999 */ michael@0: /* parse the part after the 0-, note count is 0-based */ michael@0: if (buf[1] == '-' && isdigit(buf[2])) { michael@0: numCpus = 1 + atoi(buf + 2); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: fclose(fin); michael@0: } michael@0: /* if that fails, fall back to more standard methods */ michael@0: if (!numCpus) { michael@0: numCpus = sysconf( _SC_NPROCESSORS_CONF ); michael@0: } michael@0: #elif defined(XP_UNIX) michael@0: numCpus = sysconf( _SC_NPROCESSORS_CONF ); michael@0: #else michael@0: #error "An implementation is required" michael@0: #endif michael@0: return(numCpus); michael@0: } /* end PR_GetNumberOfProcessors() */ michael@0: michael@0: /* michael@0: ** PR_GetPhysicalMemorySize() michael@0: ** michael@0: ** Implementation notes: michael@0: ** Every platform does it a bit different. michael@0: ** bytes is the returned value. michael@0: ** for each platform's "if defined" section michael@0: ** declare your local variable michael@0: ** do your thing, assign to bytes. michael@0: ** michael@0: */ michael@0: PR_IMPLEMENT(PRUint64) PR_GetPhysicalMemorySize(void) michael@0: { michael@0: PRUint64 bytes = 0; michael@0: michael@0: #if defined(LINUX) || defined(SOLARIS) michael@0: michael@0: long pageSize = sysconf(_SC_PAGESIZE); michael@0: long pageCount = sysconf(_SC_PHYS_PAGES); michael@0: if (pageSize >= 0 && pageCount >= 0) michael@0: bytes = (PRUint64) pageSize * pageCount; michael@0: michael@0: #elif defined(NETBSD) || defined(OPENBSD) michael@0: michael@0: int mib[2]; michael@0: int rc; michael@0: uint64_t memSize; michael@0: size_t len = sizeof(memSize); michael@0: michael@0: mib[0] = CTL_HW; michael@0: mib[1] = HW_PHYSMEM64; michael@0: rc = sysctl(mib, 2, &memSize, &len, NULL, 0); michael@0: if (-1 != rc) { michael@0: bytes = memSize; michael@0: } michael@0: michael@0: #elif defined(HPUX) michael@0: michael@0: struct pst_static info; michael@0: int result = pstat_getstatic(&info, sizeof(info), 1, 0); michael@0: if (result == 1) michael@0: bytes = (PRUint64) info.physical_memory * info.page_size; michael@0: michael@0: #elif defined(DARWIN) michael@0: michael@0: mach_port_t mach_host = mach_host_self(); michael@0: struct host_basic_info hInfo; michael@0: mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; michael@0: michael@0: int result = host_info(mach_host, michael@0: HOST_BASIC_INFO, michael@0: (host_info_t) &hInfo, michael@0: &count); michael@0: mach_port_deallocate(mach_task_self(), mach_host); michael@0: if (result == KERN_SUCCESS) michael@0: bytes = hInfo.max_mem; michael@0: michael@0: #elif defined(WIN32) michael@0: michael@0: MEMORYSTATUSEX memStat; michael@0: memStat.dwLength = sizeof(memStat); michael@0: if (GlobalMemoryStatusEx(&memStat)) michael@0: bytes = memStat.ullTotalPhys; michael@0: michael@0: #elif defined(OS2) michael@0: michael@0: ULONG ulPhysMem; michael@0: DosQuerySysInfo(QSV_TOTPHYSMEM, michael@0: QSV_TOTPHYSMEM, michael@0: &ulPhysMem, michael@0: sizeof(ulPhysMem)); michael@0: bytes = ulPhysMem; michael@0: michael@0: #elif defined(AIX) michael@0: michael@0: if (odm_initialize() == 0) { michael@0: int how_many; michael@0: struct CuAt *obj = getattr("sys0", "realmem", 0, &how_many); michael@0: if (obj != NULL) { michael@0: bytes = (PRUint64) atoi(obj->value) * 1024; michael@0: free(obj); michael@0: } michael@0: odm_terminate(); michael@0: } michael@0: michael@0: #else michael@0: michael@0: PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); michael@0: michael@0: #endif michael@0: michael@0: return bytes; michael@0: } /* end PR_GetPhysicalMemorySize() */