semmutex-posix.cpp revision 9e5c26690d45216629b5f588aced8fcfb68c23b6
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* $Id$ */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** @file
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * innotek Portable Runtime - Mutex Semaphore, POSIX.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2007 innotek GmbH
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync *
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * The contents of this file may alternatively be used under the terms
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * of the Common Development and Distribution License Version 1.0
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * VirtualBox OSE distribution, in which case the provisions of the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * CDDL are applicable instead of those of the GPL.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * You may elect to license modified versions of this file under the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * terms and conditions of either the GPL or the CDDL or both.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Header Files *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/semaphore.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/assert.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/alloc.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/asm.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/err.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <errno.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <pthread.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <unistd.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <sys/time.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Structures and Typedefs *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** Posix internal representation of a Mutex semaphore. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstruct RTSEMMUTEXINTERNAL
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** pthread mutex. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pthread_mutex_t Mutex;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The owner of the mutex. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync volatile pthread_t Owner;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Nesting count. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync volatile uint32_t cNesting;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync};
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate a Mutex semaphore handle passed to one of the interface.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns true if valid.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns false if invalid.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pIntMutexSem Pointer to the mutex semaphore to validate.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncinline bool rtsemMutexValid(struct RTSEMMUTEXINTERNAL *pIntMutexSem)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ((uintptr_t)pIntMutexSem < 0x10000)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pIntMutexSem->cNesting == (uint32_t)~0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
cfb3a8ae5e9668de4506cf5c053b8009bcc89dafvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync int rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync * Allocate semaphore handle.
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync struct RTSEMMUTEXINTERNAL *pIntMutexSem = (struct RTSEMMUTEXINTERNAL *)RTMemAlloc(sizeof(struct RTSEMMUTEXINTERNAL));
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync if (pIntMutexSem)
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync {
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync /*
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync * Create the semaphore.
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync */
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync pthread_mutexattr_t MutexAttr;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync rc = pthread_mutexattr_init(&MutexAttr);
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync if (!rc)
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = pthread_mutex_init(&pIntMutexSem->Mutex, &MutexAttr);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!rc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pthread_mutexattr_destroy(&MutexAttr);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync pIntMutexSem->Owner = (pthread_t)-1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pIntMutexSem->cNesting = 0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync *pMutexSem = pIntMutexSem;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync return VINF_SUCCESS;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pthread_mutexattr_destroy(&MutexAttr);
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync }
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync RTMemFree(pIntMutexSem);
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync }
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync else
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync rc = VERR_NO_MEMORY;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync return rc;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync}
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsyncRTDECL(int) RTSemMutexDestroy(RTSEMMUTEX MutexSem)
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync{
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync /*
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync * Validate input.
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync */
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync if (!rtsemMutexValid(MutexSem))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync return VERR_INVALID_HANDLE;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Try destroy it.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync int rc = pthread_mutex_destroy(&pIntMutexSem->Mutex);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Failed to destroy mutex sem %p, rc=%d.\n", MutexSem, rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return RTErrConvertFromErrno(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Free the memory and be gone.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pIntMutexSem->Owner = (pthread_t)-1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pIntMutexSem->cNesting = ~0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTMemTmpFree(pIntMutexSem);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!rtsemMutexValid(MutexSem))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_INVALID_HANDLE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Check if nested request.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pthread_t Self = pthread_self();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( pIntMutexSem->Owner == Self
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && pIntMutexSem->cNesting > 0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pIntMutexSem->cNesting++;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync return VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Lock it.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cMillies == RT_INDEFINITE_WAIT)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync /* take mutex */
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync int rc = pthread_mutex_lock(&pIntMutexSem->Mutex);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync AssertMsgFailed(("Failed to lock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return RTErrConvertFromErrno(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifdef RT_OS_DARWIN
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_NOT_IMPLEMENTED;
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync#else /* !RT_OS_DARWIN */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Get current time and calc end of wait time.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync struct timespec ts = {0,0};
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync clock_gettime(CLOCK_REALTIME, &ts);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cMillies != 0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ts.tv_nsec += (cMillies % 1000) * 1000000;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ts.tv_sec += cMillies / 1000;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (ts.tv_nsec >= 1000000000)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ts.tv_nsec -= 1000000000;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ts.tv_sec++;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
61283d6341bac43f73cf33c9ec754a59f674fa19vboxsync /* take mutex */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = pthread_mutex_timedlock(&pIntMutexSem->Mutex, &ts);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsg(rc == ETIMEDOUT, ("Failed to lock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync return RTErrConvertFromErrno(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* !RT_OS_DARWIN */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Set the owner and nesting.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pIntMutexSem->Owner = Self;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ASMAtomicXchgU32(&pIntMutexSem->cNesting, 1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies)
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* EINTR isn't returned by the wait functions we're using. */
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync return RTSemMutexRequest(MutexSem, cMillies);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTSemMutexRelease(RTSEMMUTEX MutexSem)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync /*
be9bc9b4ba510c4b4159c193f783d024633ef8e9vboxsync * Validate input.
be9bc9b4ba510c4b4159c193f783d024633ef8e9vboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!rtsemMutexValid(MutexSem))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
be9bc9b4ba510c4b4159c193f783d024633ef8e9vboxsync AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_INVALID_HANDLE;
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Check if nested.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync pthread_t Self = pthread_self();
d8df004f4caf4f71e78f0be1cc2e2a918358ae9fvboxsync struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( pIntMutexSem->Owner != Self
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync || pIntMutexSem->cNesting == (uint32_t)~0)
78a205e3fc6719d59e8c561b3d287d3a4f879852vboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Not owner of mutex %p!! Self=%08x Owner=%08x cNesting=%d\n",
344f8996b5cf3f8bbc2c361f9d526eb5b1350916vboxsync pIntMutexSem, Self, pIntMutexSem->Owner, pIntMutexSem->cNesting));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_NOT_OWNER;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync /*
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync * If nested we'll just pop a nesting.
d8df004f4caf4f71e78f0be1cc2e2a918358ae9fvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pIntMutexSem->cNesting > 1)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
78a205e3fc6719d59e8c561b3d287d3a4f879852vboxsync pIntMutexSem->cNesting--;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VINF_SUCCESS;
344f8996b5cf3f8bbc2c361f9d526eb5b1350916vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Clear the state. (cNesting == 1)
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync */
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync pIntMutexSem->Owner = (pthread_t)-1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ASMAtomicXchgU32(&pIntMutexSem->cNesting, 0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Unlock mutex semaphore.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = pthread_mutex_unlock(&pIntMutexSem->Mutex);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Failed to unlock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return RTErrConvertFromErrno(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync