VirtualBox

Changeset 10419 in vbox for trunk/src/VBox/Runtime/r3/linux


Ignore:
Timestamp:
Jul 9, 2008 1:46:17 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
33078
Message:

Linux implementation of the RTMp* bits we current need in ring-3.

File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/linux/mp-linux.cpp

    r10405 r10419  
    11/* $Id$ */
    22/** @file
    3  * IPRT - Multiprocessor, Windows.
     3 * IPRT - Multiprocessor, Linux.
    44 */
    55
    66/*
    7  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     7 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3434*******************************************************************************/
    3535#define LOG_GROUP RTLOGGROUP_SYSTEM
    36 #include <Windows.h>
     36#include <unistd.h>
     37#include <stdio.h>
     38#include <sys/sysctl.h>
     39#include <sys/stat.h>
     40#include <sys/fcntl.h>
     41#include <errno.h>
     42
    3743#include <iprt/mp.h>
    3844#include <iprt/cpuset.h>
    3945#include <iprt/assert.h>
     46#include <iprt/string.h>
     47
     48
     49/** @todo move the rtLinuxSysFs* bits into sysfs.cpp and sysfs.h. */
     50
     51/**
     52 * Checks if a sysfs file (or directory, device, symlink, whatever) exists.
     53 *
     54 * @returns true / false, errno is preserved.
     55 * @param   pszFormat   The name format, without "/sys/".
     56 * @param   va          The format args.
     57 */
     58bool rtLinuxSysFsExistsV(const char *pszFormat, va_list va)
     59{
     60    int iSavedErrno = errno;
     61
     62    /*
     63     * Construct the filename and call stat.
     64     */
     65    char szFilename[128];
     66    static const size_t cchPrefix = sizeof("/sys/") - 1;
     67    strcpy(szFilename, "/sys/");
     68    size_t cch = RTStrPrintfV(&szFilename[cchPrefix], sizeof(szFilename) - cchPrefix, pszFormat, va);
     69    Assert(cch < sizeof(szFilename) - cchPrefix - 1);
     70
     71    struct stat st;
     72    bool fRet = stat(szFilename, &st) == 0;
     73
     74    errno = iSavedErrno;
     75    return fRet;
     76}
     77
     78/**
     79 * Checks if a sysfs file (or directory, device, symlink, whatever) exists.
     80 *
     81 * @returns true / false, errno is preserved.
     82 * @param   pszFormat   The name format, without "/sys/".
     83 * @param   ...         The format args.
     84 */
     85bool rtLinuxSysFsExists(const char *pszFormat, ...)
     86{
     87    va_list va;
     88    va_start(va, pszFormat);
     89    bool fRet = rtLinuxSysFsExistsV(pszFormat, va);
     90    va_end(va);
     91    return fRet;
     92}
     93
     94
     95/**
     96 * Opens a sysfs file.
     97 *
     98 * @returns The file descriptor. -1 and errno on failure.
     99 * @param   pszFormat   The name format, without "/sys/".
     100 * @param   va          The format args.
     101 */
     102int rtLinuxSysFsOpenV(const char *pszFormat, va_list va)
     103{
     104    /*
     105     * Construct the filename and call open.
     106     */
     107    char szFilename[128];
     108    static const size_t cchPrefix = sizeof("/sys/") - 1;
     109    strcpy(szFilename, "/sys/");
     110    size_t cch = RTStrPrintfV(&szFilename[cchPrefix], sizeof(szFilename) - cchPrefix, pszFormat, va);
     111    Assert(cch < sizeof(szFilename) - cchPrefix - 1);
     112
     113    return open(szFilename, O_RDONLY, 0);
     114}
     115
     116
     117/**
     118 * Opens a sysfs file.
     119 *
     120 * @returns The file descriptor. -1 and errno on failure.
     121 * @param   pszFormat   The name format, without "/sys/".
     122 * @param   ...         The format args.
     123 */
     124int rtLinuxSysFsOpen(const char *pszFormat, ...)
     125{
     126    va_list va;
     127    va_start(va, pszFormat);
     128    int fd = rtLinuxSysFsOpenV(pszFormat, va);
     129    va_end(va);
     130    return fd;
     131}
     132
     133
     134/**
     135 * Closes a file opened with rtLinuxSysFsOpen or rtLinuxSysFsOpenV.
     136 *
     137 * @param   fd
     138 */
     139void rtLinuxSysFsClose(int fd)
     140{
     141    int iSavedErrno = errno;
     142    close(fd);
     143    errno = iSavedErrno;
     144}
     145
     146
     147/**
     148 * Closes a file opened with rtLinuxSysFsOpen or rtLinuxSysFsOpenV.
     149 *
     150 * @returns The number of bytes read. -1 and errno on failure.
     151 * @param   fd          The file descriptor returned by rtLinuxSysFsOpen or rtLinuxSysFsOpenV.
     152 * @param   pszBuf      Where to store the string.
     153 * @param   cchBuf      The size of the buffer. Must be at least 2 bytes.
     154 */
     155ssize_t rtLinuxSysFsReadStr(int fd, char *pszBuf, size_t cchBuf)
     156{
     157    Assert(cchBuf > 1);
     158    ssize_t cchRead = read(fd, pszBuf, cchBuf - 1);
     159    pszBuf[cchRead >= 0 ? cchRead : 0] = '\0';
     160    return cchRead;
     161}
     162
     163
     164/**
     165 * Reads a sysfs file.
     166 *
     167 * @returns 64-bit signed value on success, -1 and errno on failure.
     168 * @param   uBase       The number base, 0 for autodetect.
     169 * @param   pszFormat   The filename format, without "/sys/".
     170 * @param   va          Format args.
     171 */
     172int64_t rtLinuxSysFsReadIntFileV(unsigned uBase, const char *pszFormat, va_list va)
     173{
     174    int fd = rtLinuxSysFsOpenV(pszFormat, va);
     175    if (fd == -1)
     176        return -1;
     177
     178    int64_t i64Ret = -1;
     179    char szNum[128];
     180    ssize_t cchNum = rtLinuxSysFsReadStr(fd, szNum, sizeof(szNum));
     181    if (cchNum > 0)
     182    {
     183        int rc = RTStrToInt64Ex(szNum, NULL, uBase, &i64Ret);
     184        if (RT_FAILURE(rc))
     185        {
     186            i64Ret = -1;
     187            errno = -ETXTBSY; /* just something that won't happen at read / open. */
     188        }
     189    }
     190    else if (cchNum == 0)
     191        errno = -ETXTBSY; /* just something that won't happen at read / open. */
     192
     193    rtLinuxSysFsClose(fd);
     194    return i64Ret;
     195}
     196
     197
     198/**
     199 * Reads a sysfs file.
     200 *
     201 * @returns 64-bit signed value on success, -1 and errno on failure.
     202 * @param   uBase       The number base, 0 for autodetect.
     203 * @param   pszFormat   The filename format, without "/sys/".
     204 * @param   ...         Format args.
     205 */
     206static int64_t rtLinuxSysFsReadIntFile(unsigned uBase, const char *pszFormat, ...)
     207{
     208    va_list va;
     209    va_start(va, pszFormat);
     210    int64_t i64Ret = rtLinuxSysFsReadIntFileV(uBase, pszFormat, va);
     211    va_end(va);
     212    return i64Ret;
     213}
     214
     215
     216/**
     217 * Internal worker that determins the max possible CPU count.
     218 *
     219 * @returns Max cpus.
     220 */
     221DECLINLINE(RTCPUID) rtMpLinuxMaxCpus(void)
     222{
     223    int cMax = sysconf(_SC_NPROCESSORS_CONF);
     224    Assert(cMax >= 1);
     225    return cMax;
     226}
    40227
    41228
     
    44231RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
    45232{
    46     return idCpu < MAXIMUM_PROCESSORS ? idCpu : -1;
     233    return idCpu < rtMpLinuxMaxCpus() ? idCpu : -1;
    47234}
    48235
     
    50237RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
    51238{
    52     return (unsigned)iCpu < MAXIMUM_PROCESSORS ? iCpu : NIL_RTCPUID;
     239    return (unsigned)iCpu < rtMpLinuxMaxCpus() ? iCpu : NIL_RTCPUID;
    53240}
    54241
     
    56243RTDECL(RTCPUID) RTMpGetMaxCpuId(void)
    57244{
    58     return MAXIMUM_PROCESSORS - 1;
     245    return rtMpLinuxMaxCpus() - 1;
    59246}
    60247
     
    62249RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
    63250{
     251    /** @todo check if there is a simpler interface than this... */
     252    int i = rtLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/online", (int)idCpu);
     253    if (    i == -1
     254        &&  rtLinuxSysFsExists("devices/system/cpu/cpu%d", (int)idCpu))
     255    {
     256        Assert(!rtLinuxSysFsExists("devices/system/cpu/cpu%d/online", (int)idCpu));
     257        i = 1;
     258    }
     259
     260    Assert(i == 0 || i == -1 || i == 1);
     261    return i != 0 && i != -1;
     262}
     263
     264
     265RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
     266{
     267    /** @todo check this up with hotplugging! */
     268    return rtLinuxSysFsExists("devices/system/cpu/cpu%d", (int)idCpu);
     269}
     270
     271
     272RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
     273{
     274    RTCpuSetEmpty(pSet);
     275    RTCPUID cMax = rtMpLinuxMaxCpus();
     276    for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
     277        if (RTMpIsCpuPossible(idCpu))
     278            RTCpuSetAdd(pSet, idCpu);
     279    return pSet;
     280}
     281
     282
     283RTDECL(RTCPUID) RTMpGetCount(void)
     284{
    64285    RTCPUSET Set;
    65     return RTCpuSetIsMember(RTMpGetOnlineSet(&Set), idCpu);
    66 }
    67 
    68 
    69 RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
    70 {
    71     RTCPUSET Set;
    72     return RTCpuSetIsMember(RTMpGetSet(&Set), idCpu);
    73 }
    74 
    75 
    76 RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
    77 {
    78     RTCPUID idCpu = RTMpGetCount();
     286    RTMpGetSet(&Set);
     287    return RTCpuSetCount(&Set);
     288}
     289
     290
     291RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
     292{
    79293    RTCpuSetEmpty(pSet);
    80     while (idCpu-- > 0)
    81         RTCpuSetAdd(pSet, idCpu);
     294    RTCPUID cMax = rtMpLinuxMaxCpus();
     295    for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
     296        if (RTMpIsCpuOnline(idCpu))
     297            RTCpuSetAdd(pSet, idCpu);
    82298    return pSet;
    83 }
    84 
    85 
    86 RTDECL(RTCPUID) RTMpGetCount(void)
    87 {
    88     SYSTEM_INFO SysInfo;
    89     GetSystemInfo(&SysInfo);
    90     Assert((RTCPUID)SysInfo.dwNumberOfProcessors == SysInfo.dwNumberOfProcessors);
    91     return SysInfo.dwNumberOfProcessors;
    92 }
    93 
    94 
    95 RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
    96 {
    97     SYSTEM_INFO SysInfo;
    98     GetSystemInfo(&SysInfo);
    99     return RTCpuSetFromU64(pSet, SysInfo.dwActiveProcessorMask);
    100299}
    101300
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette