diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-03-26 19:21:20 +0000 |
---|---|---|
committer | <> | 2014-05-08 15:03:54 +0000 |
commit | fb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch) | |
tree | c2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Runtime/r3/solaris | |
parent | 58ed4748338f9466599adfc8a9171280ed99e23f (diff) | |
download | VirtualBox-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.kup | 0 | ||||
-rw-r--r-- | src/VBox/Runtime/r3/solaris/RTSystemShutdown-solaris.cpp | 102 | ||||
-rw-r--r-- | src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp | 56 | ||||
-rw-r--r-- | src/VBox/Runtime/r3/solaris/coredumper-solaris.h | 2 | ||||
-rw-r--r-- | src/VBox/Runtime/r3/solaris/fileaio-solaris.cpp | 14 | ||||
-rw-r--r-- | src/VBox/Runtime/r3/solaris/mp-solaris.cpp | 182 | ||||
-rw-r--r-- | src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp | 2 | ||||
-rw-r--r-- | src/VBox/Runtime/r3/solaris/systemmem-solaris.cpp | 172 |
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; +} + |