mp-linux.cpp revision 6c4e3969e6cd04ef1119bdfe2ab51e3cbedab9cb
26456d1900aba0e903e6e1beec552396618322e2vboxsync * IPRT - Multiprocessor, Linux.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Copyright (C) 2006-2008 Sun Microsystems, Inc.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
26456d1900aba0e903e6e1beec552396618322e2vboxsync * available from http://www.virtualbox.org. This file is free software;
26456d1900aba0e903e6e1beec552396618322e2vboxsync * you can redistribute it and/or modify it under the terms of the GNU
26456d1900aba0e903e6e1beec552396618322e2vboxsync * General Public License (GPL) as published by the Free Software
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
26456d1900aba0e903e6e1beec552396618322e2vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
26456d1900aba0e903e6e1beec552396618322e2vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * The contents of this file may alternatively be used under the terms
26456d1900aba0e903e6e1beec552396618322e2vboxsync * of the Common Development and Distribution License Version 1.0
26456d1900aba0e903e6e1beec552396618322e2vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
26456d1900aba0e903e6e1beec552396618322e2vboxsync * VirtualBox OSE distribution, in which case the provisions of the
26456d1900aba0e903e6e1beec552396618322e2vboxsync * CDDL are applicable instead of those of the GPL.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * You may elect to license modified versions of this file under the
26456d1900aba0e903e6e1beec552396618322e2vboxsync * terms and conditions of either the GPL or the CDDL or both.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
26456d1900aba0e903e6e1beec552396618322e2vboxsync * additional information or have any questions.
26456d1900aba0e903e6e1beec552396618322e2vboxsync/*******************************************************************************
26456d1900aba0e903e6e1beec552396618322e2vboxsync* Header Files *
26456d1900aba0e903e6e1beec552396618322e2vboxsync*******************************************************************************/
26456d1900aba0e903e6e1beec552396618322e2vboxsync/** @todo move the rtLinuxSysFs* bits into sysfs.cpp and sysfs.h. */
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Checks if a sysfs file (or directory, device, symlink, whatever) exists.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns true / false, errno is preserved.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param pszFormat The name format, without "/sys/".
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param va The format args.
26456d1900aba0e903e6e1beec552396618322e2vboxsyncbool rtLinuxSysFsExistsV(const char *pszFormat, va_list va)
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Construct the filename and call stat.
26456d1900aba0e903e6e1beec552396618322e2vboxsync static const size_t cchPrefix = sizeof("/sys/") - 1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync size_t cch = RTStrPrintfV(&szFilename[cchPrefix], sizeof(szFilename) - cchPrefix, pszFormat, va);
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Checks if a sysfs file (or directory, device, symlink, whatever) exists.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns true / false, errno is preserved.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param pszFormat The name format, without "/sys/".
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param ... The format args.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Opens a sysfs file.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns The file descriptor. -1 and errno on failure.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param pszFormat The name format, without "/sys/".
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param va The format args.
26456d1900aba0e903e6e1beec552396618322e2vboxsyncint rtLinuxSysFsOpenV(const char *pszFormat, va_list va)
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Construct the filename and call open.
26456d1900aba0e903e6e1beec552396618322e2vboxsync static const size_t cchPrefix = sizeof("/sys/") - 1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync size_t cch = RTStrPrintfV(&szFilename[cchPrefix], sizeof(szFilename) - cchPrefix, pszFormat, va);
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Opens a sysfs file.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns The file descriptor. -1 and errno on failure.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param pszFormat The name format, without "/sys/".
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param ... The format args.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Closes a file opened with rtLinuxSysFsOpen or rtLinuxSysFsOpenV.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param fd
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Closes a file opened with rtLinuxSysFsOpen or rtLinuxSysFsOpenV.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns The number of bytes read. -1 and errno on failure.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param fd The file descriptor returned by rtLinuxSysFsOpen or rtLinuxSysFsOpenV.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param pszBuf Where to store the string.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param cchBuf The size of the buffer. Must be at least 2 bytes.
26456d1900aba0e903e6e1beec552396618322e2vboxsyncssize_t rtLinuxSysFsReadStr(int fd, char *pszBuf, size_t cchBuf)
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Reads a sysfs file.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns 64-bit signed value on success, -1 and errno on failure.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param uBase The number base, 0 for autodetect.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param pszFormat The filename format, without "/sys/".
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param va Format args.
26456d1900aba0e903e6e1beec552396618322e2vboxsyncint64_t rtLinuxSysFsReadIntFileV(unsigned uBase, const char *pszFormat, va_list va)
26456d1900aba0e903e6e1beec552396618322e2vboxsync ssize_t cchNum = rtLinuxSysFsReadStr(fd, szNum, sizeof(szNum));
26456d1900aba0e903e6e1beec552396618322e2vboxsync int rc = RTStrToInt64Ex(szNum, NULL, uBase, &i64Ret);
26456d1900aba0e903e6e1beec552396618322e2vboxsync errno = -ETXTBSY; /* just something that won't happen at read / open. */
26456d1900aba0e903e6e1beec552396618322e2vboxsync else if (cchNum == 0)
26456d1900aba0e903e6e1beec552396618322e2vboxsync errno = -ETXTBSY; /* just something that won't happen at read / open. */
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Reads a sysfs file.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns 64-bit signed value on success, -1 and errno on failure.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param uBase The number base, 0 for autodetect.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param pszFormat The filename format, without "/sys/".
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param ... Format args.
26456d1900aba0e903e6e1beec552396618322e2vboxsyncstatic int64_t rtLinuxSysFsReadIntFile(unsigned uBase, const char *pszFormat, ...)
26456d1900aba0e903e6e1beec552396618322e2vboxsync int64_t i64Ret = rtLinuxSysFsReadIntFileV(uBase, pszFormat, va);
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Internal worker that determins the max possible CPU count.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns Max cpus.
26456d1900aba0e903e6e1beec552396618322e2vboxsync#if 0 /* this doesn't do the right thing :-/ */
26456d1900aba0e903e6e1beec552396618322e2vboxsync for (unsigned iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++)
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (rtLinuxSysFsExists("devices/system/cpu/cpu%d", iCpu))
26456d1900aba0e903e6e1beec552396618322e2vboxsync ASMAtomicUoWriteU32((uint32_t volatile *)&s_cMax, cMax);
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Internal worker that picks the processor speed in MHz from /proc/cpuinfo.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns CPU frequency.
26456d1900aba0e903e6e1beec552396618322e2vboxsyncstatic uint32_t rtMpLinuxGetFrequency(RTCPUID idCpu)
26456d1900aba0e903e6e1beec552396618322e2vboxsync && (sz[10] == ' ' || sz[10] == '\t' || sz[10] == ':')
26456d1900aba0e903e6e1beec552396618322e2vboxsync && (sz[10] == ' ' || sz[10] == '\t' || sz[10] == ':')
26456d1900aba0e903e6e1beec552396618322e2vboxsync/** @todo RTmpCpuId(). */
26456d1900aba0e903e6e1beec552396618322e2vboxsync return (unsigned)iCpu < rtMpLinuxMaxCpus() ? iCpu : NIL_RTCPUID;
26456d1900aba0e903e6e1beec552396618322e2vboxsync /** @todo check if there is a simpler interface than this... */
26456d1900aba0e903e6e1beec552396618322e2vboxsync int i = rtLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/online", (int)idCpu);
26456d1900aba0e903e6e1beec552396618322e2vboxsync if ( i == -1
26456d1900aba0e903e6e1beec552396618322e2vboxsync && rtLinuxSysFsExists("devices/system/cpu/cpu%d", (int)idCpu))
26456d1900aba0e903e6e1beec552396618322e2vboxsync Assert(!rtLinuxSysFsExists("devices/system/cpu/cpu%d/online", (int)idCpu));
26456d1900aba0e903e6e1beec552396618322e2vboxsync return i != 0 && i != -1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync /** @todo check this up with hotplugging! */
26456d1900aba0e903e6e1beec552396618322e2vboxsync return rtLinuxSysFsExists("devices/system/cpu/cpu%d", (int)idCpu);
26456d1900aba0e903e6e1beec552396618322e2vboxsync int64_t kHz = rtLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/cpufreq/cpuinfo_cur_freq", (int)idCpu);
26456d1900aba0e903e6e1beec552396618322e2vboxsync /* The file may be just unreadable - in that case use plan B, i.e.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * /proc/cpuinfo to get the data we want. The assumption is that if
26456d1900aba0e903e6e1beec552396618322e2vboxsync * cpuinfo_cur_freq doesn't exist then the speed won't change, and
26456d1900aba0e903e6e1beec552396618322e2vboxsync * thus cur == max. If it does exist then cpuinfo contains the
26456d1900aba0e903e6e1beec552396618322e2vboxsync * current frequency. */
26456d1900aba0e903e6e1beec552396618322e2vboxsync int64_t kHz = rtLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", (int)idCpu);
26456d1900aba0e903e6e1beec552396618322e2vboxsync /* Check if the file isn't there - if it is there, then /proc/cpuinfo
26456d1900aba0e903e6e1beec552396618322e2vboxsync * would provide current frequency information, which is wrong. */