05afe08870681beb0792f384475077c988916762vboxsync/* $Id$ */
05afe08870681beb0792f384475077c988916762vboxsync/** @file
05afe08870681beb0792f384475077c988916762vboxsync * IPRT - Mutex Semaphores, Ring-0 Driver, Darwin.
05afe08870681beb0792f384475077c988916762vboxsync */
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2011 Oracle Corporation
05afe08870681beb0792f384475077c988916762vboxsync *
05afe08870681beb0792f384475077c988916762vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
05afe08870681beb0792f384475077c988916762vboxsync * available from http://www.virtualbox.org. This file is free software;
05afe08870681beb0792f384475077c988916762vboxsync * you can redistribute it and/or modify it under the terms of the GNU
05afe08870681beb0792f384475077c988916762vboxsync * General Public License (GPL) as published by the Free Software
05afe08870681beb0792f384475077c988916762vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
05afe08870681beb0792f384475077c988916762vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
05afe08870681beb0792f384475077c988916762vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
05afe08870681beb0792f384475077c988916762vboxsync *
05afe08870681beb0792f384475077c988916762vboxsync * The contents of this file may alternatively be used under the terms
05afe08870681beb0792f384475077c988916762vboxsync * of the Common Development and Distribution License Version 1.0
05afe08870681beb0792f384475077c988916762vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
05afe08870681beb0792f384475077c988916762vboxsync * VirtualBox OSE distribution, in which case the provisions of the
05afe08870681beb0792f384475077c988916762vboxsync * CDDL are applicable instead of those of the GPL.
05afe08870681beb0792f384475077c988916762vboxsync *
05afe08870681beb0792f384475077c988916762vboxsync * You may elect to license modified versions of this file under the
05afe08870681beb0792f384475077c988916762vboxsync * terms and conditions of either the GPL or the CDDL or both.
05afe08870681beb0792f384475077c988916762vboxsync */
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync/*******************************************************************************
05afe08870681beb0792f384475077c988916762vboxsync* Header Files *
05afe08870681beb0792f384475077c988916762vboxsync*******************************************************************************/
53b280dfb976ee84687ab9c63a01269ad74002ebvboxsync#define RTSEMMUTEX_WITHOUT_REMAPPING
05afe08870681beb0792f384475077c988916762vboxsync#include "the-darwin-kernel.h"
05afe08870681beb0792f384475077c988916762vboxsync#include "internal/iprt.h"
05afe08870681beb0792f384475077c988916762vboxsync#include <iprt/semaphore.h>
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync#include <iprt/asm.h>
a8f65e585466d1267633cea76b4f97a69b7f1cc0vboxsync#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
a8f65e585466d1267633cea76b4f97a69b7f1cc0vboxsync# include <iprt/asm-amd64-x86.h>
a8f65e585466d1267633cea76b4f97a69b7f1cc0vboxsync#endif
243cd452144a61285fc9be2bd5448698af935f13vboxsync#include <iprt/assert.h>
05afe08870681beb0792f384475077c988916762vboxsync#include <iprt/err.h>
243cd452144a61285fc9be2bd5448698af935f13vboxsync#include <iprt/mem.h>
05afe08870681beb0792f384475077c988916762vboxsync#include <iprt/thread.h>
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync#include "internal/magics.h"
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync/*******************************************************************************
05afe08870681beb0792f384475077c988916762vboxsync* Structures and Typedefs *
05afe08870681beb0792f384475077c988916762vboxsync*******************************************************************************/
05afe08870681beb0792f384475077c988916762vboxsync/**
05afe08870681beb0792f384475077c988916762vboxsync * Darwin mutex semaphore.
05afe08870681beb0792f384475077c988916762vboxsync */
05afe08870681beb0792f384475077c988916762vboxsynctypedef struct RTSEMMUTEXINTERNAL
05afe08870681beb0792f384475077c988916762vboxsync{
05afe08870681beb0792f384475077c988916762vboxsync /** Magic value (RTSEMMUTEX_MAGIC). */
05afe08870681beb0792f384475077c988916762vboxsync uint32_t volatile u32Magic;
243cd452144a61285fc9be2bd5448698af935f13vboxsync /** The number of waiting threads. */
243cd452144a61285fc9be2bd5448698af935f13vboxsync uint32_t cWaiters;
243cd452144a61285fc9be2bd5448698af935f13vboxsync /** The number of references. */
243cd452144a61285fc9be2bd5448698af935f13vboxsync uint32_t volatile cRefs;
243cd452144a61285fc9be2bd5448698af935f13vboxsync /** The number of recursions. */
243cd452144a61285fc9be2bd5448698af935f13vboxsync uint32_t cRecursions;
243cd452144a61285fc9be2bd5448698af935f13vboxsync /** The handle of the owner thread. */
243cd452144a61285fc9be2bd5448698af935f13vboxsync RTNATIVETHREAD hNativeOwner;
243cd452144a61285fc9be2bd5448698af935f13vboxsync /** The spinlock protecting us. */
243cd452144a61285fc9be2bd5448698af935f13vboxsync lck_spin_t *pSpinlock;
05afe08870681beb0792f384475077c988916762vboxsync} RTSEMMUTEXINTERNAL, *PRTSEMMUTEXINTERNAL;
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsyncRTDECL(int) RTSemMutexCreate(PRTSEMMUTEX phMutexSem)
243cd452144a61285fc9be2bd5448698af935f13vboxsync{
243cd452144a61285fc9be2bd5448698af935f13vboxsync return RTSemMutexCreateEx(phMutexSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
243cd452144a61285fc9be2bd5448698af935f13vboxsync}
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsyncRTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags,
243cd452144a61285fc9be2bd5448698af935f13vboxsync RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
05afe08870681beb0792f384475077c988916762vboxsync{
243cd452144a61285fc9be2bd5448698af935f13vboxsync AssertReturn(!(fFlags & ~RTSEMMUTEX_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
05afe08870681beb0792f384475077c988916762vboxsync RT_ASSERT_PREEMPTIBLE();
243cd452144a61285fc9be2bd5448698af935f13vboxsync
05afe08870681beb0792f384475077c988916762vboxsync AssertCompile(sizeof(RTSEMMUTEXINTERNAL) > sizeof(void *));
05afe08870681beb0792f384475077c988916762vboxsync PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)RTMemAlloc(sizeof(*pThis));
05afe08870681beb0792f384475077c988916762vboxsync if (pThis)
05afe08870681beb0792f384475077c988916762vboxsync {
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->u32Magic = RTSEMMUTEX_MAGIC;
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->cWaiters = 0;
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->cRefs = 1;
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->cRecursions = 0;
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->hNativeOwner = NIL_RTNATIVETHREAD;
05afe08870681beb0792f384475077c988916762vboxsync Assert(g_pDarwinLockGroup);
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->pSpinlock = lck_spin_alloc_init(g_pDarwinLockGroup, LCK_ATTR_NULL);
243cd452144a61285fc9be2bd5448698af935f13vboxsync if (pThis->pSpinlock)
05afe08870681beb0792f384475077c988916762vboxsync {
243cd452144a61285fc9be2bd5448698af935f13vboxsync *phMutexSem = pThis;
05afe08870681beb0792f384475077c988916762vboxsync return VINF_SUCCESS;
05afe08870681beb0792f384475077c988916762vboxsync }
243cd452144a61285fc9be2bd5448698af935f13vboxsync
05afe08870681beb0792f384475077c988916762vboxsync RTMemFree(pThis);
05afe08870681beb0792f384475077c988916762vboxsync }
05afe08870681beb0792f384475077c988916762vboxsync return VERR_NO_MEMORY;
05afe08870681beb0792f384475077c988916762vboxsync}
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync/**
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Called when the refcount reaches zero.
243cd452144a61285fc9be2bd5448698af935f13vboxsync */
243cd452144a61285fc9be2bd5448698af935f13vboxsyncstatic void rtSemMutexDarwinFree(PRTSEMMUTEXINTERNAL pThis)
243cd452144a61285fc9be2bd5448698af935f13vboxsync{
243cd452144a61285fc9be2bd5448698af935f13vboxsync lck_spin_unlock(pThis->pSpinlock);
243cd452144a61285fc9be2bd5448698af935f13vboxsync lck_spin_destroy(pThis->pSpinlock, g_pDarwinLockGroup);
243cd452144a61285fc9be2bd5448698af935f13vboxsync RTMemFree(pThis);
243cd452144a61285fc9be2bd5448698af935f13vboxsync}
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync
05afe08870681beb0792f384475077c988916762vboxsyncRTDECL(int) RTSemMutexDestroy(RTSEMMUTEX hMutexSem)
05afe08870681beb0792f384475077c988916762vboxsync{
05afe08870681beb0792f384475077c988916762vboxsync /*
05afe08870681beb0792f384475077c988916762vboxsync * Validate input.
05afe08870681beb0792f384475077c988916762vboxsync */
05afe08870681beb0792f384475077c988916762vboxsync PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)hMutexSem;
2c2a4a499b956f8a56863a7a5b8113cfbdfbe049vboxsync if (pThis == NIL_RTSEMMUTEX)
05afe08870681beb0792f384475077c988916762vboxsync return VERR_INVALID_PARAMETER;
05afe08870681beb0792f384475077c988916762vboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
243cd452144a61285fc9be2bd5448698af935f13vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
05afe08870681beb0792f384475077c988916762vboxsync RT_ASSERT_INTS_ON();
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync /*
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Kill it, wake up all waiting threads and release the reference.
05afe08870681beb0792f384475077c988916762vboxsync */
243cd452144a61285fc9be2bd5448698af935f13vboxsync AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTSEMMUTEX_MAGIC, RTSEMMUTEX_MAGIC), VERR_INVALID_HANDLE);
243cd452144a61285fc9be2bd5448698af935f13vboxsync lck_spin_lock(pThis->pSpinlock);
05afe08870681beb0792f384475077c988916762vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync if (pThis->cWaiters > 0)
243cd452144a61285fc9be2bd5448698af935f13vboxsync thread_wakeup_prim((event_t)pThis, FALSE /* one_thread */, THREAD_RESTART);
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync if (ASMAtomicDecU32(&pThis->cRefs) == 0)
243cd452144a61285fc9be2bd5448698af935f13vboxsync rtSemMutexDarwinFree(pThis);
243cd452144a61285fc9be2bd5448698af935f13vboxsync else
243cd452144a61285fc9be2bd5448698af935f13vboxsync lck_spin_unlock(pThis->pSpinlock);
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync return VINF_SUCCESS;
05afe08870681beb0792f384475077c988916762vboxsync}
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync/**
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Internal worker for the sleep scenario.
243cd452144a61285fc9be2bd5448698af935f13vboxsync *
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Called owning the spinlock, returns without it.
243cd452144a61285fc9be2bd5448698af935f13vboxsync *
243cd452144a61285fc9be2bd5448698af935f13vboxsync * @returns IPRT status code.
243cd452144a61285fc9be2bd5448698af935f13vboxsync * @param pThis The mutex instance.
243cd452144a61285fc9be2bd5448698af935f13vboxsync * @param cMillies The timeout.
243cd452144a61285fc9be2bd5448698af935f13vboxsync * @param fInterruptible Whether it's interruptible
243cd452144a61285fc9be2bd5448698af935f13vboxsync * (RTSemMutexRequestNoResume) or not
243cd452144a61285fc9be2bd5448698af935f13vboxsync * (RTSemMutexRequest).
243cd452144a61285fc9be2bd5448698af935f13vboxsync * @param hNativeSelf The thread handle of the caller.
243cd452144a61285fc9be2bd5448698af935f13vboxsync */
243cd452144a61285fc9be2bd5448698af935f13vboxsyncstatic int rtR0SemMutexDarwinRequestSleep(PRTSEMMUTEXINTERNAL pThis, RTMSINTERVAL cMillies,
243cd452144a61285fc9be2bd5448698af935f13vboxsync wait_interrupt_t fInterruptible, RTNATIVETHREAD hNativeSelf)
05afe08870681beb0792f384475077c988916762vboxsync{
05afe08870681beb0792f384475077c988916762vboxsync /*
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Grab a reference and indicate that we're waiting.
05afe08870681beb0792f384475077c988916762vboxsync */
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->cWaiters++;
243cd452144a61285fc9be2bd5448698af935f13vboxsync ASMAtomicIncU32(&pThis->cRefs);
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync /*
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Go to sleep, use the address of the mutex instance as sleep/blocking/event id.
05afe08870681beb0792f384475077c988916762vboxsync */
243cd452144a61285fc9be2bd5448698af935f13vboxsync wait_result_t rcWait;
05afe08870681beb0792f384475077c988916762vboxsync if (cMillies == RT_INDEFINITE_WAIT)
243cd452144a61285fc9be2bd5448698af935f13vboxsync rcWait = lck_spin_sleep(pThis->pSpinlock, LCK_SLEEP_DEFAULT, (event_t)pThis, fInterruptible);
05afe08870681beb0792f384475077c988916762vboxsync else
05afe08870681beb0792f384475077c988916762vboxsync {
243cd452144a61285fc9be2bd5448698af935f13vboxsync uint64_t u64AbsTime;
243cd452144a61285fc9be2bd5448698af935f13vboxsync nanoseconds_to_absolutetime(cMillies * UINT64_C(1000000), &u64AbsTime);
243cd452144a61285fc9be2bd5448698af935f13vboxsync u64AbsTime += mach_absolute_time();
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync rcWait = lck_spin_sleep_deadline(pThis->pSpinlock, LCK_SLEEP_DEFAULT,
243cd452144a61285fc9be2bd5448698af935f13vboxsync (event_t)pThis, fInterruptible, u64AbsTime);
05afe08870681beb0792f384475077c988916762vboxsync }
243cd452144a61285fc9be2bd5448698af935f13vboxsync /*
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Translate the rc.
243cd452144a61285fc9be2bd5448698af935f13vboxsync */
243cd452144a61285fc9be2bd5448698af935f13vboxsync int rc;
243cd452144a61285fc9be2bd5448698af935f13vboxsync switch (rcWait)
05afe08870681beb0792f384475077c988916762vboxsync {
243cd452144a61285fc9be2bd5448698af935f13vboxsync case THREAD_AWAKENED:
243cd452144a61285fc9be2bd5448698af935f13vboxsync if (RT_LIKELY(pThis->u32Magic == RTSEMMUTEX_MAGIC))
243cd452144a61285fc9be2bd5448698af935f13vboxsync {
243cd452144a61285fc9be2bd5448698af935f13vboxsync if (RT_LIKELY( pThis->cRecursions == 0
243cd452144a61285fc9be2bd5448698af935f13vboxsync && pThis->hNativeOwner == NIL_RTNATIVETHREAD))
243cd452144a61285fc9be2bd5448698af935f13vboxsync {
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->cRecursions = 1;
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->hNativeOwner = hNativeSelf;
243cd452144a61285fc9be2bd5448698af935f13vboxsync rc = VINF_SUCCESS;
243cd452144a61285fc9be2bd5448698af935f13vboxsync }
243cd452144a61285fc9be2bd5448698af935f13vboxsync else
243cd452144a61285fc9be2bd5448698af935f13vboxsync {
243cd452144a61285fc9be2bd5448698af935f13vboxsync Assert(pThis->cRecursions == 0);
243cd452144a61285fc9be2bd5448698af935f13vboxsync Assert(pThis->hNativeOwner == NIL_RTNATIVETHREAD);
243cd452144a61285fc9be2bd5448698af935f13vboxsync rc = VERR_INTERNAL_ERROR_3;
243cd452144a61285fc9be2bd5448698af935f13vboxsync }
243cd452144a61285fc9be2bd5448698af935f13vboxsync }
243cd452144a61285fc9be2bd5448698af935f13vboxsync else
243cd452144a61285fc9be2bd5448698af935f13vboxsync rc = VERR_SEM_DESTROYED;
243cd452144a61285fc9be2bd5448698af935f13vboxsync break;
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync case THREAD_TIMED_OUT:
243cd452144a61285fc9be2bd5448698af935f13vboxsync Assert(cMillies != RT_INDEFINITE_WAIT);
243cd452144a61285fc9be2bd5448698af935f13vboxsync rc = VERR_TIMEOUT;
243cd452144a61285fc9be2bd5448698af935f13vboxsync break;
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync case THREAD_INTERRUPTED:
243cd452144a61285fc9be2bd5448698af935f13vboxsync Assert(fInterruptible);
243cd452144a61285fc9be2bd5448698af935f13vboxsync rc = VERR_INTERRUPTED;
243cd452144a61285fc9be2bd5448698af935f13vboxsync break;
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync case THREAD_RESTART:
243cd452144a61285fc9be2bd5448698af935f13vboxsync Assert(pThis->u32Magic == ~RTSEMMUTEX_MAGIC);
243cd452144a61285fc9be2bd5448698af935f13vboxsync rc = VERR_SEM_DESTROYED;
243cd452144a61285fc9be2bd5448698af935f13vboxsync break;
243cd452144a61285fc9be2bd5448698af935f13vboxsync
05afe08870681beb0792f384475077c988916762vboxsync default:
243cd452144a61285fc9be2bd5448698af935f13vboxsync AssertMsgFailed(("rcWait=%d\n", rcWait));
243cd452144a61285fc9be2bd5448698af935f13vboxsync rc = VERR_GENERAL_FAILURE;
243cd452144a61285fc9be2bd5448698af935f13vboxsync break;
05afe08870681beb0792f384475077c988916762vboxsync }
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync /*
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Dereference it and quit the lock.
243cd452144a61285fc9be2bd5448698af935f13vboxsync */
243cd452144a61285fc9be2bd5448698af935f13vboxsync Assert(pThis->cWaiters > 0);
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->cWaiters--;
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync Assert(pThis->cRefs > 0);
243cd452144a61285fc9be2bd5448698af935f13vboxsync if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
243cd452144a61285fc9be2bd5448698af935f13vboxsync rtSemMutexDarwinFree(pThis);
243cd452144a61285fc9be2bd5448698af935f13vboxsync else
243cd452144a61285fc9be2bd5448698af935f13vboxsync lck_spin_unlock(pThis->pSpinlock);
243cd452144a61285fc9be2bd5448698af935f13vboxsync return rc;
243cd452144a61285fc9be2bd5448698af935f13vboxsync}
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync/**
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Internal worker for RTSemMutexRequest and RTSemMutexRequestNoResume
243cd452144a61285fc9be2bd5448698af935f13vboxsync *
243cd452144a61285fc9be2bd5448698af935f13vboxsync * @returns IPRT status code.
243cd452144a61285fc9be2bd5448698af935f13vboxsync * @param hMutexSem The mutex handle.
243cd452144a61285fc9be2bd5448698af935f13vboxsync * @param cMillies The timeout.
243cd452144a61285fc9be2bd5448698af935f13vboxsync * @param fInterruptible Whether it's interruptible
243cd452144a61285fc9be2bd5448698af935f13vboxsync * (RTSemMutexRequestNoResume) or not
243cd452144a61285fc9be2bd5448698af935f13vboxsync * (RTSemMutexRequest).
243cd452144a61285fc9be2bd5448698af935f13vboxsync */
243cd452144a61285fc9be2bd5448698af935f13vboxsyncDECLINLINE(int) rtR0SemMutexDarwinRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, wait_interrupt_t fInterruptible)
243cd452144a61285fc9be2bd5448698af935f13vboxsync{
243cd452144a61285fc9be2bd5448698af935f13vboxsync /*
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Validate input.
243cd452144a61285fc9be2bd5448698af935f13vboxsync */
243cd452144a61285fc9be2bd5448698af935f13vboxsync PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)hMutexSem;
243cd452144a61285fc9be2bd5448698af935f13vboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
243cd452144a61285fc9be2bd5448698af935f13vboxsync AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
243cd452144a61285fc9be2bd5448698af935f13vboxsync RT_ASSERT_PREEMPTIBLE();
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync /*
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Grab the lock and check out the state.
243cd452144a61285fc9be2bd5448698af935f13vboxsync */
243cd452144a61285fc9be2bd5448698af935f13vboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
243cd452144a61285fc9be2bd5448698af935f13vboxsync int rc = VINF_SUCCESS;
243cd452144a61285fc9be2bd5448698af935f13vboxsync lck_spin_lock(pThis->pSpinlock);
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync /* Recursive call? */
243cd452144a61285fc9be2bd5448698af935f13vboxsync if (pThis->hNativeOwner == hNativeSelf)
243cd452144a61285fc9be2bd5448698af935f13vboxsync {
243cd452144a61285fc9be2bd5448698af935f13vboxsync Assert(pThis->cRecursions > 0);
243cd452144a61285fc9be2bd5448698af935f13vboxsync Assert(pThis->cRecursions < 256);
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->cRecursions++;
243cd452144a61285fc9be2bd5448698af935f13vboxsync }
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync /* Is it free and nobody ahead of us in the queue? */
243cd452144a61285fc9be2bd5448698af935f13vboxsync else if ( pThis->hNativeOwner == NIL_RTNATIVETHREAD
243cd452144a61285fc9be2bd5448698af935f13vboxsync && pThis->cWaiters == 0)
243cd452144a61285fc9be2bd5448698af935f13vboxsync {
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->hNativeOwner = hNativeSelf;
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->cRecursions = 1;
243cd452144a61285fc9be2bd5448698af935f13vboxsync }
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync /* Polling call? */
243cd452144a61285fc9be2bd5448698af935f13vboxsync else if (cMillies == 0)
243cd452144a61285fc9be2bd5448698af935f13vboxsync rc = VERR_TIMEOUT;
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync /* Yawn, time for a nap... */
243cd452144a61285fc9be2bd5448698af935f13vboxsync else
243cd452144a61285fc9be2bd5448698af935f13vboxsync return rtR0SemMutexDarwinRequestSleep(pThis, cMillies, fInterruptible, hNativeSelf);
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync lck_spin_unlock(pThis->pSpinlock);
243cd452144a61285fc9be2bd5448698af935f13vboxsync return rc;
243cd452144a61285fc9be2bd5448698af935f13vboxsync}
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsyncRTDECL(int) RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
243cd452144a61285fc9be2bd5448698af935f13vboxsync{
243cd452144a61285fc9be2bd5448698af935f13vboxsync return rtR0SemMutexDarwinRequest(hMutexSem, cMillies, THREAD_UNINT);
243cd452144a61285fc9be2bd5448698af935f13vboxsync}
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsyncRTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
243cd452144a61285fc9be2bd5448698af935f13vboxsync{
243cd452144a61285fc9be2bd5448698af935f13vboxsync return RTSemMutexRequest(hMutexSem, cMillies);
243cd452144a61285fc9be2bd5448698af935f13vboxsync}
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsyncRTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies)
243cd452144a61285fc9be2bd5448698af935f13vboxsync{
243cd452144a61285fc9be2bd5448698af935f13vboxsync return rtR0SemMutexDarwinRequest(hMutexSem, cMillies, THREAD_ABORTSAFE);
243cd452144a61285fc9be2bd5448698af935f13vboxsync}
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsyncRTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
243cd452144a61285fc9be2bd5448698af935f13vboxsync{
243cd452144a61285fc9be2bd5448698af935f13vboxsync return RTSemMutexRequestNoResume(hMutexSem, cMillies);
05afe08870681beb0792f384475077c988916762vboxsync}
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsyncRTDECL(int) RTSemMutexRelease(RTSEMMUTEX hMutexSem)
05afe08870681beb0792f384475077c988916762vboxsync{
05afe08870681beb0792f384475077c988916762vboxsync /*
05afe08870681beb0792f384475077c988916762vboxsync * Validate input.
05afe08870681beb0792f384475077c988916762vboxsync */
05afe08870681beb0792f384475077c988916762vboxsync PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)hMutexSem;
05afe08870681beb0792f384475077c988916762vboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
243cd452144a61285fc9be2bd5448698af935f13vboxsync AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
05afe08870681beb0792f384475077c988916762vboxsync RT_ASSERT_PREEMPTIBLE();
05afe08870681beb0792f384475077c988916762vboxsync
05afe08870681beb0792f384475077c988916762vboxsync /*
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Take the lock and do the job.
05afe08870681beb0792f384475077c988916762vboxsync */
243cd452144a61285fc9be2bd5448698af935f13vboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
243cd452144a61285fc9be2bd5448698af935f13vboxsync int rc = VINF_SUCCESS;
243cd452144a61285fc9be2bd5448698af935f13vboxsync lck_spin_lock(pThis->pSpinlock);
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync if (pThis->hNativeOwner == hNativeSelf)
243cd452144a61285fc9be2bd5448698af935f13vboxsync {
243cd452144a61285fc9be2bd5448698af935f13vboxsync Assert(pThis->cRecursions > 0);
243cd452144a61285fc9be2bd5448698af935f13vboxsync if (--pThis->cRecursions == 0)
243cd452144a61285fc9be2bd5448698af935f13vboxsync {
243cd452144a61285fc9be2bd5448698af935f13vboxsync pThis->hNativeOwner = NIL_RTNATIVETHREAD;
243cd452144a61285fc9be2bd5448698af935f13vboxsync if (pThis->cWaiters > 0)
243cd452144a61285fc9be2bd5448698af935f13vboxsync {
243cd452144a61285fc9be2bd5448698af935f13vboxsync int rc2=thread_wakeup_prim((event_t)pThis, TRUE /* one_thread */, THREAD_AWAKENED);
243cd452144a61285fc9be2bd5448698af935f13vboxsync }
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync }
243cd452144a61285fc9be2bd5448698af935f13vboxsync }
243cd452144a61285fc9be2bd5448698af935f13vboxsync else
243cd452144a61285fc9be2bd5448698af935f13vboxsync rc = VERR_NOT_OWNER;
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync lck_spin_unlock(pThis->pSpinlock);
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync AssertRC(rc);
05afe08870681beb0792f384475077c988916762vboxsync return VINF_SUCCESS;
05afe08870681beb0792f384475077c988916762vboxsync}
05afe08870681beb0792f384475077c988916762vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsyncRTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem)
243cd452144a61285fc9be2bd5448698af935f13vboxsync{
243cd452144a61285fc9be2bd5448698af935f13vboxsync /*
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Validate.
243cd452144a61285fc9be2bd5448698af935f13vboxsync */
243cd452144a61285fc9be2bd5448698af935f13vboxsync RTSEMMUTEXINTERNAL *pThis = hMutexSem;
243cd452144a61285fc9be2bd5448698af935f13vboxsync AssertPtrReturn(pThis, false);
243cd452144a61285fc9be2bd5448698af935f13vboxsync AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, false);
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync /*
243cd452144a61285fc9be2bd5448698af935f13vboxsync * Take the lock and do the check.
243cd452144a61285fc9be2bd5448698af935f13vboxsync */
243cd452144a61285fc9be2bd5448698af935f13vboxsync lck_spin_lock(pThis->pSpinlock);
243cd452144a61285fc9be2bd5448698af935f13vboxsync bool fRc = pThis->hNativeOwner != NIL_RTNATIVETHREAD;
243cd452144a61285fc9be2bd5448698af935f13vboxsync lck_spin_unlock(pThis->pSpinlock);
243cd452144a61285fc9be2bd5448698af935f13vboxsync
243cd452144a61285fc9be2bd5448698af935f13vboxsync return fRc;
243cd452144a61285fc9be2bd5448698af935f13vboxsync}
05afe08870681beb0792f384475077c988916762vboxsync