summaryrefslogtreecommitdiff
path: root/src/VBox/Runtime/r3/solaris
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-03-26 19:21:20 +0000
committer <>2014-05-08 15:03:54 +0000
commitfb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch)
treec2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Runtime/r3/solaris
parent58ed4748338f9466599adfc8a9171280ed99e23f (diff)
downloadVirtualBox-master.tar.gz
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/Runtime/r3/solaris')
-rw-r--r--src/VBox/Runtime/r3/solaris/Makefile.kup0
-rw-r--r--src/VBox/Runtime/r3/solaris/RTSystemShutdown-solaris.cpp102
-rw-r--r--src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp56
-rw-r--r--src/VBox/Runtime/r3/solaris/coredumper-solaris.h2
-rw-r--r--src/VBox/Runtime/r3/solaris/fileaio-solaris.cpp14
-rw-r--r--src/VBox/Runtime/r3/solaris/mp-solaris.cpp182
-rw-r--r--src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp2
-rw-r--r--src/VBox/Runtime/r3/solaris/systemmem-solaris.cpp172
8 files changed, 456 insertions, 74 deletions
diff --git a/src/VBox/Runtime/r3/solaris/Makefile.kup b/src/VBox/Runtime/r3/solaris/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Runtime/r3/solaris/Makefile.kup
diff --git a/src/VBox/Runtime/r3/solaris/RTSystemShutdown-solaris.cpp b/src/VBox/Runtime/r3/solaris/RTSystemShutdown-solaris.cpp
new file mode 100644
index 00000000..44906788
--- /dev/null
+++ b/src/VBox/Runtime/r3/solaris/RTSystemShutdown-solaris.cpp
@@ -0,0 +1,102 @@
+/* $Id: RTSystemShutdown-solaris.cpp $ */
+/** @file
+ * IPRT - RTSystemShutdown, linux implementation.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include <iprt/system.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/env.h>
+#include <iprt/err.h>
+#include <iprt/process.h>
+#include <iprt/string.h>
+
+
+RTDECL(int) RTSystemShutdown(RTMSINTERVAL cMsDelay, uint32_t fFlags, const char *pszLogMsg)
+{
+ AssertPtrReturn(pszLogMsg, VERR_INVALID_POINTER);
+ AssertReturn(!(fFlags & ~RTSYSTEM_SHUTDOWN_VALID_MASK), VERR_INVALID_PARAMETER);
+
+ /*
+ * Assemble the argument vector.
+ */
+ int iArg = 0;
+ const char *apszArgs[8];
+
+ RT_BZERO(apszArgs, sizeof(apszArgs));
+
+ apszArgs[iArg++] = "/usr/sbin/shutdown";
+ apszArgs[iArg++] = "-y"; /* Pre-answer confirmation question. */
+ apszArgs[iArg++] = "-i"; /* Change to the following state. */
+ switch (fFlags & RTSYSTEM_SHUTDOWN_ACTION_MASK)
+ {
+ case RTSYSTEM_SHUTDOWN_HALT:
+ apszArgs[iArg++] = "0";
+ break;
+ case RTSYSTEM_SHUTDOWN_REBOOT:
+ apszArgs[iArg++] = "6";
+ break;
+ case RTSYSTEM_SHUTDOWN_POWER_OFF:
+ case RTSYSTEM_SHUTDOWN_POWER_OFF_HALT:
+ apszArgs[iArg++] = "5";
+ break;
+ }
+
+ apszArgs[iArg++] = "-g"; /* Grace period. */
+
+ char szWhen[80];
+ if (cMsDelay < 500)
+ strcpy(szWhen, "0");
+ else
+ RTStrPrintf(szWhen, sizeof(szWhen), "%u", (unsigned)((cMsDelay + 499) / 1000));
+ apszArgs[iArg++] = szWhen;
+
+ apszArgs[iArg++] = pszLogMsg;
+
+
+ /*
+ * Start the shutdown process and wait for it to complete.
+ */
+ RTPROCESS hProc;
+ int rc = RTProcCreate(apszArgs[0], apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, &hProc);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ RTPROCSTATUS ProcStatus;
+ rc = RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus);
+ if (RT_SUCCESS(rc))
+ {
+ if ( ProcStatus.enmReason != RTPROCEXITREASON_NORMAL
+ || ProcStatus.iStatus != 0)
+ rc = VERR_SYS_SHUTDOWN_FAILED;
+ }
+
+ return rc;
+}
+
diff --git a/src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp b/src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp
index 39726eda..66ef5286 100644
--- a/src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp
+++ b/src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010-2011 Oracle Corporation
+ * Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -162,7 +162,7 @@ static int ReadFileNoIntr(int fd, void *pv, size_t cbToRead)
*
* @param fd Handle to the file to write to.
* @param pv Pointer to what to write.
- * @param cbToWrite Size of data to write.
+ * @param cbToWrite Size of data to write.
*
* @return IPRT status code.
*/
@@ -191,9 +191,9 @@ static int WriteFileNoIntr(int fd, const void *pv, size_t cbToWrite)
* Read from a given offset in the process' address space.
*
* @param pSolProc Pointer to the solaris process.
- * @param pv Where to read the data into.
- * @param cb Size of the read buffer.
- * @param off Offset to read from.
+ * @param off The offset to read from.
+ * @param pvBuf Where to read the data into.
+ * @param cbToRead Number of bytes to read.
*
* @return VINF_SUCCESS, if all the given bytes was read in, otherwise VERR_READ_ERROR.
*/
@@ -1263,51 +1263,8 @@ static int rtCoreDumperResumeThreads(PRTSOLCORE pSolCore)
{
AssertReturn(pSolCore, VERR_INVALID_POINTER);
-#if 1
uint64_t cThreads;
return rtCoreDumperForEachThread(pSolCore, &cThreads, resumeThread);
-#else
- PRTSOLCOREPROCESS pSolProc = &pSolCore->SolProc;
-
- char szCurThread[128];
- char szPath[PATH_MAX];
- PRTDIR pDir = NULL;
-
- RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/lwp", (int)pSolProc->Process);
- RTStrPrintf(szCurThread, sizeof(szCurThread), "%d", (int)pSolProc->hCurThread);
-
- int32_t cRunningThreads = 0;
- int rc = RTDirOpen(&pDir, szPath);
- if (RT_SUCCESS(rc))
- {
- /*
- * Loop through all our threads & resume them.
- */
- RTDIRENTRY DirEntry;
- while (RT_SUCCESS(RTDirRead(pDir, &DirEntry, NULL)))
- {
- if ( !strcmp(DirEntry.szName, ".")
- || !strcmp(DirEntry.szName, ".."))
- continue;
-
- if ( !strcmp(DirEntry.szName, szCurThread))
- continue;
-
- int32_t ThreadId = RTStrToInt32(DirEntry.szName);
- _lwp_continue((lwpid_t)ThreadId);
- ++cRunningThreads;
- }
-
- CORELOG((CORELOG_NAME "ResumeAllThreads: resumed %d threads\n", cRunningThreads));
- RTDirClose(pDir);
- }
- else
- {
- CORELOGRELSYS((CORELOG_NAME "ResumeAllThreads: Failed to open %s\n", szPath));
- rc = VERR_READ_ERROR;
- }
- return rc;
-#endif
}
@@ -2116,8 +2073,7 @@ static int rtCoreDumperDestroyCore(PRTSOLCORE pSolCore)
/**
- * Takes a core dump. This function has no other parameters than the context
- * because it can be called from signal handlers.
+ * Takes a core dump.
*
* @param pContext The context of the caller.
* @param pszOutputFile Path of the core file. If NULL is passed, the
diff --git a/src/VBox/Runtime/r3/solaris/coredumper-solaris.h b/src/VBox/Runtime/r3/solaris/coredumper-solaris.h
index 127fd9be..662effc6 100644
--- a/src/VBox/Runtime/r3/solaris/coredumper-solaris.h
+++ b/src/VBox/Runtime/r3/solaris/coredumper-solaris.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010-2011 Oracle Corporation
+ * Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/solaris/fileaio-solaris.cpp b/src/VBox/Runtime/r3/solaris/fileaio-solaris.cpp
index 2b6d60b8..2f218305 100644
--- a/src/VBox/Runtime/r3/solaris/fileaio-solaris.cpp
+++ b/src/VBox/Runtime/r3/solaris/fileaio-solaris.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -55,6 +55,8 @@ typedef struct RTFILEAIOCTXINTERNAL
int iPort;
/** Current number of requests active on this context. */
volatile int32_t cRequests;
+ /** Flags given during creation. */
+ uint32_t fFlags;
/** Magic value (RTFILEAIOCTX_MAGIC). */
uint32_t u32Magic;
} RTFILEAIOCTXINTERNAL;
@@ -270,11 +272,13 @@ RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered)
return RTErrConvertFromErrno(rcSol);
}
-RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax)
+RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax,
+ uint32_t fFlags)
{
int rc = VINF_SUCCESS;
PRTFILEAIOCTXINTERNAL pCtxInt;
AssertPtrReturn(phAioCtx, VERR_INVALID_POINTER);
+ AssertReturn(!(fFlags & ~RTFILEAIOCTX_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
pCtxInt = (PRTFILEAIOCTXINTERNAL)RTMemAllocZ(sizeof(RTFILEAIOCTXINTERNAL));
if (RT_UNLIKELY(!pCtxInt))
@@ -284,7 +288,8 @@ RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax)
pCtxInt->iPort = port_create();
if (RT_LIKELY(pCtxInt->iPort > 0))
{
- pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC;
+ pCtxInt->fFlags = fFlags;
+ pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC;
*phAioCtx = (RTFILEAIOCTX)pCtxInt;
}
else
@@ -448,7 +453,8 @@ RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL
AssertReturn(cReqs != 0, VERR_INVALID_PARAMETER);
AssertReturn(cReqs >= cMinReqs, VERR_OUT_OF_RANGE);
- if (RT_UNLIKELY(ASMAtomicReadS32(&pCtxInt->cRequests) == 0))
+ if ( RT_UNLIKELY(ASMAtomicReadS32(&pCtxInt->cRequests) == 0)
+ && !(pCtxInt->fFlags & RTFILEAIOCTX_FLAGS_WAIT_WITHOUT_PENDING_REQUESTS))
return VERR_FILE_AIO_NO_REQUEST;
/*
diff --git a/src/VBox/Runtime/r3/solaris/mp-solaris.cpp b/src/VBox/Runtime/r3/solaris/mp-solaris.cpp
index 0f2c6fdf..d21bbb42 100644
--- a/src/VBox/Runtime/r3/solaris/mp-solaris.cpp
+++ b/src/VBox/Runtime/r3/solaris/mp-solaris.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -57,19 +57,77 @@ static kstat_ctl_t *g_pKsCtl;
static kstat_t **g_papCpuInfo;
/** The number of entries in g_papCpuInfo */
static RTCPUID g_capCpuInfo;
+/** Array of core ids. */
+static uint64_t *g_pu64CoreIds;
+/** Number of entries in g_pu64CoreIds. */
+static size_t g_cu64CoreIds;
+/** Number of cores in the system. */
+static size_t g_cCores;
+
+
+/**
+ * Helper for getting the core ID for a given CPU/strand/hyperthread.
+ *
+ * @returns The core ID.
+ * @param idCpu The CPU ID instance.
+ */
+static inline uint64_t rtMpSolarisGetCoreId(RTCPUID idCpu)
+{
+ kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(g_papCpuInfo[idCpu], (char *)"core_id");
+ Assert(pStat->data_type == KSTAT_DATA_LONG);
+ Assert(pStat->value.l >= 0);
+ AssertCompile(sizeof(uint64_t) >= sizeof(long)); /* Paranoia. */
+ return (uint64_t)pStat->value.l;
+}
+
+
+/**
+ * Populates 'g_pu64CoreIds' array with unique core identifiers in the system.
+ *
+ * @returns VBox status code.
+ */
+static int rtMpSolarisGetCoreIds(void)
+{
+ for (RTCPUID idCpu = 0; idCpu < g_capCpuInfo; idCpu++)
+ {
+ if (kstat_read(g_pKsCtl, g_papCpuInfo[idCpu], 0) != -1)
+ {
+ /* Strands/Hyperthreads share the same core ID. */
+ uint64_t u64CoreId = rtMpSolarisGetCoreId(idCpu);
+ bool fAddedCore = false;
+ for (RTCPUID i = 0; i < g_cCores; i++)
+ {
+ if (g_pu64CoreIds[i] == u64CoreId)
+ {
+ fAddedCore = true;
+ break;
+ }
+ }
+
+ if (!fAddedCore)
+ {
+ g_pu64CoreIds[g_cCores] = u64CoreId;
+ ++g_cCores;
+ }
+ }
+ else
+ return VERR_INTERNAL_ERROR_2;
+ }
+
+ return VINF_SUCCESS;
+}
/**
* Run once function that initializes the kstats we need here.
*
* @returns IPRT status code.
- * @param pvUser1 Unused.
- * @param pvUser2 Unused.
+ * @param pvUser Unused.
*/
-static DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser1, void *pvUser2)
+static DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser)
{
int rc = VINF_SUCCESS;
- NOREF(pvUser1); NOREF(pvUser2);
+ NOREF(pvUser);
/*
* Open kstat and find the cpu_info entries for each of the CPUs.
@@ -81,25 +139,40 @@ static DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser1, void *pvUser2)
g_papCpuInfo = (kstat_t **)RTMemAllocZ(g_capCpuInfo * sizeof(kstat_t *));
if (g_papCpuInfo)
{
- rc = RTCritSectInit(&g_MpSolarisCritSect);
- if (RT_SUCCESS(rc))
+ g_cu64CoreIds = g_capCpuInfo;
+ g_pu64CoreIds = (uint64_t *)RTMemAllocZ(g_cu64CoreIds * sizeof(uint64_t));
+ if (g_pu64CoreIds)
{
- RTCPUID i = 0;
- for (kstat_t *pKsp = g_pKsCtl->kc_chain; pKsp != NULL; pKsp = pKsp->ks_next)
+ rc = RTCritSectInit(&g_MpSolarisCritSect);
+ if (RT_SUCCESS(rc))
{
- if (!strcmp(pKsp->ks_module, "cpu_info"))
+ RTCPUID i = 0;
+ for (kstat_t *pKsp = g_pKsCtl->kc_chain; pKsp != NULL; pKsp = pKsp->ks_next)
{
- AssertBreak(i < g_capCpuInfo);
- g_papCpuInfo[i++] = pKsp;
- /** @todo ks_instance == cpu_id (/usr/src/uts/common/os/cpu.c)? Check this and fix it ASAP. */
+ if (!RTStrCmp(pKsp->ks_module, "cpu_info"))
+ {
+ AssertBreak(i < g_capCpuInfo);
+ g_papCpuInfo[i++] = pKsp;
+ /** @todo ks_instance == cpu_id (/usr/src/uts/common/os/cpu.c)? Check this and fix it ASAP. */
+ }
}
+
+ rc = rtMpSolarisGetCoreIds();
+ if (RT_SUCCESS(rc))
+ return VINF_SUCCESS;
+ else
+ Log(("rtMpSolarisGetCoreIds failed. rc=%Rrc\n", rc));
}
- return VINF_SUCCESS;
+ RTMemFree(g_pu64CoreIds);
+ g_pu64CoreIds = NULL;
}
+ else
+ rc = VERR_NO_MEMORY;
/* bail out, we failed. */
RTMemFree(g_papCpuInfo);
+ g_papCpuInfo = NULL;
}
else
rc = VERR_NO_MEMORY;
@@ -119,6 +192,21 @@ static DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser1, void *pvUser2)
/**
+ * RTOnceEx() cleanup function.
+ *
+ * @param pvUser Unused.
+ * @param fLazyCleanUpOk Whether lazy cleanup is okay or not.
+ */
+static DECLCALLBACK(void) rtMpSolarisCleanUp(void *pvUser, bool fLazyCleanUpOk)
+{
+ if (g_pKsCtl)
+ kstat_close(g_pKsCtl);
+ RTMemFree(g_pu64CoreIds);
+ RTMemFree(g_papCpuInfo);
+}
+
+
+/**
* Worker for RTMpGetCurFrequency and RTMpGetMaxFrequency.
*
* @returns The desired frequency on success, 0 on failure.
@@ -126,10 +214,10 @@ static DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser1, void *pvUser2)
* @param idCpu The CPU ID.
* @param pszStatName The cpu_info stat name.
*/
-static uint64_t rtMpSolarisGetFrequency(RTCPUID idCpu, char *pszStatName)
+static uint64_t rtMpSolarisGetFrequency(RTCPUID idCpu, const char *pszStatName)
{
uint64_t u64 = 0;
- int rc = RTOnce(&g_MpSolarisOnce, rtMpSolarisOnce, NULL, NULL);
+ int rc = RTOnceEx(&g_MpSolarisOnce, rtMpSolarisOnce, rtMpSolarisCleanUp, NULL /* pvUser */);
if (RT_SUCCESS(rc))
{
if ( idCpu < g_capCpuInfo
@@ -141,7 +229,8 @@ static uint64_t rtMpSolarisGetFrequency(RTCPUID idCpu, char *pszStatName)
{
if (kstat_read(g_pKsCtl, g_papCpuInfo[idCpu], 0) != -1)
{
- kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(g_papCpuInfo[idCpu], pszStatName);
+ /* Solaris really need to fix their APIs. Explicitly cast for now. */
+ kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(g_papCpuInfo[idCpu], (char*)pszStatName);
if (pStat)
{
Assert(pStat->data_type == KSTAT_DATA_UINT64 || pStat->data_type == KSTAT_DATA_LONG);
@@ -280,7 +369,7 @@ RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
RTDECL(PRTCPUSET) RTMpGetPresentSet(PRTCPUSET pSet)
{
#ifdef RT_STRICT
- long cCpusPresent = 0;
+ RTCPUID cCpusPresent = 0;
#endif
RTCpuSetEmpty(pSet);
RTCPUID cCpus = RTMpGetCount();
@@ -305,3 +394,60 @@ RTDECL(RTCPUID) RTMpGetPresentCount(void)
return sysconf(_SC_NPROCESSORS_CONF);
}
+
+RTDECL(RTCPUID) RTMpGetPresentCoreCount(void)
+{
+ return RTMpGetCoreCount();
+}
+
+
+RTDECL(RTCPUID) RTMpGetCoreCount(void)
+{
+ int rc = RTOnceEx(&g_MpSolarisOnce, rtMpSolarisOnce, rtMpSolarisCleanUp, NULL /* pvUser */);
+ if (RT_SUCCESS(rc))
+ return g_cCores;
+
+ return 0;
+}
+
+
+RTDECL(RTCPUID) RTMpGetOnlineCoreCount(void)
+{
+ RTCPUID uOnlineCores = 0;
+ int rc = RTOnceEx(&g_MpSolarisOnce, rtMpSolarisOnce, rtMpSolarisCleanUp, NULL /* pvUser */);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTCritSectEnter(&g_MpSolarisCritSect);
+ AssertRC(rc);
+
+ /*
+ * For each core in the system, count how many are currently online.
+ */
+ for (RTCPUID j = 0; j < g_cCores; j++)
+ {
+ uint64_t u64CoreId = g_pu64CoreIds[j];
+ for (RTCPUID idCpu = 0; idCpu < g_capCpuInfo; idCpu++)
+ {
+ rc = kstat_read(g_pKsCtl, g_papCpuInfo[idCpu], 0);
+ AssertReturn(rc != -1, 0 /* rc */);
+ uint64_t u64ThreadCoreId = rtMpSolarisGetCoreId(idCpu);
+ if (u64ThreadCoreId == u64CoreId)
+ {
+ kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(g_papCpuInfo[idCpu], (char *)"state");
+ Assert(pStat->data_type == KSTAT_DATA_CHAR);
+ if( !RTStrNCmp(pStat->value.c, PS_ONLINE, sizeof(PS_ONLINE) - 1)
+ || !RTStrNCmp(pStat->value.c, PS_NOINTR, sizeof(PS_NOINTR) - 1))
+ {
+ uOnlineCores++;
+ break; /* Move to the next core. We have at least 1 hyperthread online in the current core. */
+ }
+ }
+ }
+ }
+
+ RTCritSectLeave(&g_MpSolarisCritSect);
+ }
+
+ return uOnlineCores;
+}
+
diff --git a/src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp b/src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp
index 40baf8c2..ffaad258 100644
--- a/src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp
+++ b/src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2008 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/solaris/systemmem-solaris.cpp b/src/VBox/Runtime/r3/solaris/systemmem-solaris.cpp
new file mode 100644
index 00000000..e5efe631
--- /dev/null
+++ b/src/VBox/Runtime/r3/solaris/systemmem-solaris.cpp
@@ -0,0 +1,172 @@
+/* $Id: systemmem-solaris.cpp $ */
+/** @file
+ * IPRT - RTSystemQueryTotalRam, Solaris ring-3.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include <iprt/system.h>
+#include "internal/iprt.h"
+
+#include <iprt/err.h>
+#include <iprt/assert.h>
+#include <iprt/critsect.h>
+#include <iprt/once.h>
+#include <iprt/param.h>
+
+#include <errno.h>
+#include <kstat.h>
+
+
+/*******************************************************************************
+* Global Variables *
+*******************************************************************************/
+/** Initialize globals once. */
+static RTONCE g_rtSysMemSolInitOnce = RTONCE_INITIALIZER;
+/** Critical section serializing access to g_pKStatCtl and the other handles. */
+static RTCRITSECT g_rtSysMemSolCritSect;
+/** The kstate control handle. */
+static kstat_ctl_t *g_pKStatCtl = NULL;
+/** The unix.system_pages handle. */
+static kstat_t *g_pUnixSysPages = NULL;
+/** The zfs.archstats handle. */
+static kstat_t *g_pZfsArcStats = NULL;
+
+
+/** @callback_method_impl{FNRTONCE} */
+static DECLCALLBACK(int) rtSysMemSolInit(void *pvUser)
+{
+ int rc = RTCritSectInit(&g_rtSysMemSolCritSect);
+ if (RT_SUCCESS(rc))
+ {
+ g_pKStatCtl = kstat_open();
+ if (g_pKStatCtl)
+ {
+ g_pUnixSysPages = kstat_lookup(g_pKStatCtl, (char *)"unix", 0, (char *)"system_pages");
+ if (g_pUnixSysPages)
+ {
+ g_pZfsArcStats = kstat_lookup(g_pKStatCtl, (char *)"zfs", 0, (char *)"arcstats"); /* allow NULL */
+ return VINF_SUCCESS;
+ }
+
+ rc = RTErrConvertFromErrno(errno);
+ kstat_close(g_pKStatCtl);
+ g_pKStatCtl = NULL;
+ }
+ else
+ rc = RTErrConvertFromErrno(errno);
+ }
+ return rc;
+}
+
+
+/** @callback_method_impl{FNRTONCECLEANUP} */
+static DECLCALLBACK(void) rtSysMemSolCleanUp(void *pvUser, bool fLazyCleanUpOk)
+{
+ RTCritSectDelete(&g_rtSysMemSolCritSect);
+
+ kstat_close(g_pKStatCtl);
+ g_pKStatCtl = NULL;
+ g_pUnixSysPages = NULL;
+ g_pZfsArcStats = NULL;
+
+ NOREF(pvUser); NOREF(fLazyCleanUpOk);
+}
+
+
+
+RTDECL(int) RTSystemQueryTotalRam(uint64_t *pcb)
+{
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+
+ int rc = RTOnceEx(&g_rtSysMemSolInitOnce, rtSysMemSolInit, rtSysMemSolCleanUp, NULL);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTCritSectEnter(&g_rtSysMemSolCritSect);
+ if (RT_SUCCESS(rc))
+ {
+ if (kstat_read(g_pKStatCtl, g_pUnixSysPages, NULL) != -1)
+ {
+ kstat_named_t *pData = (kstat_named_t *)kstat_data_lookup(g_pUnixSysPages, (char *)"physmem");
+ if (pData)
+ *pcb = (uint64_t)pData->value.ul * PAGE_SIZE;
+ else
+ rc = RTErrConvertFromErrno(errno);
+ }
+ else
+ rc = RTErrConvertFromErrno(errno);
+ RTCritSectLeave(&g_rtSysMemSolCritSect);
+ }
+ }
+ return rc;
+}
+
+
+RTDECL(int) RTSystemQueryAvailableRam(uint64_t *pcb)
+{
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+
+ int rc = RTOnceEx(&g_rtSysMemSolInitOnce, rtSysMemSolInit, rtSysMemSolCleanUp, NULL);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTCritSectEnter(&g_rtSysMemSolCritSect);
+ if (RT_SUCCESS(rc))
+ {
+ if (kstat_read(g_pKStatCtl, g_pUnixSysPages, NULL) != -1)
+ {
+ kstat_named_t *pData = (kstat_named_t *)kstat_data_lookup(g_pUnixSysPages, (char *)"freemem");
+ if (pData)
+ {
+ *pcb = (uint64_t)pData->value.ul * PAGE_SIZE;
+
+ /*
+ * Adjust for ZFS greedyness if possible.
+ * (c_min is the target minimum size of the cache, it is not
+ * an absolute minimum.)
+ */
+ if ( g_pZfsArcStats
+ && kstat_read(g_pKStatCtl, g_pZfsArcStats, NULL) != -1)
+ {
+ kstat_named_t *pCurSize = (kstat_named_t *)kstat_data_lookup(g_pZfsArcStats, (char *)"size");
+ kstat_named_t *pMinSize = (kstat_named_t *)kstat_data_lookup(g_pZfsArcStats, (char *)"c_min");
+ if ( pCurSize
+ && pMinSize
+ && pCurSize->value.ul > pMinSize->value.ul)
+ {
+ *pcb += pCurSize->value.ul - pMinSize->value.ul;
+ }
+ }
+ }
+ else
+ rc = RTErrConvertFromErrno(errno);
+ }
+
+ RTCritSectLeave(&g_rtSysMemSolCritSect);
+ }
+ }
+ return rc;
+}
+