VirtualBox

Changeset 10419 in vbox


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.

Location:
trunk/src/VBox/Runtime
Files:
2 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/Makefile.kmk

    r10418 r10419  
    321321        generic/RTMpGetCurFrequency-generic.cpp \
    322322        generic/RTMpGetMaxFrequency-generic.cpp \
     323        r3/linux/mp-linux.cpp \
    323324        r3/linux/sched-linux.cpp \
    324325        r3/linux/time-linux.cpp \
     
    333334        r3/posix/process-posix.cpp \
    334335        r3/posix/rand-posix.cpp \
    335         r3/posix/RTMpGetCount-posix.cpp \
    336336        r3/posix/RTTimeNow-posix.cpp \
    337337        r3/posix/semrw-posix.cpp \
  • 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
  • trunk/src/VBox/Runtime/testcase/Makefile.kmk

    r10048 r10419  
    7272        tstLog \
    7373        tstMove \
     74        tstMp-1 \
    7475        tstNoCrt-1 \
    7576        tstPath \
     
    246247tstMove_SOURCES = tstMove.cpp
    247248
     249tstMp-1_SOURCES = tstMp-1.cpp
     250
    248251tstNoCrt-1_DEFS = RT_WITHOUT_NOCRT_WRAPPER_ALIASES
    249252tstNoCrt-1_SOURCES = \
  • trunk/src/VBox/Runtime/testcase/tstMp-1.cpp

    r10405 r10419  
    11/* $Id$ */
    22/** @file
    3  * IPRT Testcase - IPv4.
     3 * IPRT Testcase - RTMp.
    44 */
    55
     
    3333*   Header Files                                                               *
    3434*******************************************************************************/
    35 #include <iprt/cidr.h>
     35#include <iprt/mp.h>
     36#include <iprt/cpuset.h>
    3637#include <iprt/err.h>
    3738#include <iprt/stream.h>
     
    4243*   Defined Constants And Macros                                               *
    4344*******************************************************************************/
    44 #define CHECKNETWORK(string, expected_result, expected_network, expected_netmask) \
    45     do { \
    46         RTIPV4ADDR network, netmask; \
    47         int result = RTCidrStrToIPv4(string, &network, &netmask); \
    48         if (expected_result && !result) \
    49         { \
    50             g_cErrors++; \
    51             RTPrintf("%s, %d: %s: expected %Vrc got %Vrc\n", \
    52                     __FUNCTION__, __LINE__, string, expected_result, result); \
    53         } \
    54         else if (   expected_result != result \
    55                  || (   result == VINF_SUCCESS \
    56                      && (   expected_network != network \
    57                          || expected_netmask != netmask))) \
    58         { \
    59             g_cErrors++; \
    60             RTPrintf("%s, %d: '%s': expected %Vrc got %Vrc, expected network %08x got %08x, expected netmask %08x got %08x\n", \
    61                     __FUNCTION__, __LINE__, string, expected_result, result, expected_network, network, expected_netmask, netmask); \
    62         } \
    63     } while (0)
    64 
    6545
    6646/*******************************************************************************
     
    7353{
    7454    RTR3Init();
    75     CHECKNETWORK("10.0.0/24",                VINF_SUCCESS, 0x0A000000, 0xFFFFFF00);
    76     CHECKNETWORK("10.0.0/8",                 VINF_SUCCESS, 0x0A000000, 0xFF000000);
    77     CHECKNETWORK("10.0.0./24",     VERR_INVALID_PARAMETER,          0,          0);
    78     CHECKNETWORK("0.1.0/24",       VERR_INVALID_PARAMETER,          0,          0);
    79     CHECKNETWORK("10.255.0.0/24",  VERR_INVALID_PARAMETER,          0,          0);
    80     CHECKNETWORK("10.1234.0.0/24", VERR_INVALID_PARAMETER,          0,          0);
    81     CHECKNETWORK("10.256.0.0/24",  VERR_INVALID_PARAMETER,          0,          0);
    82     CHECKNETWORK("10.0.0/3",       VERR_INVALID_PARAMETER,          0,          0);
    83     CHECKNETWORK("10.1.2.3/8",               VINF_SUCCESS, 0x0A010203, 0xFF000000);
    84     CHECKNETWORK("10.0.0/29",      VERR_INVALID_PARAMETER,          0,          0);
    85     CHECKNETWORK("10.0.0/240",     VERR_INVALID_PARAMETER,          0,          0);
    86     CHECKNETWORK("10.0.0/24.",     VERR_INVALID_PARAMETER,          0,          0);
    87     CHECKNETWORK("10.1.2/16",                VINF_SUCCESS, 0x0A010200, 0xFFFF0000);
    88     CHECKNETWORK("1.2.3.4",                  VINF_SUCCESS, 0x01020304, 0xFFFFFFFF);
     55    RTPrintf("tstMp-1: TESTING...\n");
     56
     57#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) || defined(RT_OS_LINUX)
     58    /*
     59     * Present and possible CPUs.
     60     */
     61    RTCPUID cCpus = RTMpGetCount();
     62    if (cCpus > 0)
     63        RTPrintf("tstMp-1: RTMpGetCount -> %d\n", (int)cCpus);
     64    else
     65    {
     66        RTPrintf("tstMp-1: FAILURE: RTMpGetCount -> %d\n", (int)cCpus);
     67        g_cErrors++;
     68        cCpus = 1;
     69    }
     70
     71    RTCPUSET Set;
     72    PRTCPUSET pSet = RTMpGetSet(&Set);
     73    if (pSet == &Set)
     74    {
     75        if ((RTCPUID)RTCpuSetCount(&Set) != cCpus)
     76        {
     77            RTPrintf("tstMp-1: FAILURE: RTMpGetSet returned a set with a different cpu count; %d, expected %d\n",
     78                     RTCpuSetCount(&Set), cCpus);
     79            g_cErrors++;
     80        }
     81        RTPrintf("tstMp-1: Possible CPU mask:\n");
     82        for (int iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++)
     83        {
     84            if (RTCpuSetIsMemberByIndex(&Set, iCpu))
     85            {
     86                RTPrintf("tstMp-1: %2d - id %d\n", iCpu, RTMpCpuIdFromSetIndex(iCpu));
     87                if (!RTMpIsCpuPossible(RTMpCpuIdFromSetIndex(iCpu)))
     88                {
     89                    RTPrintf("tstMp-1: FAILURE: Cpu with index %d is returned by RTCpuSet but not RTMpIsCpuPossible!\n", iCpu);
     90                    g_cErrors++;
     91                }
     92            }
     93            else if (RTMpIsCpuPossible(RTMpCpuIdFromSetIndex(iCpu)))
     94            {
     95                RTPrintf("tstMp-1: FAILURE: Cpu with index %d is returned by RTMpIsCpuPossible but not RTCpuSet!\n", iCpu);
     96                g_cErrors++;
     97            }
     98        }
     99    }
     100    else
     101    {
     102        RTPrintf("tstMp-1: FAILURE: RTMpGetSet -> %p, expected %p\n", pSet, &Set);
     103        g_cErrors++;
     104        RTCpuSetEmpty(&Set);
     105        RTCpuSetAdd(&Set, RTMpCpuIdFromSetIndex(0));
     106    }
     107
     108    /*
     109     * Online CPUs.
     110     */
     111    RTCPUID cCpusOnline = RTMpGetOnlineCount();
     112    if (cCpusOnline > 0)
     113    {
     114        if (cCpusOnline <= cCpus)
     115            RTPrintf("tstMp-1: RTMpGetOnlineCount -> %d\n", (int)cCpusOnline);
     116        else
     117        {
     118            RTPrintf("tstMp-1: FAILURE: RTMpGetOnlineCount -> %d, expected <= %d\n", (int)cCpusOnline, (int)cCpus);
     119            g_cErrors++;
     120            cCpusOnline = cCpus;
     121        }
     122    }
     123    else
     124    {
     125        RTPrintf("tstMp-1: FAILURE: RTMpGetOnlineCount -> %d\n", (int)cCpusOnline);
     126        g_cErrors++;
     127        cCpusOnline = 1;
     128    }
     129
     130    RTCPUSET SetOnline;
     131    pSet = RTMpGetOnlineSet(&SetOnline);
     132    if (pSet == &SetOnline)
     133    {
     134        if (RTCpuSetCount(&SetOnline) <= 0)
     135        {
     136            RTPrintf("tstMp-1: FAILURE: RTMpGetOnlineSet returned an empty set!\n");
     137            g_cErrors++;
     138        }
     139        else if ((RTCPUID)RTCpuSetCount(&SetOnline) > cCpus)
     140        {
     141            RTPrintf("tstMp-1: FAILURE: RTMpGetOnlineSet returned a too high value; %d, expected <= %d\n",
     142                     RTCpuSetCount(&SetOnline), cCpus);
     143            g_cErrors++;
     144        }
     145        RTPrintf("tstMp-1: Online CPU mask:\n");
     146        for (int iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++)
     147            if (RTCpuSetIsMemberByIndex(&SetOnline, iCpu))
     148            {
     149                RTPrintf("tstMp-1: %2d - id %d\n", iCpu, RTMpCpuIdFromSetIndex(iCpu));
     150                if (!RTCpuSetIsMemberByIndex(&Set, iCpu))
     151                {
     152                    RTPrintf("tstMp-1: FAILURE: online cpu with index %2d is not a member of the possible cpu set!\n", iCpu);
     153                    g_cErrors++;
     154                }
     155            }
     156
     157        /* There isn't any sane way of testing RTMpIsCpuOnline really... :-/ */
     158    }
     159    else
     160    {
     161        RTPrintf("tstMp-1: FAILURE: RTMpGetOnlineSet -> %p, expected %p\n", pSet, &Set);
     162        g_cErrors++;
     163    }
     164
     165#else
     166    RTPrintf("tstMp-1: SKIPPED - RTMp is not implemented on this host OS.\n");
     167#endif
     168
    89169    if (!g_cErrors)
    90         RTPrintf("tstIp: SUCCESS\n", g_cErrors);
     170        RTPrintf("tstMp-1: SUCCESS\n", g_cErrors);
    91171    else
    92         RTPrintf("tstIp: FAILURE - %d errors\n", g_cErrors);
     172        RTPrintf("tstMp-1: FAILURE - %d errors\n", g_cErrors);
    93173    return !!g_cErrors;
    94174}
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