semrw-posix.cpp revision 2805b95732a8d26015a397626b96049a6e6573e7
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/* $Id$ */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/** @file
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync * IPRT - Read-Write Semaphore, POSIX.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * available from http://www.virtualbox.org. This file is free software;
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * you can redistribute it and/or modify it under the terms of the GNU
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * General Public License (GPL) as published by the Free Software
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync *
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * The contents of this file may alternatively be used under the terms
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * of the Common Development and Distribution License Version 1.0
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * VirtualBox OSE distribution, in which case the provisions of the
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * CDDL are applicable instead of those of the GPL.
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync *
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * You may elect to license modified versions of this file under the
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * terms and conditions of either the GPL or the CDDL or both.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * additional information or have any questions.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*******************************************************************************
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync* Header Files *
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync*******************************************************************************/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <iprt/semaphore.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include "internal/iprt.h"
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <iprt/asm.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <iprt/assert.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <iprt/err.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <iprt/lockvalidator.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <iprt/mem.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <iprt/thread.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <errno.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <pthread.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <unistd.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/time.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include "internal/magics.h"
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include "internal/strict.h"
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*******************************************************************************
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync* Defined Constants And Macros *
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync*******************************************************************************/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/** @todo move this to r3/posix/something.h. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifdef RT_OS_SOLARIS
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync# define ATOMIC_GET_PTHREAD_T(pvVar, pThread) ASMAtomicReadSize(pvVar, pThread)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync# define ATOMIC_SET_PTHREAD_T(pvVar, pThread) ASMAtomicWriteSize(pvVar, pThread)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncAssertCompileSize(pthread_t, sizeof(void *));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync# define ATOMIC_GET_PTHREAD_T(pvVar, pThread) do { *(pThread) = (pthread_t)ASMAtomicReadPtr((void *volatile *)pvVar); } while (0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync# define ATOMIC_SET_PTHREAD_T(pvVar, pThread) ASMAtomicWritePtr((void *volatile *)pvVar, (void *)pThread)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*******************************************************************************
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync* Structures and Typedefs *
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync*******************************************************************************/
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync/** Posix internal representation of a read-write semaphore. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstruct RTSEMRWINTERNAL
f65dabff4474710524235022d328b737f174fc1dvboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /** The usual magic. (RTSEMRW_MAGIC) */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync uint32_t u32Magic;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /** The number of readers.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * (For preventing screwing up the lock on linux). */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync uint32_t volatile cReaders;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /** Number of write recursions. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync uint32_t cWrites;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /** Number of read recursions by the writer. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync uint32_t cWriterReads;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /** The write owner of the lock. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync volatile pthread_t Writer;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /** pthread rwlock. */
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync pthread_rwlock_t RWLock;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync#ifdef RTSEMRW_STRICT
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync /** The validator record for the writer. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLOCKVALRECEXCL ValidatorWrite;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /** The validator record for the readers. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLOCKVALRECSHRD ValidatorRead;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync};
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/* No debug wrapping here. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#undef RTSemRWRequestRead
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#undef RTSemRWRequestReadNoResume
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#undef RTSemRWRequestWrite
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#undef RTSemRWRequestWriteNoResume
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(int) RTSemRWCreate(PRTSEMRW pRWSem)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int rc;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Allocate handle.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct RTSEMRWINTERNAL *pThis = (struct RTSEMRWINTERNAL *)RTMemAlloc(sizeof(struct RTSEMRWINTERNAL));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (pThis)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Create the rwlock.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pthread_rwlockattr_t Attr;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync rc = pthread_rwlockattr_init(&Attr);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (!rc)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync rc = pthread_rwlock_init(&pThis->RWLock, &Attr);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (!rc)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pThis->u32Magic = RTSEMRW_MAGIC;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pThis->cReaders = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pThis->cWrites = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pThis->cWriterReads = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pThis->Writer = (pthread_t)-1;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifdef RTSEMRW_STRICT
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLockValidatorRecExclInit(&pThis->ValidatorWrite, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, "RTSemRW", pThis, true);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLockValidatorRecSharedInit(&pThis->ValidatorRead, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, "RTSemRW", pThis, false /*fSignaller*/, true);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLockValidatorRecMakeSiblings(&pThis->ValidatorWrite.Core, &pThis->ValidatorRead.Core);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *pRWSem = pThis;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return VINF_SUCCESS;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync rc = RTErrConvertFromErrno(rc);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTMemFree(pThis);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync rc = VERR_NO_MEMORY;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rc;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(int) RTSemRWDestroy(RTSEMRW RWSem)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Validate input, nil handle is fine.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct RTSEMRWINTERNAL *pThis = RWSem;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (pThis == NIL_RTSEMRW)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return VINF_SUCCESS;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VERR_INVALID_HANDLE);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync Assert(pThis->Writer == (pthread_t)-1);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync Assert(!pThis->cReaders);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync Assert(!pThis->cWrites);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync Assert(!pThis->cWriterReads);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync /*
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * Try destroy it.
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync */
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTSEMRW_MAGIC, RTSEMRW_MAGIC), VERR_INVALID_HANDLE);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync int rc = pthread_rwlock_destroy(&pThis->RWLock);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync if (!rc)
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync {
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync#ifdef RTSEMRW_STRICT
6479169ec893c18a646cec595e4e214492d180f0vboxsync RTLockValidatorRecSharedDelete(&pThis->ValidatorRead);
6479169ec893c18a646cec595e4e214492d180f0vboxsync RTLockValidatorRecExclDelete(&pThis->ValidatorWrite);
6479169ec893c18a646cec595e4e214492d180f0vboxsync#endif
6479169ec893c18a646cec595e4e214492d180f0vboxsync RTMemFree(pThis);
6479169ec893c18a646cec595e4e214492d180f0vboxsync rc = VINF_SUCCESS;
6479169ec893c18a646cec595e4e214492d180f0vboxsync }
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync else
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASMAtomicWriteU32(&pThis->u32Magic, RTSEMRW_MAGIC);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgFailed(("Failed to destroy read-write sem %p, rc=%d.\n", RWSem, rc));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync rc = RTErrConvertFromErrno(rc);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rc;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncDECL_FORCE_INLINE(int) rtSemRWRequestRead(RTSEMRW RWSem, unsigned cMillies, PCRTLOCKVALSRCPOS pSrcPos)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Validate input.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct RTSEMRWINTERNAL *pThis = RWSem;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VERR_INVALID_HANDLE);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Check if it's the writer (implement write+read recursion).
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pthread_t Self = pthread_self();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pthread_t Writer;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (Writer == Self)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifdef RTSEMRW_STRICT
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int rc9 = RTLockValidatorRecExclRecursionMixed(&pThis->ValidatorWrite, &pThis->ValidatorRead.Core, pSrcPos);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (RT_FAILURE(rc9))
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rc9;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync Assert(pThis->cWriterReads < INT32_MAX);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pThis->cWriterReads++;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return VINF_SUCCESS;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Try lock it.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTTHREAD hThreadSelf = NIL_RTTHREAD;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (cMillies > 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifdef RTSEMRW_STRICT
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync hThreadSelf = RTThreadSelfAutoAdopt();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int rc9 = RTLockValidatorRecSharedCheckOrderAndBlocking(&pThis->ValidatorRead, hThreadSelf, pSrcPos, true,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cMillies, RTTHREADSTATE_RW_READ, true);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (RT_FAILURE(rc9))
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rc9;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync hThreadSelf = RTThreadSelf();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_READ, true);
6479169ec893c18a646cec595e4e214492d180f0vboxsync#endif
6479169ec893c18a646cec595e4e214492d180f0vboxsync }
6479169ec893c18a646cec595e4e214492d180f0vboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (cMillies == RT_INDEFINITE_WAIT)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /* take rwlock */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int rc = pthread_rwlock_rdlock(&pThis->RWLock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_READ);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (rc)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgFailed(("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return RTErrConvertFromErrno(rc);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifdef RT_OS_DARWIN
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return VERR_NOT_IMPLEMENTED;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#else /* !RT_OS_DARWIN */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Get current time and calc end of wait time.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct timespec ts = {0,0};
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync clock_gettime(CLOCK_REALTIME, &ts);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync if (cMillies != 0)
6479169ec893c18a646cec595e4e214492d180f0vboxsync {
6479169ec893c18a646cec595e4e214492d180f0vboxsync ts.tv_nsec += (cMillies % 1000) * 1000000;
6479169ec893c18a646cec595e4e214492d180f0vboxsync ts.tv_sec += cMillies / 1000;
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (ts.tv_nsec >= 1000000000)
6479169ec893c18a646cec595e4e214492d180f0vboxsync {
6479169ec893c18a646cec595e4e214492d180f0vboxsync ts.tv_nsec -= 1000000000;
6479169ec893c18a646cec595e4e214492d180f0vboxsync ts.tv_sec++;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /* take rwlock */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int rc = pthread_rwlock_timedrdlock(&pThis->RWLock, &ts);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_READ);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (rc)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return RTErrConvertFromErrno(rc);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif /* !RT_OS_DARWIN */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASMAtomicIncU32(&pThis->cReaders);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifdef RTSEMRW_STRICT
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLockValidatorRecSharedAddOwner(&pThis->ValidatorRead, hThreadSelf, pSrcPos);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return VINF_SUCCESS;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(int) RTSemRWRequestRead(RTSEMRW RWSem, unsigned cMillies)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifndef RTSEMRW_STRICT
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync return rtSemRWRequestRead(RWSem, cMillies, NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rtSemRWRequestRead(RWSem, cMillies, &SrcPos);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(int) RTSemRWRequestReadDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rtSemRWRequestRead(RWSem, cMillies, &SrcPos);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(int) RTSemRWRequestReadNoResume(RTSEMRW RWSem, unsigned cMillies)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync /* EINTR isn't returned by the wait functions we're using. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifndef RTSEMRW_STRICT
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync return rtSemRWRequestRead(RWSem, cMillies, NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rtSemRWRequestRead(RWSem, cMillies, &SrcPos);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(int) RTSemRWRequestReadNoResumeDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rtSemRWRequestRead(RWSem, cMillies, &SrcPos);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(int) RTSemRWReleaseRead(RTSEMRW RWSem)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Validate input.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct RTSEMRWINTERNAL *pThis = RWSem;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VERR_INVALID_HANDLE);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Check if it's the writer.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pthread_t Self = pthread_self();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pthread_t Writer;
2084a447d1acb619df7c393fac41b79d517e4b3dvboxsync ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (Writer == Self)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgReturn(pThis->cWriterReads > 0, ("pThis=%p\n", pThis), VERR_NOT_OWNER);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifdef RTSEMRW_STRICT
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int rc9 = RTLockValidatorRecExclUnwindMixed(&pThis->ValidatorWrite, &pThis->ValidatorRead.Core);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (RT_FAILURE(rc9))
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rc9;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pThis->cWriterReads--;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return VINF_SUCCESS;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Try unlock it.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifdef RTSEMRW_STRICT
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int rc9 = RTLockValidatorRecSharedCheckAndRelease(&pThis->ValidatorRead, RTThreadSelf());
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (RT_FAILURE(rc9))
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rc9;
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifdef RT_OS_LINUX /* glibc (at least 2.8) may screw up when unlocking a lock we don't own. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (ASMAtomicReadU32(&pThis->cReaders) == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgFailed(("Not owner of %p\n", pThis));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return VERR_NOT_OWNER;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASMAtomicDecU32(&pThis->cReaders);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int rc = pthread_rwlock_unlock(&pThis->RWLock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (rc)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASMAtomicIncU32(&pThis->cReaders);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgFailed(("Failed read unlock read-write sem %p, rc=%d.\n", RWSem, rc));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return RTErrConvertFromErrno(rc);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return VINF_SUCCESS;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncDECL_FORCE_INLINE(int) rtSemRWRequestWrite(RTSEMRW RWSem, unsigned cMillies, PCRTLOCKVALSRCPOS pSrcPos)
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync{
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync /*
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * Validate input.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct RTSEMRWINTERNAL *pThis = RWSem;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VERR_INVALID_HANDLE);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Recursion?
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pthread_t Self = pthread_self();
6479169ec893c18a646cec595e4e214492d180f0vboxsync pthread_t Writer;
6479169ec893c18a646cec595e4e214492d180f0vboxsync ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (Writer == Self)
09e4ff0eddf453bdf8d622df2b48cff510f7d01dvboxsync {
09e4ff0eddf453bdf8d622df2b48cff510f7d01dvboxsync#ifdef RTSEMRW_STRICT
6479169ec893c18a646cec595e4e214492d180f0vboxsync int rc9 = RTLockValidatorRecExclRecursion(&pThis->ValidatorWrite, pSrcPos);
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (RT_FAILURE(rc9))
6479169ec893c18a646cec595e4e214492d180f0vboxsync return rc9;
6479169ec893c18a646cec595e4e214492d180f0vboxsync#endif
6479169ec893c18a646cec595e4e214492d180f0vboxsync Assert(pThis->cWrites < INT32_MAX);
6479169ec893c18a646cec595e4e214492d180f0vboxsync pThis->cWrites++;
6479169ec893c18a646cec595e4e214492d180f0vboxsync return VINF_SUCCESS;
6479169ec893c18a646cec595e4e214492d180f0vboxsync }
6479169ec893c18a646cec595e4e214492d180f0vboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync /*
6479169ec893c18a646cec595e4e214492d180f0vboxsync * Try lock it.
6479169ec893c18a646cec595e4e214492d180f0vboxsync */
6479169ec893c18a646cec595e4e214492d180f0vboxsync RTTHREAD hThreadSelf = NIL_RTTHREAD;
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (cMillies)
6479169ec893c18a646cec595e4e214492d180f0vboxsync {
6479169ec893c18a646cec595e4e214492d180f0vboxsync#ifdef RTSEMRW_STRICT
6479169ec893c18a646cec595e4e214492d180f0vboxsync hThreadSelf = RTThreadSelfAutoAdopt();
6479169ec893c18a646cec595e4e214492d180f0vboxsync int rc9 = RTLockValidatorRecExclCheckOrderAndBlocking(&pThis->ValidatorWrite, hThreadSelf, pSrcPos, true,
6479169ec893c18a646cec595e4e214492d180f0vboxsync cMillies, RTTHREADSTATE_RW_WRITE, true);
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (RT_FAILURE(rc9))
6479169ec893c18a646cec595e4e214492d180f0vboxsync return rc9;
6479169ec893c18a646cec595e4e214492d180f0vboxsync#else
6479169ec893c18a646cec595e4e214492d180f0vboxsync hThreadSelf = RTThreadSelf();
6479169ec893c18a646cec595e4e214492d180f0vboxsync RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_WRITE, true);
6479169ec893c18a646cec595e4e214492d180f0vboxsync#endif
6479169ec893c18a646cec595e4e214492d180f0vboxsync }
6479169ec893c18a646cec595e4e214492d180f0vboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (cMillies == RT_INDEFINITE_WAIT)
6479169ec893c18a646cec595e4e214492d180f0vboxsync {
6479169ec893c18a646cec595e4e214492d180f0vboxsync /* take rwlock */
6479169ec893c18a646cec595e4e214492d180f0vboxsync int rc = pthread_rwlock_wrlock(&pThis->RWLock);
6479169ec893c18a646cec595e4e214492d180f0vboxsync RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (rc)
6479169ec893c18a646cec595e4e214492d180f0vboxsync {
6479169ec893c18a646cec595e4e214492d180f0vboxsync AssertMsgFailed(("Failed write lock read-write sem %p, rc=%d.\n", RWSem, rc));
6479169ec893c18a646cec595e4e214492d180f0vboxsync return RTErrConvertFromErrno(rc);
6479169ec893c18a646cec595e4e214492d180f0vboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifdef RT_OS_DARWIN
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return VERR_NOT_IMPLEMENTED;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#else /* !RT_OS_DARWIN */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Get current time and calc end of wait time.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct timespec ts = {0,0};
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync clock_gettime(CLOCK_REALTIME, &ts);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (cMillies != 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ts.tv_nsec += (cMillies % 1000) * 1000000;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ts.tv_sec += cMillies / 1000;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (ts.tv_nsec >= 1000000000)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ts.tv_nsec -= 1000000000;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ts.tv_sec++;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /* take rwlock */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int rc = pthread_rwlock_timedwrlock(&pThis->RWLock, &ts);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (rc)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return RTErrConvertFromErrno(rc);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif /* !RT_OS_DARWIN */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ATOMIC_SET_PTHREAD_T(&pThis->Writer, Self);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pThis->cWrites = 1;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync Assert(!pThis->cReaders);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifdef RTSEMRW_STRICT
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLockValidatorRecExclSetOwner(&pThis->ValidatorWrite, hThreadSelf, pSrcPos, true);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return VINF_SUCCESS;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(int) RTSemRWRequestWrite(RTSEMRW RWSem, unsigned cMillies)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifndef RTSEMRW_STRICT
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rtSemRWRequestWrite(RWSem, cMillies, NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync return rtSemRWRequestWrite(RWSem, cMillies, &SrcPos);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(int) RTSemRWRequestWriteDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rtSemRWRequestWrite(RWSem, cMillies, &SrcPos);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(int) RTSemRWRequestWriteNoResume(RTSEMRW RWSem, unsigned cMillies)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /* EINTR isn't returned by the wait functions we're using. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifndef RTSEMRW_STRICT
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rtSemRWRequestWrite(RWSem, cMillies, NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rtSemRWRequestWrite(RWSem, cMillies, &SrcPos);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(int) RTSemRWRequestWriteNoResumeDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /* EINTR isn't returned by the wait functions we're using. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return rtSemRWRequestWrite(RWSem, cMillies, &SrcPos);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(int) RTSemRWReleaseWrite(RTSEMRW RWSem)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Validate input.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct RTSEMRWINTERNAL *pThis = RWSem;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VERR_INVALID_HANDLE);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Verify ownership and implement recursion.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pthread_t Self = pthread_self();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pthread_t Writer;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgReturn(Writer == Self, ("pThis=%p\n", pThis), VERR_NOT_OWNER);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertReturn(pThis->cWriterReads == 0 || pThis->cWrites > 1, VERR_WRONG_ORDER);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (pThis->cWrites > 1)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifdef RTSEMRW_STRICT
6479169ec893c18a646cec595e4e214492d180f0vboxsync int rc9 = RTLockValidatorRecExclUnwind(&pThis->ValidatorWrite);
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (RT_FAILURE(rc9))
6479169ec893c18a646cec595e4e214492d180f0vboxsync return rc9;
6479169ec893c18a646cec595e4e214492d180f0vboxsync#endif
6479169ec893c18a646cec595e4e214492d180f0vboxsync pThis->cWrites--;
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync return VINF_SUCCESS;
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pThis->cWrites--;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Try unlock it.
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#ifdef RTSEMRW_STRICT
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int rc9 = RTLockValidatorRecExclReleaseOwner(&pThis->ValidatorWrite, true);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (RT_FAILURE(rc9))
6479169ec893c18a646cec595e4e214492d180f0vboxsync return rc9;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ATOMIC_SET_PTHREAD_T(&pThis->Writer, (pthread_t)-1);
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync int rc = pthread_rwlock_unlock(&pThis->RWLock);
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync if (rc)
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgFailed(("Failed write unlock read-write sem %p, rc=%d.\n", RWSem, rc));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return RTErrConvertFromErrno(rc);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return VINF_SUCCESS;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(bool) RTSemRWIsWriteOwner(RTSEMRW RWSem)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Validate input.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
2084a447d1acb619df7c393fac41b79d517e4b3dvboxsync struct RTSEMRWINTERNAL *pThis = RWSem;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertPtrReturn(pThis, false);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync false);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Check ownership.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pthread_t Self = pthread_self();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync pthread_t Writer;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return Writer == Self;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(uint32_t) RTSemRWGetWriteRecursion(RTSEMRW RWSem)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Validate input.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct RTSEMRWINTERNAL *pThis = RWSem;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertPtrReturn(pThis, 0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync 0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Return the requested data.
6479169ec893c18a646cec595e4e214492d180f0vboxsync */
6479169ec893c18a646cec595e4e214492d180f0vboxsync return pThis->cWrites;
6479169ec893c18a646cec595e4e214492d180f0vboxsync}
6479169ec893c18a646cec595e4e214492d180f0vboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsyncRTDECL(uint32_t) RTSemRWGetWriterReadRecursion(RTSEMRW RWSem)
6479169ec893c18a646cec595e4e214492d180f0vboxsync{
6479169ec893c18a646cec595e4e214492d180f0vboxsync /*
6479169ec893c18a646cec595e4e214492d180f0vboxsync * Validate input.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct RTSEMRWINTERNAL *pThis = RWSem;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertPtrReturn(pThis, 0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync 0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync * Return the requested data.
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync */
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync return pThis->cWriterReads;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncRTDECL(uint32_t) RTSemRWGetReadCount(RTSEMRW RWSem)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Validate input.
6479169ec893c18a646cec595e4e214492d180f0vboxsync */
6479169ec893c18a646cec595e4e214492d180f0vboxsync struct RTSEMRWINTERNAL *pThis = RWSem;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertPtrReturn(pThis, 0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync 0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Return the requested data.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return pThis->cReaders;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync