semrw-posix.cpp revision 2e409a283e011f22209ad3f6009baffdbdf30539
af062818b47340eef15700d2f0211576ba3506eevboxsync * innotek Portable Runtime - Read-Write Semaphore, POSIX.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Copyright (C) 2006-2007 innotek GmbH
af062818b47340eef15700d2f0211576ba3506eevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
af062818b47340eef15700d2f0211576ba3506eevboxsync * available from http://www.virtualbox.org. This file is free software;
af062818b47340eef15700d2f0211576ba3506eevboxsync * you can redistribute it and/or modify it under the terms of the GNU
af062818b47340eef15700d2f0211576ba3506eevboxsync * General Public License (GPL) as published by the Free Software
af062818b47340eef15700d2f0211576ba3506eevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
af062818b47340eef15700d2f0211576ba3506eevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
af062818b47340eef15700d2f0211576ba3506eevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
af062818b47340eef15700d2f0211576ba3506eevboxsync * The contents of this file may alternatively be used under the terms
af062818b47340eef15700d2f0211576ba3506eevboxsync * of the Common Development and Distribution License Version 1.0
af062818b47340eef15700d2f0211576ba3506eevboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
af062818b47340eef15700d2f0211576ba3506eevboxsync * VirtualBox OSE distribution, in which case the provisions of the
af062818b47340eef15700d2f0211576ba3506eevboxsync * CDDL are applicable instead of those of the GPL.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * You may elect to license modified versions of this file under the
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * terms and conditions of either the GPL or the CDDL or both.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/*******************************************************************************
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync* Header Files *
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync*******************************************************************************/
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/** @todo move this to r3/posix/something.h. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync# define ATOMIC_GET_PTHREAD_T(pvVar, pThread) ASMAtomicReadSize(pvVar, pThread)
af062818b47340eef15700d2f0211576ba3506eevboxsync# define ATOMIC_SET_PTHREAD_T(pvVar, pThread) ASMAtomicWriteSize(pvVar, pThread)
af062818b47340eef15700d2f0211576ba3506eevboxsync# define ATOMIC_GET_PTHREAD_T(pvVar, pThread) do { *(pThread) = (pthread_t)ASMAtomicReadPtr((void *volatile *)pvVar); } while (0)
af062818b47340eef15700d2f0211576ba3506eevboxsync# define ATOMIC_SET_PTHREAD_T(pvVar, pThread) ASMAtomicWritePtr((void *volatile *)pvVar, (void *)pThread)
af062818b47340eef15700d2f0211576ba3506eevboxsync/*******************************************************************************
af062818b47340eef15700d2f0211576ba3506eevboxsync* Structures and Typedefs *
af062818b47340eef15700d2f0211576ba3506eevboxsync*******************************************************************************/
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Posix internal representation of a read-write semaphore. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The usual magic. (RTSEMRW_MAGIC) */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Alignment padding. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Number of write recursions. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Number of read recursions by the writer. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The write owner of the lock. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** pthread rwlock. */
af062818b47340eef15700d2f0211576ba3506eevboxsync * Allocate handle.
af062818b47340eef15700d2f0211576ba3506eevboxsync struct RTSEMRWINTERNAL *pThis = (struct RTSEMRWINTERNAL *)RTMemAlloc(sizeof(struct RTSEMRWINTERNAL));
af062818b47340eef15700d2f0211576ba3506eevboxsync * Create the rwlock.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Validate input, nil handle is fine.
af062818b47340eef15700d2f0211576ba3506eevboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
af062818b47340eef15700d2f0211576ba3506eevboxsync * Try destroy it.
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Failed to destroy read-write sem %p, rc=%d.\n", RWSem, rc));
af062818b47340eef15700d2f0211576ba3506eevboxsyncRTDECL(int) RTSemRWRequestRead(RTSEMRW RWSem, unsigned cMillies)
af062818b47340eef15700d2f0211576ba3506eevboxsync * Validate input.
af062818b47340eef15700d2f0211576ba3506eevboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
af062818b47340eef15700d2f0211576ba3506eevboxsync * Check if it's the writer (implement write+read recursion).
af062818b47340eef15700d2f0211576ba3506eevboxsync * Try lock it.
af062818b47340eef15700d2f0211576ba3506eevboxsync /* take rwlock */
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
af062818b47340eef15700d2f0211576ba3506eevboxsync#else /* !RT_OS_DARWIN */
af062818b47340eef15700d2f0211576ba3506eevboxsync * Get current time and calc end of wait time.
af062818b47340eef15700d2f0211576ba3506eevboxsync /* take rwlock */
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pthread_rwlock_timedrdlock(&pThis->RWLock, &ts);
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif /* !RT_OS_DARWIN */
af062818b47340eef15700d2f0211576ba3506eevboxsyncRTDECL(int) RTSemRWRequestReadNoResume(RTSEMRW RWSem, unsigned cMillies)
af062818b47340eef15700d2f0211576ba3506eevboxsync /* EINTR isn't returned by the wait functions we're using. */
af062818b47340eef15700d2f0211576ba3506eevboxsync * Validate input.
af062818b47340eef15700d2f0211576ba3506eevboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
af062818b47340eef15700d2f0211576ba3506eevboxsync * Check if it's the writer.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Try unlock it.
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Failed read unlock read-write sem %p, rc=%d.\n", RWSem, rc));
af062818b47340eef15700d2f0211576ba3506eevboxsyncRTDECL(int) RTSemRWRequestWrite(RTSEMRW RWSem, unsigned cMillies)
af062818b47340eef15700d2f0211576ba3506eevboxsync * Validate input.
af062818b47340eef15700d2f0211576ba3506eevboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
af062818b47340eef15700d2f0211576ba3506eevboxsync * Recursion?
af062818b47340eef15700d2f0211576ba3506eevboxsync * Try lock it.
af062818b47340eef15700d2f0211576ba3506eevboxsync /* take rwlock */
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Failed write lock read-write sem %p, rc=%d.\n", RWSem, rc));
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
af062818b47340eef15700d2f0211576ba3506eevboxsync#else /* !RT_OS_DARWIN */
af062818b47340eef15700d2f0211576ba3506eevboxsync * Get current time and calc end of wait time.
af062818b47340eef15700d2f0211576ba3506eevboxsync /* take rwlock */
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = pthread_rwlock_timedwrlock(&pThis->RWLock, &ts);
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif /* !RT_OS_DARWIN */
af062818b47340eef15700d2f0211576ba3506eevboxsyncRTDECL(int) RTSemRWRequestWriteNoResume(RTSEMRW RWSem, unsigned cMillies)
af062818b47340eef15700d2f0211576ba3506eevboxsync /* EINTR isn't returned by the wait functions we're using. */
af062818b47340eef15700d2f0211576ba3506eevboxsync * Validate input.
af062818b47340eef15700d2f0211576ba3506eevboxsync ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
af062818b47340eef15700d2f0211576ba3506eevboxsync * Verify ownership and implement recursion.
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgReturn(Writer == Self, ("pThis=%p\n", pThis), VERR_NOT_OWNER);
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertReturn(!pThis->cWriterReads, VERR_WRONG_ORDER);
af062818b47340eef15700d2f0211576ba3506eevboxsync * Try unlock it.
af062818b47340eef15700d2f0211576ba3506eevboxsync ATOMIC_SET_PTHREAD_T(&pThis->Writer, (pthread_t)-1);
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Failed write unlock read-write sem %p, rc=%d.\n", RWSem, rc));