VirtualBox

Changeset 11241 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 8, 2008 12:51:27 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
34318
Message:

iprt/r3/mp-solaris r=bird:

  • kstat doesn't appear to be serialized (fixed).
  • current_clock_Hz and clock_MHz returns different data types it seems, current_clock_Hz would be wrong on 32-bit boxes with high frequency cpus (fixed).
  • Heap corruption if RTMpGetCount and kstat has different ideas about the number of cpus. (fixed)
  • Serialize initialization using RTOnce (done).
  • There is an assumption about cpu_info instance ordering and the cpu_id, looking at the source it seems ks_instance == cpu_id. Please check this out.
File:
1 edited

Legend:

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

    r11205 r11241  
    2929 */
    3030
    31 
    3231/*******************************************************************************
    3332*   Header Files                                                               *
     
    4544#include <iprt/alloc.h>
    4645#include <iprt/log.h>
     46#include <iprt/once.h>
     47#include <iprt/critsect.h>
    4748
    48 static kstat_ctl_t *g_kc;
    49 static kstat_t    **g_cpuInfo;
    50 static RTCPUID      g_nCPUs;
    5149
    52 void rtLookupCpuInfoStats()
     50/*******************************************************************************
     51*   Global Variables                                                           *
     52*******************************************************************************/
     53/** Initialization serializing (rtMpSolarisOnce). */
     54static RTONCE       g_MpSolarisOnce = RTONCE_INITIALIZER;
     55/** Critical section serializing access to kstat. */
     56static RTCRITSECT   g_MpSolarisCritSect;
     57/** The kstat handle. */
     58static kstat_ctl_t *g_pKsCtl;
     59/** Array pointing to the cpu_info instances. */
     60static kstat_t    **g_papCpuInfo;
     61/** The number of entries in g_papCpuInfo */
     62static RTCPUID      g_capCpuInfo;
     63
     64
     65/**
     66 * Run once function that initializes the kstats we need here.
     67 *
     68 * @returns IPRT status code.
     69 * @param   pvUser1     Unused.
     70 * @param   pvUser2     Unused.
     71 */
     72static DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser1, void *pvUser2)
    5373{
    54     g_kc = kstat_open();
    55     if (!g_kc)
     74    int rc = VINF_SUCCESS;
     75    NOREF(pvUser1); NOREF(pvUser2);
     76
     77    /*
     78     * Open kstat and find the cpu_info entries for each of the CPUs.
     79     */
     80    g_pKsCtl = kstat_open();
     81    if (g_pKsCtl)
    5682    {
    57         Log(("kstat_open() -> %d\n", errno));
    58         return;
     83        g_capCpuInfo = RTMpGetCount();
     84        g_papCpuInfo = (kstat_t **)RTMemAlloc(g_capCpuInfo * sizeof(kstat_t *));
     85        if (g_papCpuInfo)
     86        {
     87            rc = RTCritSectInit(&g_MpSolarisCritSect);
     88            if (RT_SUCCESS(rc))
     89            {
     90                RTCPUID i = 0;
     91                for (kstat_t *pKsp = g_pKsCtl->kc_chain; pKsp != NULL; pKsp = pKsp->ks_next)
     92                {
     93                    if (!strcmp(pKsp->ks_module, "cpu_info"))
     94                    {
     95                        AssertBreak(i < g_capCpuInfo);
     96                        g_papCpuInfo[i++] = pKsp;
     97                        /** @todo ks_instance == cpu_id (/usr/src/uts/common/os/cpu.c)? Check this and fix it ASAP. */
     98                    }
     99                }
     100
     101                return VINF_SUCCESS;
     102            }
     103
     104            /* bail out, we failed. */
     105            RTMemFree(g_papCpuInfo);
     106        }
     107        else
     108            rc = VERR_NO_MEMORY;
     109        kstat_close(g_pKsCtl);
     110        g_pKsCtl = NULL;
     111    }
     112    else
     113    {
     114        rc = RTErrConvertFromErrno(errno);
     115        if (RT_SUCCESS(rc))
     116            rc = VERR_INTERNAL_ERROR;
     117        Log(("kstat_open() -> %d (%Rrc)\n", errno, rc));
    59118    }
    60119
    61     g_nCPUs = RTMpGetCount();
    62     g_cpuInfo = (kstat_t**)RTMemAlloc(g_nCPUs * sizeof(kstat_t*));
    63     if (!g_cpuInfo)
     120    return rc;
     121}
     122
     123
     124/**
     125 * Worker for RTMpGetCurFrequency and RTMpGetMaxFrequency.
     126 *
     127 * @returns The desired frequency on success, 0 on failure.
     128 *
     129 * @param   idCpu           The CPU ID.
     130 * @param   pszStatName     The cpu_info stat name.
     131 */
     132static uint64_t rtMpSolarisGetFrequency(RTCPUID idCpu, char *pszStatName)
     133{
     134    uint64_t u64 = 0;
     135    int rc = RTOnce(&g_MpSolarisOnce, rtMpSolarisOnce, NULL, NULL);
     136    if (RT_SUCCESS(rc))
    64137    {
    65         Log(("RTMemAlloc() -> NULL\n"));
    66         return;
     138        if (    idCpu < g_capCpuInfo
     139            &&  g_papCpuInfo[idCpu])
     140        {
     141            rc = RTCritSectEnter(&g_MpSolarisCritSect);
     142            AssertRC(rc);
     143            if (RT_SUCCESS(rc))
     144            {
     145                if (kstat_read(g_pKsCtl, g_papCpuInfo[idCpu], 0) != -1)
     146                {
     147                    kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(g_papCpuInfo[idCpu], pszStatName);
     148                    if (pStat)
     149                    {
     150                        Assert(pStat->data_type == KSTAT_DATA_UINT64 || pStat->data_type == KSTAT_DATA_LONG);
     151                        switch (pStat->data_type)
     152                        {
     153                            case KSTAT_DATA_UINT64: u64 = pStat->value.ui64; break; /* current_clock_Hz */
     154                            case KSTAT_DATA_INT32:  u64 = pStat->value.i32;  break; /* clock_MHz */
     155
     156                            /* just in case... */
     157                            case KSTAT_DATA_UINT32: u64 = pStat->value.ui32; break;
     158                            case KSTAT_DATA_INT64:  u64 = pStat->value.i64;  break;
     159                            default:
     160                                AssertMsgFailed(("%d\n", pStat->data_type));
     161                                break;
     162                        }
     163                    }
     164                    else
     165                        Log(("kstat_data_lookup(%s) -> %d\n", pszStatName, errno));
     166                }
     167                else
     168                    Log(("kstat_read() -> %d\n", errno));
     169                RTCritSectLeave(&g_MpSolarisCritSect);
     170            }
     171        }
     172        else
     173            Log(("invalid idCpu: %d (g_capCpuInfo=%d)\n", (int)idCpu, (int)g_capCpuInfo));
    67174    }
    68175
    69     RTCPUID i = 0;
    70     kstat_t *ksp;
    71     for (ksp = g_kc->kc_chain; ksp != NULL; ksp = ksp->ks_next)
    72     {
    73         if (strcmp(ksp->ks_module, "cpu_info") == 0)
    74         {
    75             g_cpuInfo[i++] = ksp;
    76         }
    77         Assert(i <= g_nCPUs);
    78     }
    79 }
    80 
    81 static uint64_t rtMpGetFrequency(RTCPUID idCpu, char *statName)
    82 {
    83     if (!g_kc)
    84         rtLookupCpuInfoStats();
    85 
    86     if (idCpu < g_nCPUs && g_cpuInfo[idCpu])
    87         if (kstat_read(g_kc, g_cpuInfo[idCpu], 0) != -1)
    88         {
    89             kstat_named_t *kn;
    90             kn = (kstat_named_t *)kstat_data_lookup(g_cpuInfo[idCpu], statName);
    91             if (kn)
    92                 return kn->value.ul;
    93             else
    94                 Log(("kstat_data_lookup(%s) -> %d\n", statName, errno));
    95         }
    96         else
    97             Log(("kstat_read() -> %d\n", errno));
    98     else
    99         Log(("invalid idCpu: %d\n", idCpu));
    100 
    101     return 0;
     176    return u64;
    102177}
    103178
     
    105180RTDECL(uint32_t) RTMpGetCurFrequency(RTCPUID idCpu)
    106181{
    107     return rtMpGetFrequency(idCpu, "current_clock_Hz") / 1000000;
     182    return rtMpSolarisGetFrequency(idCpu, "current_clock_Hz") / 1000000;
    108183}
     184
    109185
    110186RTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu)
    111187{
    112     return rtMpGetFrequency(idCpu, "clock_MHz");
     188    return rtMpSolarisGetFrequency(idCpu, "clock_MHz");
    113189}
     190
Note: See TracChangeset for help on using the changeset viewer.

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