3bad884471a4755d52abffc98cc326f153750ca1vboxsync/* $Id$ */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/** @file
844cd568b34737db015068632c9131c25f9b6578vboxsync * IPRT - Solaris Ring-0 Driver Helpers for Event Semaphore Waits.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/*
c8d782151b3a3e0be03e5dfc8b9b3ebbd8e65eb0vboxsync * Copyright (C) 2006-2014 Oracle Corporation
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * available from http://www.virtualbox.org. This file is free software;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * you can redistribute it and/or modify it under the terms of the GNU
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * General Public License (GPL) as published by the Free Software
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * The contents of this file may alternatively be used under the terms
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * of the Common Development and Distribution License Version 1.0
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * VirtualBox OSE distribution, in which case the provisions of the
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * CDDL are applicable instead of those of the GPL.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * You may elect to license modified versions of this file under the
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * terms and conditions of either the GPL or the CDDL or both.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#ifndef ___r0drv_solaris_semeventwait_r0drv_solaris_h
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#define ___r0drv_solaris_semeventwait_r0drv_solaris_h
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include "the-solaris-kernel.h"
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <iprt/err.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <iprt/string.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <iprt/time.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync/** The resolution (nanoseconds) specified when using timeout_generic. */
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync#define RTR0SEMSOLWAIT_RESOLUTION 50000
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync
4030b8473736055cd02947418ef4f8f9b1945323vboxsync/** Disables the cyclic fallback code for old S10 installs - see @bugref{5342}.
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * @todo Fixed by @bugref{5595}, can be reenabled after checking out
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * CY_HIGH_LEVEL. */
4030b8473736055cd02947418ef4f8f9b1945323vboxsync#define RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync
48f43c5b6dd4cb9f5edfc0ec82720e0954b29d29vboxsync#define SOL_THREAD_TINTR_PTR ((kthread_t **)((char *)curthread + g_offrtSolThreadIntrThread))
48f43c5b6dd4cb9f5edfc0ec82720e0954b29d29vboxsync
48f43c5b6dd4cb9f5edfc0ec82720e0954b29d29vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Solaris semaphore wait structure.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsynctypedef struct RTR0SEMSOLWAIT
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync /** The absolute timeout given as nanoseconds since the start of the
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * monotonic clock. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync uint64_t uNsAbsTimeout;
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync /** The timeout in nanoseconds relative to the start of the wait. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync uint64_t cNsRelTimeout;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /** The native timeout value. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync union
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
c8d782151b3a3e0be03e5dfc8b9b3ebbd8e65eb0vboxsync /** The timeout (in ticks) when fHighRes is false. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync clock_t lTimeout;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync } u;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /** Set if we use high resolution timeouts. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync bool fHighRes;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /** Set if it's an indefinite wait. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync bool fIndefinite;
4030b8473736055cd02947418ef4f8f9b1945323vboxsync /** Set if the waiting thread is ready to be woken up.
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * Avoids false setrun() calls due to temporary mutex exits. */
4030b8473736055cd02947418ef4f8f9b1945323vboxsync bool volatile fWantWakeup;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /** Set if we've already timed out.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Set by rtR0SemSolWaitDoIt or rtR0SemSolWaitHighResTimeout, read by
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * rtR0SemSolWaitHasTimedOut. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync bool volatile fTimedOut;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /** Whether the wait was interrupted. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync bool fInterrupted;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /** Interruptible or uninterruptible wait. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync bool fInterruptible;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /** The thread to wake up. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync kthread_t *pThread;
4030b8473736055cd02947418ef4f8f9b1945323vboxsync#ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /** Cylic timer ID (used by the timeout callback). */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync cyclic_id_t idCy;
81631dabcaa76e2e48221548b08c71bd7ed6f2ecvboxsync#endif
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync /** The mutex associated with the condition variable wait. */
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync void volatile *pvMtx;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync} RTR0SEMSOLWAIT;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/** Pointer to a solaris semaphore wait structure. */
3bad884471a4755d52abffc98cc326f153750ca1vboxsynctypedef RTR0SEMSOLWAIT *PRTR0SEMSOLWAIT;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Initializes a wait.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * The caller MUST check the wait condition BEFORE calling this function or the
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * timeout logic will be flawed.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @returns VINF_SUCCESS or VERR_TIMEOUT.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pWait The wait structure.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param fFlags The wait flags.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param uTimeout The timeout.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pWaitQueue The wait queue head.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncDECLINLINE(int) rtR0SemSolWaitInit(PRTR0SEMSOLWAIT pWait, uint32_t fFlags, uint64_t uTimeout)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /*
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Process the flags and timeout.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (fFlags & RTSEMWAIT_FLAGS_MILLISECS)
c8d782151b3a3e0be03e5dfc8b9b3ebbd8e65eb0vboxsync uTimeout = uTimeout < UINT64_MAX / RT_NS_1MS
c8d782151b3a3e0be03e5dfc8b9b3ebbd8e65eb0vboxsync ? uTimeout * RT_NS_1MS
3bad884471a4755d52abffc98cc326f153750ca1vboxsync : UINT64_MAX;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (uTimeout == UINT64_MAX)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync else
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync uint64_t u64Now;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (fFlags & RTSEMWAIT_FLAGS_RELATIVE)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (uTimeout == 0)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return VERR_TIMEOUT;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync u64Now = RTTimeSystemNanoTS();
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->cNsRelTimeout = uTimeout;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->uNsAbsTimeout = u64Now + uTimeout;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (pWait->uNsAbsTimeout < u64Now) /* overflow */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync else
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync u64Now = RTTimeSystemNanoTS();
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (u64Now >= uTimeout)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return VERR_TIMEOUT;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->cNsRelTimeout = uTimeout - u64Now;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->uNsAbsTimeout = uTimeout;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->fIndefinite = false;
81631dabcaa76e2e48221548b08c71bd7ed6f2ecvboxsync if ( ( (fFlags & (RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE))
81631dabcaa76e2e48221548b08c71bd7ed6f2ecvboxsync || pWait->cNsRelTimeout < UINT32_C(1000000000) / 100 /*Hz*/ * 4)
4030b8473736055cd02947418ef4f8f9b1945323vboxsync#ifdef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK
4030b8473736055cd02947418ef4f8f9b1945323vboxsync && g_pfnrtR0Sol_timeout_generic != NULL
4030b8473736055cd02947418ef4f8f9b1945323vboxsync#endif
4030b8473736055cd02947418ef4f8f9b1945323vboxsync )
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->fHighRes = true;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync else
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync uint64_t cTicks = NSEC_TO_TICK_ROUNDUP(uTimeout);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (cTicks >= LONG_MAX)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync else
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
45a9b4f09e0ed7262f79181541297eb9e13b1e70vboxsync pWait->u.lTimeout = cTicks;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->fHighRes = false;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->fIndefinite = true;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->fHighRes = false;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->uNsAbsTimeout = UINT64_MAX;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->cNsRelTimeout = UINT64_MAX;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->u.lTimeout = LONG_MAX;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
4030b8473736055cd02947418ef4f8f9b1945323vboxsync pWait->fWantWakeup = false;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->fTimedOut = false;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->fInterrupted = false;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->fInterruptible = !!(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->pThread = curthread;
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync pWait->pvMtx = NULL;
4030b8473736055cd02947418ef4f8f9b1945323vboxsync#ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->idCy = CYCLIC_NONE;
81631dabcaa76e2e48221548b08c71bd7ed6f2ecvboxsync#endif
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return VINF_SUCCESS;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync}
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
4030b8473736055cd02947418ef4f8f9b1945323vboxsync#ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Cyclic timeout callback that sets the timeout indicator and wakes up the
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * waiting thread.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pvUser The wait structure.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncstatic void rtR0SemSolWaitHighResTimeout(void *pvUser)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync PRTR0SEMSOLWAIT pWait = (PRTR0SEMSOLWAIT)pvUser;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync kthread_t *pThread = pWait->pThread;
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync kmutex_t *pMtx = (kmutex_t *)ASMAtomicReadPtr(&pWait->pvMtx);
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync if (VALID_PTR(pMtx))
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync /* Enter the mutex here to make sure the thread has gone to sleep
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync before we wake it up.
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync Note: Trying to take the cpu_lock here doesn't work. */
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync mutex_enter(pMtx);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (mutex_owner(&cpu_lock) == curthread)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync cyclic_remove(pWait->idCy);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->idCy = CYCLIC_NONE;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
4030b8473736055cd02947418ef4f8f9b1945323vboxsync bool const fWantWakeup = pWait->fWantWakeup;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync ASMAtomicWriteBool(&pWait->fTimedOut, true);
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync mutex_exit(pMtx);
4030b8473736055cd02947418ef4f8f9b1945323vboxsync
4030b8473736055cd02947418ef4f8f9b1945323vboxsync if (fWantWakeup)
4030b8473736055cd02947418ef4f8f9b1945323vboxsync setrun(pThread);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync}
81631dabcaa76e2e48221548b08c71bd7ed6f2ecvboxsync#endif
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync/**
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync * Timeout callback that sets the timeout indicator and wakes up the waiting
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync * thread.
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync *
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync * @param pvUser The wait structure.
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync */
5eb8c49f193655f19bb89b653df8643091fa987bvboxsyncstatic void rtR0SemSolWaitTimeout(void *pvUser)
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync{
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync PRTR0SEMSOLWAIT pWait = (PRTR0SEMSOLWAIT)pvUser;
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync kthread_t *pThread = pWait->pThread;
8750aef1556280f62aac28c3d97598db154b1ba6vboxsync kmutex_t *pMtx = (kmutex_t *)ASMAtomicReadPtr((void * volatile *)&pWait->pvMtx);
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync if (VALID_PTR(pMtx))
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync {
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync /* Enter the mutex here to make sure the thread has gone to sleep
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync before we wake it up. */
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync mutex_enter(pMtx);
4030b8473736055cd02947418ef4f8f9b1945323vboxsync bool const fWantWakeup = pWait->fWantWakeup;
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync ASMAtomicWriteBool(&pWait->fTimedOut, true);
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync mutex_exit(pMtx);
4030b8473736055cd02947418ef4f8f9b1945323vboxsync
4030b8473736055cd02947418ef4f8f9b1945323vboxsync if (fWantWakeup)
4030b8473736055cd02947418ef4f8f9b1945323vboxsync setrun(pThread);
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync }
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync}
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Do the actual wait.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pWait The wait structure.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pCnd The condition variable to wait on.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pMtx The mutex related to the condition variable.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * The caller has entered this.
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * @param pfState The state variable to check if have changed
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * after leaving the mutex (spinlock).
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * @param fCurState The current value of @a pfState. We'll return
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * without sleeping if @a pfState doesn't hold
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * this value after reacquiring the mutex.
3023311f6627a7ef580ad6d7b5f01f82c0e8f105vboxsync *
3023311f6627a7ef580ad6d7b5f01f82c0e8f105vboxsync * @remarks This must be call with the object mutex (spinlock) held.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
4030b8473736055cd02947418ef4f8f9b1945323vboxsyncDECLINLINE(void) rtR0SemSolWaitDoIt(PRTR0SEMSOLWAIT pWait, kcondvar_t *pCnd, kmutex_t *pMtx,
4030b8473736055cd02947418ef4f8f9b1945323vboxsync uint32_t volatile *pfState, uint32_t const fCurState)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync union
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync callout_id_t idCo;
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync timeout_id_t idTom;
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync } u;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync /*
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync * Arm the timeout callback.
4030b8473736055cd02947418ef4f8f9b1945323vboxsync *
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * We will have to leave the mutex (spinlock) when doing this because S10
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * (didn't check S11) will not correctly preserve PIL across calls to
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * timeout_generic() - @bugref{5595}. We do it for all timeout methods to
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * be on the safe side, the nice sideeffect of which is that it solves the
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * lock inversion problem found in @bugref{5342}.
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync */
4030b8473736055cd02947418ef4f8f9b1945323vboxsync bool const fHasTimeout = !pWait->fIndefinite;
4030b8473736055cd02947418ef4f8f9b1945323vboxsync bool fGoToSleep = !fHasTimeout;
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync if (fHasTimeout)
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync {
4030b8473736055cd02947418ef4f8f9b1945323vboxsync pWait->fWantWakeup = false; /* only want fTimedOut */
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync ASMAtomicWritePtr(&pWait->pvMtx, pMtx); /* atomic is paranoia */
4030b8473736055cd02947418ef4f8f9b1945323vboxsync mutex_exit(pMtx);
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync if (pWait->fHighRes)
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync {
4030b8473736055cd02947418ef4f8f9b1945323vboxsync#ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync if (g_pfnrtR0Sol_timeout_generic != NULL)
81631dabcaa76e2e48221548b08c71bd7ed6f2ecvboxsync#endif
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync {
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync /*
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync * High resolution timeout - arm a high resolution timeout callback
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync * for waking up the thread at the desired time.
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync */
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync u.idCo = g_pfnrtR0Sol_timeout_generic(CALLOUT_REALTIME, rtR0SemSolWaitTimeout, pWait,
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync pWait->uNsAbsTimeout, RTR0SEMSOLWAIT_RESOLUTION,
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync CALLOUT_FLAG_ABSOLUTE);
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync }
4030b8473736055cd02947418ef4f8f9b1945323vboxsync#ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync else
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync {
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync /*
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync * High resolution timeout - arm a one-shot cyclic for waking up
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync * the thread at the desired time.
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync */
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync cyc_handler_t Cyh;
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync Cyh.cyh_arg = pWait;
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync Cyh.cyh_func = rtR0SemSolWaitHighResTimeout;
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync Cyh.cyh_level = CY_LOW_LEVEL; /// @todo try CY_LOCK_LEVEL and CY_HIGH_LEVEL?
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync cyc_time_t Cyt;
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync Cyt.cyt_when = pWait->uNsAbsTimeout;
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync Cyt.cyt_interval = UINT64_C(1000000000) * 60;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync mutex_enter(&cpu_lock);
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync pWait->idCy = cyclic_add(&Cyh, &Cyt);
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync mutex_exit(&cpu_lock);
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync }
81631dabcaa76e2e48221548b08c71bd7ed6f2ecvboxsync#endif
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync else
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync /*
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync * Normal timeout.
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync * We're better off with our own callback like on the timeout man page,
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync * than calling cv_timedwait[_sig]().
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync */
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync u.idTom = realtime_timeout(rtR0SemSolWaitTimeout, pWait, pWait->u.lTimeout);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
4030b8473736055cd02947418ef4f8f9b1945323vboxsync
4030b8473736055cd02947418ef4f8f9b1945323vboxsync /*
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * Reacquire the mutex and check if the sleep condition still holds and
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * that we didn't already time out.
4030b8473736055cd02947418ef4f8f9b1945323vboxsync */
4030b8473736055cd02947418ef4f8f9b1945323vboxsync mutex_enter(pMtx);
4030b8473736055cd02947418ef4f8f9b1945323vboxsync pWait->fWantWakeup = true;
4030b8473736055cd02947418ef4f8f9b1945323vboxsync fGoToSleep = !ASMAtomicUoReadBool(&pWait->fTimedOut)
4030b8473736055cd02947418ef4f8f9b1945323vboxsync && ASMAtomicReadU32(pfState) == fCurState;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync /*
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * Do the waiting if that's still desirable.
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * (rc > 0 - normal wake-up; rc == 0 - interruption; rc == -1 - timeout)
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync */
4030b8473736055cd02947418ef4f8f9b1945323vboxsync if (fGoToSleep)
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync {
3023311f6627a7ef580ad6d7b5f01f82c0e8f105vboxsync if (pWait->fInterruptible)
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync {
3023311f6627a7ef580ad6d7b5f01f82c0e8f105vboxsync int rc = cv_wait_sig(pCnd, pMtx);
3023311f6627a7ef580ad6d7b5f01f82c0e8f105vboxsync if (RT_UNLIKELY(rc <= 0))
3023311f6627a7ef580ad6d7b5f01f82c0e8f105vboxsync {
3023311f6627a7ef580ad6d7b5f01f82c0e8f105vboxsync if (RT_LIKELY(rc == 0))
3023311f6627a7ef580ad6d7b5f01f82c0e8f105vboxsync pWait->fInterrupted = true;
3023311f6627a7ef580ad6d7b5f01f82c0e8f105vboxsync else
3023311f6627a7ef580ad6d7b5f01f82c0e8f105vboxsync AssertMsgFailed(("rc=%d\n", rc)); /* no timeouts, see above! */
3023311f6627a7ef580ad6d7b5f01f82c0e8f105vboxsync }
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync }
3023311f6627a7ef580ad6d7b5f01f82c0e8f105vboxsync else
3023311f6627a7ef580ad6d7b5f01f82c0e8f105vboxsync cv_wait(pCnd, pMtx);
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync }
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync /*
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync * Remove the timeout callback. Drop the lock while we're doing that
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * to reduce lock contention / deadlocks. Before dropping the lock,
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * indicate that the callback shouldn't do anything.
4030b8473736055cd02947418ef4f8f9b1945323vboxsync *
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * (Too bad we are stuck with the cv_* API here, it's doing a little
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * bit too much.)
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync */
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync if (fHasTimeout)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
4030b8473736055cd02947418ef4f8f9b1945323vboxsync pWait->fWantWakeup = false;
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync ASMAtomicWritePtr(&pWait->pvMtx, NULL);
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync mutex_exit(pMtx);
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync if (pWait->fHighRes)
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync {
4030b8473736055cd02947418ef4f8f9b1945323vboxsync#ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync if (g_pfnrtR0Sol_timeout_generic != NULL)
81631dabcaa76e2e48221548b08c71bd7ed6f2ecvboxsync#endif
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync g_pfnrtR0Sol_untimeout_generic(u.idCo, 0 /*nowait*/);
4030b8473736055cd02947418ef4f8f9b1945323vboxsync#ifndef RTR0SEMSOLWAIT_NO_OLD_S10_FALLBACK
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync else
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync {
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync mutex_enter(&cpu_lock);
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync if (pWait->idCy != CYCLIC_NONE)
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync {
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync cyclic_remove(pWait->idCy);
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync pWait->idCy = CYCLIC_NONE;
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync }
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync mutex_exit(&cpu_lock);
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync }
81631dabcaa76e2e48221548b08c71bd7ed6f2ecvboxsync#endif
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync else
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync untimeout(u.idTom);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync mutex_enter(pMtx);
5eb8c49f193655f19bb89b653df8643091fa987bvboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync}
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Checks if a solaris wait was interrupted.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @returns true / false
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pWait The wait structure.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @remarks This shall be called before the first rtR0SemSolWaitDoIt().
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncDECLINLINE(bool) rtR0SemSolWaitWasInterrupted(PRTR0SEMSOLWAIT pWait)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return pWait->fInterrupted;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync}
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Checks if a solaris wait has timed out.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @returns true / false
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pWait The wait structure.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncDECLINLINE(bool) rtR0SemSolWaitHasTimedOut(PRTR0SEMSOLWAIT pWait)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return pWait->fTimedOut;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync}
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Deletes a solaris wait.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pWait The wait structure.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncDECLINLINE(void) rtR0SemSolWaitDelete(PRTR0SEMSOLWAIT pWait)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pWait->pThread = NULL;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync}
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Enters the mutex, unpinning the underlying current thread if contended and
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * we're on an interrupt thread.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * The unpinning is done to prevent a deadlock, see s this could lead to a
5981e6935987b08737b730b63a41acc1dd696377vboxsync * deadlock (see @bugref{4259} for the full explanation)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pMtx The mutex to enter.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncDECLINLINE(void) rtR0SemSolWaitEnterMutexWithUnpinningHack(kmutex_t *pMtx)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync int fAcquired = mutex_tryenter(pMtx);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (!fAcquired)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /*
48f43c5b6dd4cb9f5edfc0ec82720e0954b29d29vboxsync * Note! This assumes nobody is using the RTThreadPreemptDisable() in an
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * interrupt context and expects it to work right. The swtch will
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * result in a voluntary preemption. To fix this, we would have to
48f43c5b6dd4cb9f5edfc0ec82720e0954b29d29vboxsync * do our own counting in RTThreadPreemptDisable/Restore() like we do
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * on systems which doesn't do preemption (OS/2, linux, ...) and
48f43c5b6dd4cb9f5edfc0ec82720e0954b29d29vboxsync * check whether preemption was disabled via RTThreadPreemptDisable()
48f43c5b6dd4cb9f5edfc0ec82720e0954b29d29vboxsync * or not and only call swtch if RTThreadPreemptDisable() wasn't called.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
48f43c5b6dd4cb9f5edfc0ec82720e0954b29d29vboxsync kthread_t **ppIntrThread = SOL_THREAD_TINTR_PTR;
48f43c5b6dd4cb9f5edfc0ec82720e0954b29d29vboxsync if ( *ppIntrThread
48f43c5b6dd4cb9f5edfc0ec82720e0954b29d29vboxsync && getpil() < DISP_LEVEL)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTThreadPreemptDisable(&PreemptState);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync preempt();
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTThreadPreemptRestore(&PreemptState);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync mutex_enter(pMtx);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync}
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync/**
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync * Gets the max resolution of the timeout machinery.
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync *
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync * @returns Resolution specified in nanoseconds.
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync */
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsyncDECLINLINE(uint32_t) rtR0SemSolWaitGetResolution(void)
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync{
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync return g_pfnrtR0Sol_timeout_generic != NULL
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync ? RTR0SEMSOLWAIT_RESOLUTION
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync : cyclic_getres();
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync}
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync
8750aef1556280f62aac28c3d97598db154b1ba6vboxsync#endif /* ___r0drv_solaris_semeventwait_r0drv_solaris_h */
8750aef1556280f62aac28c3d97598db154b1ba6vboxsync