537680a235921a9a53f5040185a15cdcf228c217vboxsync/* $Id$ */
537680a235921a9a53f5040185a15cdcf228c217vboxsync/** @file
537680a235921a9a53f5040185a15cdcf228c217vboxsync * IPRT - Multiprocessor, Solaris.
537680a235921a9a53f5040185a15cdcf228c217vboxsync */
537680a235921a9a53f5040185a15cdcf228c217vboxsync
537680a235921a9a53f5040185a15cdcf228c217vboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2008-2012 Oracle Corporation
537680a235921a9a53f5040185a15cdcf228c217vboxsync *
537680a235921a9a53f5040185a15cdcf228c217vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
537680a235921a9a53f5040185a15cdcf228c217vboxsync * available from http://www.virtualbox.org. This file is free software;
537680a235921a9a53f5040185a15cdcf228c217vboxsync * you can redistribute it and/or modify it under the terms of the GNU
537680a235921a9a53f5040185a15cdcf228c217vboxsync * General Public License (GPL) as published by the Free Software
537680a235921a9a53f5040185a15cdcf228c217vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
537680a235921a9a53f5040185a15cdcf228c217vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
537680a235921a9a53f5040185a15cdcf228c217vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
537680a235921a9a53f5040185a15cdcf228c217vboxsync *
537680a235921a9a53f5040185a15cdcf228c217vboxsync * The contents of this file may alternatively be used under the terms
537680a235921a9a53f5040185a15cdcf228c217vboxsync * of the Common Development and Distribution License Version 1.0
537680a235921a9a53f5040185a15cdcf228c217vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
537680a235921a9a53f5040185a15cdcf228c217vboxsync * VirtualBox OSE distribution, in which case the provisions of the
537680a235921a9a53f5040185a15cdcf228c217vboxsync * CDDL are applicable instead of those of the GPL.
537680a235921a9a53f5040185a15cdcf228c217vboxsync *
537680a235921a9a53f5040185a15cdcf228c217vboxsync * You may elect to license modified versions of this file under the
537680a235921a9a53f5040185a15cdcf228c217vboxsync * terms and conditions of either the GPL or the CDDL or both.
537680a235921a9a53f5040185a15cdcf228c217vboxsync */
537680a235921a9a53f5040185a15cdcf228c217vboxsync
537680a235921a9a53f5040185a15cdcf228c217vboxsync/*******************************************************************************
537680a235921a9a53f5040185a15cdcf228c217vboxsync* Header Files *
537680a235921a9a53f5040185a15cdcf228c217vboxsync*******************************************************************************/
537680a235921a9a53f5040185a15cdcf228c217vboxsync#define LOG_GROUP RTLOGGROUP_DEFAULT
537680a235921a9a53f5040185a15cdcf228c217vboxsync#include <unistd.h>
537680a235921a9a53f5040185a15cdcf228c217vboxsync#include <stdio.h>
537680a235921a9a53f5040185a15cdcf228c217vboxsync#include <errno.h>
537680a235921a9a53f5040185a15cdcf228c217vboxsync#include <kstat.h>
4de6100f39be6c66ee61c3208181b8f9086f4cb6vboxsync#include <sys/processor.h>
537680a235921a9a53f5040185a15cdcf228c217vboxsync
537680a235921a9a53f5040185a15cdcf228c217vboxsync#include <iprt/mp.h>
537680a235921a9a53f5040185a15cdcf228c217vboxsync#include <iprt/cpuset.h>
537680a235921a9a53f5040185a15cdcf228c217vboxsync#include <iprt/assert.h>
537680a235921a9a53f5040185a15cdcf228c217vboxsync#include <iprt/string.h>
537680a235921a9a53f5040185a15cdcf228c217vboxsync#include <iprt/alloc.h>
537680a235921a9a53f5040185a15cdcf228c217vboxsync#include <iprt/log.h>
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync#include <iprt/once.h>
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync#include <iprt/critsect.h>
537680a235921a9a53f5040185a15cdcf228c217vboxsync
537680a235921a9a53f5040185a15cdcf228c217vboxsync
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync/*******************************************************************************
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync* Global Variables *
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync*******************************************************************************/
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync/** Initialization serializing (rtMpSolarisOnce). */
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsyncstatic RTONCE g_MpSolarisOnce = RTONCE_INITIALIZER;
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync/** Critical section serializing access to kstat. */
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsyncstatic RTCRITSECT g_MpSolarisCritSect;
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync/** The kstat handle. */
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsyncstatic kstat_ctl_t *g_pKsCtl;
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync/** Array pointing to the cpu_info instances. */
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsyncstatic kstat_t **g_papCpuInfo;
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync/** The number of entries in g_papCpuInfo */
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsyncstatic RTCPUID g_capCpuInfo;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync/** Array of core ids. */
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsyncstatic uint64_t *g_pu64CoreIds;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync/** Number of entries in g_pu64CoreIds. */
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsyncstatic size_t g_cu64CoreIds;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync/** Number of cores in the system. */
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsyncstatic size_t g_cCores;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync/**
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync * Helper for getting the core ID for a given CPU/strand/hyperthread.
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync *
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync * @returns The core ID.
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync * @param idCpu The CPU ID instance.
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync */
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsyncstatic inline uint64_t rtMpSolarisGetCoreId(RTCPUID idCpu)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync{
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(g_papCpuInfo[idCpu], (char *)"core_id");
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync Assert(pStat->data_type == KSTAT_DATA_LONG);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync Assert(pStat->value.l >= 0);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync AssertCompile(sizeof(uint64_t) >= sizeof(long)); /* Paranoia. */
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync return (uint64_t)pStat->value.l;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync}
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync/**
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync * Populates 'g_pu64CoreIds' array with unique core identifiers in the system.
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync *
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync * @returns VBox status code.
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync */
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsyncstatic int rtMpSolarisGetCoreIds(void)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync{
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync for (RTCPUID idCpu = 0; idCpu < g_capCpuInfo; idCpu++)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync if (kstat_read(g_pKsCtl, g_papCpuInfo[idCpu], 0) != -1)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync /* Strands/Hyperthreads share the same core ID. */
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync uint64_t u64CoreId = rtMpSolarisGetCoreId(idCpu);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync bool fAddedCore = false;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync for (RTCPUID i = 0; i < g_cCores; i++)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync if (g_pu64CoreIds[i] == u64CoreId)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync fAddedCore = true;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync break;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync }
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync }
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync if (!fAddedCore)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync g_pu64CoreIds[g_cCores] = u64CoreId;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync ++g_cCores;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync }
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync }
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync else
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync return VERR_INTERNAL_ERROR_2;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync }
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync return VINF_SUCCESS;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync}
537680a235921a9a53f5040185a15cdcf228c217vboxsync
537680a235921a9a53f5040185a15cdcf228c217vboxsync
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync/**
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync * Run once function that initializes the kstats we need here.
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync *
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync * @returns IPRT status code.
a438caaf732f7839dc66b4f8dad672527845a003vboxsync * @param pvUser Unused.
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync */
a438caaf732f7839dc66b4f8dad672527845a003vboxsyncstatic DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser)
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync{
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync int rc = VINF_SUCCESS;
a438caaf732f7839dc66b4f8dad672527845a003vboxsync NOREF(pvUser);
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync /*
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync * Open kstat and find the cpu_info entries for each of the CPUs.
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync */
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync g_pKsCtl = kstat_open();
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync if (g_pKsCtl)
537680a235921a9a53f5040185a15cdcf228c217vboxsync {
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync g_capCpuInfo = RTMpGetCount();
6ae948500828abfb01b923bb81950f44bde0dfc5vboxsync g_papCpuInfo = (kstat_t **)RTMemAllocZ(g_capCpuInfo * sizeof(kstat_t *));
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync if (g_papCpuInfo)
537680a235921a9a53f5040185a15cdcf228c217vboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync g_cu64CoreIds = g_capCpuInfo;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync g_pu64CoreIds = (uint64_t *)RTMemAllocZ(g_cu64CoreIds * sizeof(uint64_t));
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync if (g_pu64CoreIds)
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync rc = RTCritSectInit(&g_MpSolarisCritSect);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync if (RT_SUCCESS(rc))
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync RTCPUID i = 0;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync for (kstat_t *pKsp = g_pKsCtl->kc_chain; pKsp != NULL; pKsp = pKsp->ks_next)
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync if (!RTStrCmp(pKsp->ks_module, "cpu_info"))
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync AssertBreak(i < g_capCpuInfo);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync g_papCpuInfo[i++] = pKsp;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync /** @todo ks_instance == cpu_id (/usr/src/uts/common/os/cpu.c)? Check this and fix it ASAP. */
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync }
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync }
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync rc = rtMpSolarisGetCoreIds();
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync if (RT_SUCCESS(rc))
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync return VINF_SUCCESS;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync else
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync Log(("rtMpSolarisGetCoreIds failed. rc=%Rrc\n", rc));
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync }
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync RTMemFree(g_pu64CoreIds);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync g_pu64CoreIds = NULL;
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync }
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync else
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync rc = VERR_NO_MEMORY;
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync /* bail out, we failed. */
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync RTMemFree(g_papCpuInfo);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync g_papCpuInfo = NULL;
537680a235921a9a53f5040185a15cdcf228c217vboxsync }
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync else
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync rc = VERR_NO_MEMORY;
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync kstat_close(g_pKsCtl);
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync g_pKsCtl = NULL;
537680a235921a9a53f5040185a15cdcf228c217vboxsync }
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync else
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync {
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync rc = RTErrConvertFromErrno(errno);
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync if (RT_SUCCESS(rc))
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync rc = VERR_INTERNAL_ERROR;
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync Log(("kstat_open() -> %d (%Rrc)\n", errno, rc));
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync }
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync return rc;
537680a235921a9a53f5040185a15cdcf228c217vboxsync}
537680a235921a9a53f5040185a15cdcf228c217vboxsync
537680a235921a9a53f5040185a15cdcf228c217vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync/**
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync * RTOnceEx() cleanup function.
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync *
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync * @param pvUser Unused.
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync * @param fLazyCleanUpOk Whether lazy cleanup is okay or not.
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync */
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsyncstatic DECLCALLBACK(void) rtMpSolarisCleanUp(void *pvUser, bool fLazyCleanUpOk)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync{
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync if (g_pKsCtl)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync kstat_close(g_pKsCtl);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync RTMemFree(g_pu64CoreIds);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync RTMemFree(g_papCpuInfo);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync}
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync/**
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync * Worker for RTMpGetCurFrequency and RTMpGetMaxFrequency.
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync *
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync * @returns The desired frequency on success, 0 on failure.
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync *
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync * @param idCpu The CPU ID.
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync * @param pszStatName The cpu_info stat name.
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync */
1f942a68581d7c1b72d28bf52355dc6cb3cae4c6vboxsyncstatic uint64_t rtMpSolarisGetFrequency(RTCPUID idCpu, const char *pszStatName)
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync{
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync uint64_t u64 = 0;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync int rc = RTOnceEx(&g_MpSolarisOnce, rtMpSolarisOnce, rtMpSolarisCleanUp, NULL /* pvUser */);
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync if (RT_SUCCESS(rc))
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync {
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync if ( idCpu < g_capCpuInfo
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync && g_papCpuInfo[idCpu])
537680a235921a9a53f5040185a15cdcf228c217vboxsync {
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync rc = RTCritSectEnter(&g_MpSolarisCritSect);
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync AssertRC(rc);
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync if (RT_SUCCESS(rc))
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync {
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync if (kstat_read(g_pKsCtl, g_papCpuInfo[idCpu], 0) != -1)
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync {
cdb8035cec2e461958b23bc133e721a42517bfdfvboxsync /* Solaris really need to fix their APIs. Explicitly cast for now. */
1f942a68581d7c1b72d28bf52355dc6cb3cae4c6vboxsync kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(g_papCpuInfo[idCpu], (char*)pszStatName);
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync if (pStat)
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync {
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync Assert(pStat->data_type == KSTAT_DATA_UINT64 || pStat->data_type == KSTAT_DATA_LONG);
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync switch (pStat->data_type)
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync {
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync case KSTAT_DATA_UINT64: u64 = pStat->value.ui64; break; /* current_clock_Hz */
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync case KSTAT_DATA_INT32: u64 = pStat->value.i32; break; /* clock_MHz */
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync /* just in case... */
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync case KSTAT_DATA_UINT32: u64 = pStat->value.ui32; break;
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync case KSTAT_DATA_INT64: u64 = pStat->value.i64; break;
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync default:
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync AssertMsgFailed(("%d\n", pStat->data_type));
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync break;
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync }
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync }
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync else
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync Log(("kstat_data_lookup(%s) -> %d\n", pszStatName, errno));
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync }
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync else
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync Log(("kstat_read() -> %d\n", errno));
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync RTCritSectLeave(&g_MpSolarisCritSect);
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync }
537680a235921a9a53f5040185a15cdcf228c217vboxsync }
537680a235921a9a53f5040185a15cdcf228c217vboxsync else
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync Log(("invalid idCpu: %d (g_capCpuInfo=%d)\n", (int)idCpu, (int)g_capCpuInfo));
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync }
537680a235921a9a53f5040185a15cdcf228c217vboxsync
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync return u64;
537680a235921a9a53f5040185a15cdcf228c217vboxsync}
537680a235921a9a53f5040185a15cdcf228c217vboxsync
537680a235921a9a53f5040185a15cdcf228c217vboxsync
537680a235921a9a53f5040185a15cdcf228c217vboxsyncRTDECL(uint32_t) RTMpGetCurFrequency(RTCPUID idCpu)
537680a235921a9a53f5040185a15cdcf228c217vboxsync{
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync return rtMpSolarisGetFrequency(idCpu, "current_clock_Hz") / 1000000;
537680a235921a9a53f5040185a15cdcf228c217vboxsync}
537680a235921a9a53f5040185a15cdcf228c217vboxsync
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync
537680a235921a9a53f5040185a15cdcf228c217vboxsyncRTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu)
537680a235921a9a53f5040185a15cdcf228c217vboxsync{
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync return rtMpSolarisGetFrequency(idCpu, "clock_MHz");
537680a235921a9a53f5040185a15cdcf228c217vboxsync}
148b03bcfa337a0e994b1f7297662c972b77ac3avboxsync
164345b1ba852b4467082e8a57c8cb793304802evboxsync
f6aff34d987eb8063700c4c26456df4e70f3721cvboxsync#if defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64)
f6aff34d987eb8063700c4c26456df4e70f3721cvboxsyncRTDECL(RTCPUID) RTMpCpuId(void)
f6aff34d987eb8063700c4c26456df4e70f3721cvboxsync{
f6aff34d987eb8063700c4c26456df4e70f3721cvboxsync /** @todo implement RTMpCpuId on solaris/r3! */
f6aff34d987eb8063700c4c26456df4e70f3721cvboxsync return NIL_RTCPUID;
f6aff34d987eb8063700c4c26456df4e70f3721cvboxsync}
f6aff34d987eb8063700c4c26456df4e70f3721cvboxsync#endif
f6aff34d987eb8063700c4c26456df4e70f3721cvboxsync
f6aff34d987eb8063700c4c26456df4e70f3721cvboxsync
b929f4d04ad2a9b1cf968da876979367430c5efavboxsyncRTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync{
6bd18639c3cba30caeea5bc4fa2fe87de208c708vboxsync return idCpu < RTCPUSET_MAX_CPUS ? (int)idCpu : -1;
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync}
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync
b929f4d04ad2a9b1cf968da876979367430c5efavboxsyncRTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync{
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync return (unsigned)iCpu < RTCPUSET_MAX_CPUS ? iCpu : NIL_RTCPUID;
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync}
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync
b929f4d04ad2a9b1cf968da876979367430c5efavboxsyncRTDECL(RTCPUID) RTMpGetMaxCpuId(void)
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync{
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync return RTMpGetCount() - 1;
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync}
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync
b929f4d04ad2a9b1cf968da876979367430c5efavboxsyncRTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync{
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync return idCpu != NIL_RTCPUID
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync && idCpu < (RTCPUID)RTMpGetCount();
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync}
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync
b929f4d04ad2a9b1cf968da876979367430c5efavboxsyncRTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync{
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync int iStatus = p_online(idCpu, P_STATUS);
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync return iStatus == P_ONLINE
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync || iStatus == P_NOINTR;
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync}
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsyncRTDECL(bool) RTMpIsCpuPresent(RTCPUID idCpu)
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync{
b733caa403cbfbbcad164a0b2cb8ffe15e7fbdd1vboxsync int iStatus = p_online(idCpu, P_STATUS);
b733caa403cbfbbcad164a0b2cb8ffe15e7fbdd1vboxsync return iStatus != -1;
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync}
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsyncRTDECL(RTCPUID) RTMpGetCount(void)
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsync{
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsync /*
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsync * Solaris has sysconf.
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsync */
13c44ff552158bfa80232bb12763a53a063e3081vboxsync int cCpus = sysconf(_SC_NPROCESSORS_MAX);
164345b1ba852b4467082e8a57c8cb793304802evboxsync if (cCpus < 0)
164345b1ba852b4467082e8a57c8cb793304802evboxsync cCpus = sysconf(_SC_NPROCESSORS_CONF);
164345b1ba852b4467082e8a57c8cb793304802evboxsync return cCpus;
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsync}
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsync
164345b1ba852b4467082e8a57c8cb793304802evboxsync
b929f4d04ad2a9b1cf968da876979367430c5efavboxsyncRTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
4de6100f39be6c66ee61c3208181b8f9086f4cb6vboxsync{
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync RTCpuSetEmpty(pSet);
b9f55d08827aba9a80f57ca6af945abf6b725abcvboxsync int idCpu = RTMpGetCount();
b9f55d08827aba9a80f57ca6af945abf6b725abcvboxsync while (idCpu-- > 0)
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync RTCpuSetAdd(pSet, idCpu);
b929f4d04ad2a9b1cf968da876979367430c5efavboxsync return pSet;
4de6100f39be6c66ee61c3208181b8f9086f4cb6vboxsync}
4de6100f39be6c66ee61c3208181b8f9086f4cb6vboxsync
4de6100f39be6c66ee61c3208181b8f9086f4cb6vboxsync
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsyncRTDECL(RTCPUID) RTMpGetOnlineCount(void)
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsync{
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsync /*
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsync * Solaris has sysconf.
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsync */
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsync return sysconf(_SC_NPROCESSORS_ONLN);
7153a94e631ff3ba3ae93aa08299b4819cbd1501vboxsync}
1141858ff8cf4c97d7ade2d43cb111f053182dd2vboxsync
1141858ff8cf4c97d7ade2d43cb111f053182dd2vboxsync
1141858ff8cf4c97d7ade2d43cb111f053182dd2vboxsyncRTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
1141858ff8cf4c97d7ade2d43cb111f053182dd2vboxsync{
1141858ff8cf4c97d7ade2d43cb111f053182dd2vboxsync RTCpuSetEmpty(pSet);
44b2b8a30952a19f7d57e288f59eaba3dcf6fc4avboxsync RTCPUID cCpus = RTMpGetCount();
4de6100f39be6c66ee61c3208181b8f9086f4cb6vboxsync for (RTCPUID idCpu = 0; idCpu < cCpus; idCpu++)
4de6100f39be6c66ee61c3208181b8f9086f4cb6vboxsync if (RTMpIsCpuOnline(idCpu))
44b2b8a30952a19f7d57e288f59eaba3dcf6fc4avboxsync RTCpuSetAdd(pSet, idCpu);
1141858ff8cf4c97d7ade2d43cb111f053182dd2vboxsync return pSet;
1141858ff8cf4c97d7ade2d43cb111f053182dd2vboxsync}
1141858ff8cf4c97d7ade2d43cb111f053182dd2vboxsync
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsyncRTDECL(PRTCPUSET) RTMpGetPresentSet(PRTCPUSET pSet)
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync{
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync#ifdef RT_STRICT
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync RTCPUID cCpusPresent = 0;
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync#endif
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync RTCpuSetEmpty(pSet);
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync RTCPUID cCpus = RTMpGetCount();
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync for (RTCPUID idCpu = 0; idCpu < cCpus; idCpu++)
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync if (RTMpIsCpuPresent(idCpu))
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync {
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync RTCpuSetAdd(pSet, idCpu);
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync#ifdef RT_STRICT
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync cCpusPresent++;
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync#endif
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync }
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync Assert(cCpusPresent == RTMpGetPresentCount());
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync return pSet;
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync}
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsyncRTDECL(RTCPUID) RTMpGetPresentCount(void)
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync{
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync /*
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync * Solaris has sysconf.
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync */
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync return sysconf(_SC_NPROCESSORS_CONF);
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync}
e7fd455c7cf734fefff2b0bd4c620eebe2ce3777vboxsync
a3ff231e643d5bbfd10d8ab6716d199088375bbcvboxsync
a3ff231e643d5bbfd10d8ab6716d199088375bbcvboxsyncRTDECL(RTCPUID) RTMpGetPresentCoreCount(void)
a3ff231e643d5bbfd10d8ab6716d199088375bbcvboxsync{
a3ff231e643d5bbfd10d8ab6716d199088375bbcvboxsync return RTMpGetCoreCount();
a3ff231e643d5bbfd10d8ab6716d199088375bbcvboxsync}
a3ff231e643d5bbfd10d8ab6716d199088375bbcvboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsyncRTDECL(RTCPUID) RTMpGetCoreCount(void)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync{
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync int rc = RTOnceEx(&g_MpSolarisOnce, rtMpSolarisOnce, rtMpSolarisCleanUp, NULL /* pvUser */);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync if (RT_SUCCESS(rc))
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync return g_cCores;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync return 0;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync}
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsyncRTDECL(RTCPUID) RTMpGetOnlineCoreCount(void)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync{
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync RTCPUID uOnlineCores = 0;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync int rc = RTOnceEx(&g_MpSolarisOnce, rtMpSolarisOnce, rtMpSolarisCleanUp, NULL /* pvUser */);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync if (RT_SUCCESS(rc))
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync rc = RTCritSectEnter(&g_MpSolarisCritSect);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync AssertRC(rc);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync /*
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync * For each core in the system, count how many are currently online.
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync */
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync for (RTCPUID j = 0; j < g_cCores; j++)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync uint64_t u64CoreId = g_pu64CoreIds[j];
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync for (RTCPUID idCpu = 0; idCpu < g_capCpuInfo; idCpu++)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync rc = kstat_read(g_pKsCtl, g_papCpuInfo[idCpu], 0);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync AssertReturn(rc != -1, 0 /* rc */);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync uint64_t u64ThreadCoreId = rtMpSolarisGetCoreId(idCpu);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync if (u64ThreadCoreId == u64CoreId)
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(g_papCpuInfo[idCpu], (char *)"state");
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync Assert(pStat->data_type == KSTAT_DATA_CHAR);
be34c96bcb2a39c75eaf8754d1334390af507808vboxsync if( !RTStrNCmp(pStat->value.c, PS_ONLINE, sizeof(PS_ONLINE) - 1)
be34c96bcb2a39c75eaf8754d1334390af507808vboxsync || !RTStrNCmp(pStat->value.c, PS_NOINTR, sizeof(PS_NOINTR) - 1))
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync {
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync uOnlineCores++;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync break; /* Move to the next core. We have at least 1 hyperthread online in the current core. */
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync }
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync }
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync }
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync }
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync RTCritSectLeave(&g_MpSolarisCritSect);
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync }
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync return uOnlineCores;
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync}
c0b87dff0bb4ff4d4547b4ecd781da507f338ea8vboxsync