mp-linux.cpp revision 6c4e3969e6cd04ef1119bdfe2ab51e3cbedab9cb
26456d1900aba0e903e6e1beec552396618322e2vboxsync/* $Id$ */
26456d1900aba0e903e6e1beec552396618322e2vboxsync/** @file
26456d1900aba0e903e6e1beec552396618322e2vboxsync * IPRT - Multiprocessor, Linux.
26456d1900aba0e903e6e1beec552396618322e2vboxsync */
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/*
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Copyright (C) 2006-2008 Sun Microsystems, Inc.
26456d1900aba0e903e6e1beec552396618322e2vboxsync *
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 *
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 *
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 *
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
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/*******************************************************************************
26456d1900aba0e903e6e1beec552396618322e2vboxsync* Header Files *
26456d1900aba0e903e6e1beec552396618322e2vboxsync*******************************************************************************/
26456d1900aba0e903e6e1beec552396618322e2vboxsync#define LOG_GROUP RTLOGGROUP_SYSTEM
26456d1900aba0e903e6e1beec552396618322e2vboxsync#include <unistd.h>
26456d1900aba0e903e6e1beec552396618322e2vboxsync#include <stdio.h>
26456d1900aba0e903e6e1beec552396618322e2vboxsync#include <sys/sysctl.h>
26456d1900aba0e903e6e1beec552396618322e2vboxsync#include <sys/stat.h>
26456d1900aba0e903e6e1beec552396618322e2vboxsync#include <sys/fcntl.h>
26456d1900aba0e903e6e1beec552396618322e2vboxsync#include <errno.h>
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync#include <iprt/mp.h>
26456d1900aba0e903e6e1beec552396618322e2vboxsync#include <iprt/cpuset.h>
26456d1900aba0e903e6e1beec552396618322e2vboxsync#include <iprt/assert.h>
26456d1900aba0e903e6e1beec552396618322e2vboxsync#include <iprt/string.h>
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/** @todo move the rtLinuxSysFs* bits into sysfs.cpp and sysfs.h. */
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/**
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Checks if a sysfs file (or directory, device, symlink, whatever) exists.
26456d1900aba0e903e6e1beec552396618322e2vboxsync *
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns true / false, errno is preserved.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param pszFormat The name format, without "/sys/".
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param va The format args.
26456d1900aba0e903e6e1beec552396618322e2vboxsync */
26456d1900aba0e903e6e1beec552396618322e2vboxsyncbool rtLinuxSysFsExistsV(const char *pszFormat, va_list va)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync int iSavedErrno = errno;
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync /*
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Construct the filename and call stat.
26456d1900aba0e903e6e1beec552396618322e2vboxsync */
26456d1900aba0e903e6e1beec552396618322e2vboxsync char szFilename[128];
26456d1900aba0e903e6e1beec552396618322e2vboxsync static const size_t cchPrefix = sizeof("/sys/") - 1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync strcpy(szFilename, "/sys/");
26456d1900aba0e903e6e1beec552396618322e2vboxsync size_t cch = RTStrPrintfV(&szFilename[cchPrefix], sizeof(szFilename) - cchPrefix, pszFormat, va);
26456d1900aba0e903e6e1beec552396618322e2vboxsync Assert(cch < sizeof(szFilename) - cchPrefix - 1);
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync struct stat st;
26456d1900aba0e903e6e1beec552396618322e2vboxsync bool fRet = stat(szFilename, &st) == 0;
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync errno = iSavedErrno;
26456d1900aba0e903e6e1beec552396618322e2vboxsync return fRet;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/**
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Checks if a sysfs file (or directory, device, symlink, whatever) exists.
26456d1900aba0e903e6e1beec552396618322e2vboxsync *
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns true / false, errno is preserved.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param pszFormat The name format, without "/sys/".
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param ... The format args.
26456d1900aba0e903e6e1beec552396618322e2vboxsync */
26456d1900aba0e903e6e1beec552396618322e2vboxsyncbool rtLinuxSysFsExists(const char *pszFormat, ...)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync va_list va;
26456d1900aba0e903e6e1beec552396618322e2vboxsync va_start(va, pszFormat);
26456d1900aba0e903e6e1beec552396618322e2vboxsync bool fRet = rtLinuxSysFsExistsV(pszFormat, va);
26456d1900aba0e903e6e1beec552396618322e2vboxsync va_end(va);
26456d1900aba0e903e6e1beec552396618322e2vboxsync return fRet;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/**
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Opens a sysfs file.
26456d1900aba0e903e6e1beec552396618322e2vboxsync *
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns The file descriptor. -1 and errno on failure.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param pszFormat The name format, without "/sys/".
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param va The format args.
26456d1900aba0e903e6e1beec552396618322e2vboxsync */
26456d1900aba0e903e6e1beec552396618322e2vboxsyncint rtLinuxSysFsOpenV(const char *pszFormat, va_list va)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync /*
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Construct the filename and call open.
26456d1900aba0e903e6e1beec552396618322e2vboxsync */
26456d1900aba0e903e6e1beec552396618322e2vboxsync char szFilename[128];
26456d1900aba0e903e6e1beec552396618322e2vboxsync static const size_t cchPrefix = sizeof("/sys/") - 1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync strcpy(szFilename, "/sys/");
26456d1900aba0e903e6e1beec552396618322e2vboxsync size_t cch = RTStrPrintfV(&szFilename[cchPrefix], sizeof(szFilename) - cchPrefix, pszFormat, va);
26456d1900aba0e903e6e1beec552396618322e2vboxsync Assert(cch < sizeof(szFilename) - cchPrefix - 1);
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync return open(szFilename, O_RDONLY, 0);
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/**
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Opens a sysfs file.
26456d1900aba0e903e6e1beec552396618322e2vboxsync *
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns The file descriptor. -1 and errno on failure.
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param pszFormat The name format, without "/sys/".
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param ... The format args.
26456d1900aba0e903e6e1beec552396618322e2vboxsync */
26456d1900aba0e903e6e1beec552396618322e2vboxsyncint rtLinuxSysFsOpen(const char *pszFormat, ...)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync va_list va;
26456d1900aba0e903e6e1beec552396618322e2vboxsync va_start(va, pszFormat);
26456d1900aba0e903e6e1beec552396618322e2vboxsync int fd = rtLinuxSysFsOpenV(pszFormat, va);
26456d1900aba0e903e6e1beec552396618322e2vboxsync va_end(va);
26456d1900aba0e903e6e1beec552396618322e2vboxsync return fd;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/**
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Closes a file opened with rtLinuxSysFsOpen or rtLinuxSysFsOpenV.
26456d1900aba0e903e6e1beec552396618322e2vboxsync *
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @param fd
26456d1900aba0e903e6e1beec552396618322e2vboxsync */
26456d1900aba0e903e6e1beec552396618322e2vboxsyncvoid rtLinuxSysFsClose(int fd)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync int iSavedErrno = errno;
26456d1900aba0e903e6e1beec552396618322e2vboxsync close(fd);
26456d1900aba0e903e6e1beec552396618322e2vboxsync errno = iSavedErrno;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/**
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Closes a file opened with rtLinuxSysFsOpen or rtLinuxSysFsOpenV.
26456d1900aba0e903e6e1beec552396618322e2vboxsync *
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.
26456d1900aba0e903e6e1beec552396618322e2vboxsync */
26456d1900aba0e903e6e1beec552396618322e2vboxsyncssize_t rtLinuxSysFsReadStr(int fd, char *pszBuf, size_t cchBuf)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync Assert(cchBuf > 1);
26456d1900aba0e903e6e1beec552396618322e2vboxsync ssize_t cchRead = read(fd, pszBuf, cchBuf - 1);
26456d1900aba0e903e6e1beec552396618322e2vboxsync pszBuf[cchRead >= 0 ? cchRead : 0] = '\0';
26456d1900aba0e903e6e1beec552396618322e2vboxsync return cchRead;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/**
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Reads a sysfs file.
26456d1900aba0e903e6e1beec552396618322e2vboxsync *
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.
26456d1900aba0e903e6e1beec552396618322e2vboxsync */
26456d1900aba0e903e6e1beec552396618322e2vboxsyncint64_t rtLinuxSysFsReadIntFileV(unsigned uBase, const char *pszFormat, va_list va)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync int fd = rtLinuxSysFsOpenV(pszFormat, va);
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (fd == -1)
26456d1900aba0e903e6e1beec552396618322e2vboxsync return -1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync int64_t i64Ret = -1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync char szNum[128];
26456d1900aba0e903e6e1beec552396618322e2vboxsync ssize_t cchNum = rtLinuxSysFsReadStr(fd, szNum, sizeof(szNum));
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (cchNum > 0)
26456d1900aba0e903e6e1beec552396618322e2vboxsync {
26456d1900aba0e903e6e1beec552396618322e2vboxsync int rc = RTStrToInt64Ex(szNum, NULL, uBase, &i64Ret);
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (RT_FAILURE(rc))
26456d1900aba0e903e6e1beec552396618322e2vboxsync {
26456d1900aba0e903e6e1beec552396618322e2vboxsync i64Ret = -1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync errno = -ETXTBSY; /* just something that won't happen at read / open. */
26456d1900aba0e903e6e1beec552396618322e2vboxsync }
26456d1900aba0e903e6e1beec552396618322e2vboxsync }
26456d1900aba0e903e6e1beec552396618322e2vboxsync else if (cchNum == 0)
26456d1900aba0e903e6e1beec552396618322e2vboxsync errno = -ETXTBSY; /* just something that won't happen at read / open. */
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync rtLinuxSysFsClose(fd);
26456d1900aba0e903e6e1beec552396618322e2vboxsync return i64Ret;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/**
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Reads a sysfs file.
26456d1900aba0e903e6e1beec552396618322e2vboxsync *
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.
26456d1900aba0e903e6e1beec552396618322e2vboxsync */
26456d1900aba0e903e6e1beec552396618322e2vboxsyncstatic int64_t rtLinuxSysFsReadIntFile(unsigned uBase, const char *pszFormat, ...)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync va_list va;
26456d1900aba0e903e6e1beec552396618322e2vboxsync va_start(va, pszFormat);
26456d1900aba0e903e6e1beec552396618322e2vboxsync int64_t i64Ret = rtLinuxSysFsReadIntFileV(uBase, pszFormat, va);
26456d1900aba0e903e6e1beec552396618322e2vboxsync va_end(va);
26456d1900aba0e903e6e1beec552396618322e2vboxsync return i64Ret;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/**
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Internal worker that determins the max possible CPU count.
26456d1900aba0e903e6e1beec552396618322e2vboxsync *
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns Max cpus.
26456d1900aba0e903e6e1beec552396618322e2vboxsync */
26456d1900aba0e903e6e1beec552396618322e2vboxsyncstatic RTCPUID rtMpLinuxMaxCpus(void)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync#if 0 /* this doesn't do the right thing :-/ */
26456d1900aba0e903e6e1beec552396618322e2vboxsync int cMax = sysconf(_SC_NPROCESSORS_CONF);
26456d1900aba0e903e6e1beec552396618322e2vboxsync Assert(cMax >= 1);
26456d1900aba0e903e6e1beec552396618322e2vboxsync return cMax;
26456d1900aba0e903e6e1beec552396618322e2vboxsync#else
26456d1900aba0e903e6e1beec552396618322e2vboxsync static uint32_t s_cMax = 0;
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (!s_cMax)
26456d1900aba0e903e6e1beec552396618322e2vboxsync {
26456d1900aba0e903e6e1beec552396618322e2vboxsync int cMax = 1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync for (unsigned iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++)
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (rtLinuxSysFsExists("devices/system/cpu/cpu%d", iCpu))
26456d1900aba0e903e6e1beec552396618322e2vboxsync cMax = iCpu + 1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync ASMAtomicUoWriteU32((uint32_t volatile *)&s_cMax, cMax);
26456d1900aba0e903e6e1beec552396618322e2vboxsync return cMax;
26456d1900aba0e903e6e1beec552396618322e2vboxsync }
26456d1900aba0e903e6e1beec552396618322e2vboxsync return s_cMax;
26456d1900aba0e903e6e1beec552396618322e2vboxsync#endif
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/**
26456d1900aba0e903e6e1beec552396618322e2vboxsync * Internal worker that picks the processor speed in MHz from /proc/cpuinfo.
26456d1900aba0e903e6e1beec552396618322e2vboxsync *
26456d1900aba0e903e6e1beec552396618322e2vboxsync * @returns CPU frequency.
26456d1900aba0e903e6e1beec552396618322e2vboxsync */
26456d1900aba0e903e6e1beec552396618322e2vboxsyncstatic uint32_t rtMpLinuxGetFrequency(RTCPUID idCpu)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync FILE *f = fopen("/proc/cpuinfo", "r");
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (!f)
26456d1900aba0e903e6e1beec552396618322e2vboxsync return 0;
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync char sz[256];
26456d1900aba0e903e6e1beec552396618322e2vboxsync char *psz = NULL;
26456d1900aba0e903e6e1beec552396618322e2vboxsync RTCPUID idCpuFound = NIL_RTCPUID;
26456d1900aba0e903e6e1beec552396618322e2vboxsync uint32_t freq = 0;
26456d1900aba0e903e6e1beec552396618322e2vboxsync while (fgets(sz, sizeof(sz), f))
26456d1900aba0e903e6e1beec552396618322e2vboxsync {
26456d1900aba0e903e6e1beec552396618322e2vboxsync if ( !strncmp(sz, "processor", 9)
26456d1900aba0e903e6e1beec552396618322e2vboxsync && (sz[10] == ' ' || sz[10] == '\t' || sz[10] == ':')
26456d1900aba0e903e6e1beec552396618322e2vboxsync && (psz = strchr(sz, ':')))
26456d1900aba0e903e6e1beec552396618322e2vboxsync {
26456d1900aba0e903e6e1beec552396618322e2vboxsync psz += 2;
26456d1900aba0e903e6e1beec552396618322e2vboxsync int64_t iCpu;
26456d1900aba0e903e6e1beec552396618322e2vboxsync int rc = RTStrToInt64Ex(psz, NULL, 0, &iCpu);
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (RT_SUCCESS(rc))
26456d1900aba0e903e6e1beec552396618322e2vboxsync idCpuFound = iCpu;
26456d1900aba0e903e6e1beec552396618322e2vboxsync }
26456d1900aba0e903e6e1beec552396618322e2vboxsync else if ( idCpu == idCpuFound
26456d1900aba0e903e6e1beec552396618322e2vboxsync && !strncmp(sz, "cpu MHz", 7)
26456d1900aba0e903e6e1beec552396618322e2vboxsync && (sz[10] == ' ' || sz[10] == '\t' || sz[10] == ':')
26456d1900aba0e903e6e1beec552396618322e2vboxsync && (psz = strchr(sz, ':')))
26456d1900aba0e903e6e1beec552396618322e2vboxsync {
26456d1900aba0e903e6e1beec552396618322e2vboxsync psz += 2;
26456d1900aba0e903e6e1beec552396618322e2vboxsync int64_t v;
26456d1900aba0e903e6e1beec552396618322e2vboxsync int rc = RTStrToInt64Ex(psz, &psz, 0, &v);
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (RT_SUCCESS(rc))
26456d1900aba0e903e6e1beec552396618322e2vboxsync {
26456d1900aba0e903e6e1beec552396618322e2vboxsync freq = v;
26456d1900aba0e903e6e1beec552396618322e2vboxsync break;
26456d1900aba0e903e6e1beec552396618322e2vboxsync }
26456d1900aba0e903e6e1beec552396618322e2vboxsync }
26456d1900aba0e903e6e1beec552396618322e2vboxsync }
26456d1900aba0e903e6e1beec552396618322e2vboxsync fclose(f);
26456d1900aba0e903e6e1beec552396618322e2vboxsync return freq;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync/** @todo RTmpCpuId(). */
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsyncRTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync return idCpu < rtMpLinuxMaxCpus() ? idCpu : -1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsyncRTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync return (unsigned)iCpu < rtMpLinuxMaxCpus() ? iCpu : NIL_RTCPUID;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsyncRTDECL(RTCPUID) RTMpGetMaxCpuId(void)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync return rtMpLinuxMaxCpus() - 1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsyncRTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
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 {
26456d1900aba0e903e6e1beec552396618322e2vboxsync Assert(!rtLinuxSysFsExists("devices/system/cpu/cpu%d/online", (int)idCpu));
26456d1900aba0e903e6e1beec552396618322e2vboxsync i = 1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync }
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync Assert(i == 0 || i == -1 || i == 1);
26456d1900aba0e903e6e1beec552396618322e2vboxsync return i != 0 && i != -1;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsyncRTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync /** @todo check this up with hotplugging! */
26456d1900aba0e903e6e1beec552396618322e2vboxsync return rtLinuxSysFsExists("devices/system/cpu/cpu%d", (int)idCpu);
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsyncRTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync RTCpuSetEmpty(pSet);
26456d1900aba0e903e6e1beec552396618322e2vboxsync RTCPUID cMax = rtMpLinuxMaxCpus();
26456d1900aba0e903e6e1beec552396618322e2vboxsync for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (RTMpIsCpuPossible(idCpu))
26456d1900aba0e903e6e1beec552396618322e2vboxsync RTCpuSetAdd(pSet, idCpu);
26456d1900aba0e903e6e1beec552396618322e2vboxsync return pSet;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsyncRTDECL(RTCPUID) RTMpGetCount(void)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync RTCPUSET Set;
26456d1900aba0e903e6e1beec552396618322e2vboxsync RTMpGetSet(&Set);
26456d1900aba0e903e6e1beec552396618322e2vboxsync return RTCpuSetCount(&Set);
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsyncRTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync RTCpuSetEmpty(pSet);
26456d1900aba0e903e6e1beec552396618322e2vboxsync RTCPUID cMax = rtMpLinuxMaxCpus();
26456d1900aba0e903e6e1beec552396618322e2vboxsync for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (RTMpIsCpuOnline(idCpu))
26456d1900aba0e903e6e1beec552396618322e2vboxsync RTCpuSetAdd(pSet, idCpu);
26456d1900aba0e903e6e1beec552396618322e2vboxsync return pSet;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsyncRTDECL(RTCPUID) RTMpGetOnlineCount(void)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync RTCPUSET Set;
26456d1900aba0e903e6e1beec552396618322e2vboxsync RTMpGetOnlineSet(&Set);
26456d1900aba0e903e6e1beec552396618322e2vboxsync return RTCpuSetCount(&Set);
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsyncRTDECL(uint32_t) RTMpGetCurFrequency(RTCPUID idCpu)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync int64_t kHz = rtLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/cpufreq/cpuinfo_cur_freq", (int)idCpu);
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (kHz == -1)
26456d1900aba0e903e6e1beec552396618322e2vboxsync {
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 kHz = rtMpLinuxGetFrequency(idCpu) * 1000;
26456d1900aba0e903e6e1beec552396618322e2vboxsync }
26456d1900aba0e903e6e1beec552396618322e2vboxsync return (kHz + 999) / 1000;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsync
26456d1900aba0e903e6e1beec552396618322e2vboxsyncRTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu)
26456d1900aba0e903e6e1beec552396618322e2vboxsync{
26456d1900aba0e903e6e1beec552396618322e2vboxsync int64_t kHz = rtLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", (int)idCpu);
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (kHz == -1)
26456d1900aba0e903e6e1beec552396618322e2vboxsync {
26456d1900aba0e903e6e1beec552396618322e2vboxsync /* Check if the file isn't there - if it is there, then /proc/cpuinfo
26456d1900aba0e903e6e1beec552396618322e2vboxsync * would provide current frequency information, which is wrong. */
26456d1900aba0e903e6e1beec552396618322e2vboxsync if (!rtLinuxSysFsExists("devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", (int)idCpu))
26456d1900aba0e903e6e1beec552396618322e2vboxsync kHz = rtMpLinuxGetFrequency(idCpu) * 1000;
26456d1900aba0e903e6e1beec552396618322e2vboxsync else
26456d1900aba0e903e6e1beec552396618322e2vboxsync kHz = 0;
26456d1900aba0e903e6e1beec552396618322e2vboxsync }
26456d1900aba0e903e6e1beec552396618322e2vboxsync return (kHz + 999) / 1000;
26456d1900aba0e903e6e1beec552396618322e2vboxsync}
26456d1900aba0e903e6e1beec552396618322e2vboxsync