lockvalidator.cpp revision 75d8fea43f2d7474d00172dcf906f7ab598a8c8f
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * IPRT - Lock Validator.
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * Copyright (C) 2009 Sun Microsystems, Inc.
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * available from http://www.virtualbox.org. This file is free software;
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * you can redistribute it and/or modify it under the terms of the GNU
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * General Public License (GPL) as published by the Free Software
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * The contents of this file may alternatively be used under the terms
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * of the Common Development and Distribution License Version 1.0
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * VirtualBox OSE distribution, in which case the provisions of the
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * CDDL are applicable instead of those of the GPL.
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * You may elect to license modified versions of this file under the
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * terms and conditions of either the GPL or the CDDL or both.
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * additional information or have any questions.
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync/*******************************************************************************
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync* Header Files *
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync*******************************************************************************/
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync/*******************************************************************************
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync* Structures and Typedefs *
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync*******************************************************************************/
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * Deadlock detection stack entry.
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync /** The current record. */
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync /** The current entry number if pRec is a shared one. */
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync /** The thread state of the thread we followed to get to pFirstSibling.
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * This is only used for validating a deadlock stack. */
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync /** The thread we followed to get to pFirstSibling.
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * This is only used for validating a deadlock stack. */
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync /** What pThread is waiting on, i.e. where we entered the circular list of
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * siblings. This is used for validating a deadlock stack as well as
38ae7e4efe803ea78b6499cd05a394db32623e41vboxsync * terminating the sibling walk. */
typedef struct RTLOCKVALDDSTACK
uint32_t c;
static bool volatile g_fLockValidatorEnabled = true;
#ifdef RT_STRICT
static bool volatile g_fLockValidatorQuiet = false;
static bool volatile g_fLockValidatorQuiet = true;
#ifdef RT_STRICT
static bool volatile g_fLockValidatorMayPanic = true;
static bool volatile g_fLockValidatorMayPanic = false;
DECL_FORCE_INLINE(PRTLOCKVALRECUNION) rtLockValidatorReadRecUnionPtr(PRTLOCKVALRECUNION volatile *ppRec)
DECL_FORCE_INLINE(void) rtLockValidatorWriteRecUnionPtr(PRTLOCKVALRECUNION volatile *ppRec, PRTLOCKVALRECUNION pRecNew)
DECL_FORCE_INLINE(PRTLOCKVALRECSHRDOWN) rtLockValidatorUoReadSharedOwner(PRTLOCKVALRECSHRDOWN volatile *ppOwner)
if (!pThread)
static void rtLockValidatorComplainAboutLock(const char *pszPrefix, PRTLOCKVALRECUNION pRec, const char *pszSuffix)
case RTLOCKVALRECEXCL_MAGIC:
pRec->Excl.SrcPos.pszFile, pRec->Excl.SrcPos.uLine, pRec->Excl.SrcPos.pszFunction, pRec->Excl.SrcPos.uId,
case RTLOCKVALRECSHRD_MAGIC:
pRec->ShrdOwner.SrcPos.pszFile, pRec->ShrdOwner.SrcPos.uLine, pRec->ShrdOwner.SrcPos.pszFunction, pRec->ShrdOwner.SrcPos.uId,
pRec->ShrdOwner.SrcPos.pszFile, pRec->ShrdOwner.SrcPos.uLine, pRec->ShrdOwner.SrcPos.pszFunction, pRec->ShrdOwner.SrcPos.uId,
RTAssertMsg2AddWeak("%spRec=%p u32Magic=%#x (bad)%s", pszPrefix, pRec, pRec->Core.u32Magic, pszSuffix);
static void rtLockValidatorComplainFirst(const char *pszWhat, PCRTLOCKVALSRCPOS pSrcPos, PRTTHREADINT pThreadSelf, PRTLOCKVALRECUNION pRec)
RTAssertMsg2Weak("%s [uId=%p thrd=%s]\n", pszWhat, pSrcPos->uId, VALID_PTR(pThreadSelf) ? pThreadSelf->szName : "<NIL>");
static void rtLockValidatorComplainPanic(void)
while (pSibling)
case RTLOCKVALRECEXCL_MAGIC:
case RTLOCKVALRECSHRD_MAGIC:
AssertFailed();
return VINF_SUCCESS;
if (!pRec)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
if (pRec)
if (papOwners)
if (piEntry)
return pEntry;
return NULL;
rtLockValidatorRecSharedAllocOwner(PRTLOCKVALRECSHRD pRead, PRTTHREADINT pThreadSelf, PCRTLOCKVALSRCPOS pSrcPos)
if (iEntry > 0)
iEntry--;
return NULL;
if (pSrcPos)
return pEntry;
if (pEntry)
if (!papOwners)
while (cInc-- > 0)
cAllocated++;
DECLINLINE(bool) rtLockValidatorRecSharedAddOwner(PRTLOCKVALRECSHRD pShared, PRTLOCKVALRECSHRDOWN pEntry)
AssertFailed();
DECLINLINE(void) rtLockValidatorRecSharedRemoveAndFreeOwner(PRTLOCKVALRECSHRD pShared, PRTLOCKVALRECSHRDOWN pEntry,
AssertReturnVoidStmt(pShared->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC, rtLockValidatorSerializeDetectionLeave());
AssertFailed();
RTDECL(int) RTLockValidatorCheckOrder(PRTLOCKVALRECEXCL pRec, RTTHREAD hThread, PCRTLOCKVALSRCPOS pSrcPos)
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
RTDECL(int) RTLockValidatorRecordReadWriteRecursion(PRTLOCKVALRECEXCL pWrite, PRTLOCKVALRECSHRD pRead, PCRTLOCKVALSRCPOS pSrcPos)
return VINF_SUCCESS;
return VINF_SUCCESS;
RTDECL(int) RTLockValidatorUnwindReadWriteRecursion(PRTLOCKVALRECEXCL pWrite, PRTLOCKVALRECSHRD pRead)
return VINF_SUCCESS;
return VINF_SUCCESS;
RTDECL(RTTHREAD) RTLockValidatorSetOwner(PRTLOCKVALRECEXCL pRec, RTTHREAD hThread, PCRTLOCKVALSRCPOS pSrcPos)
return VINF_SUCCESS;
return hThread;
return VINF_SUCCESS;
return pThread;
RTDECL(void) RTLockValidatorAddReadOwner(PRTLOCKVALRECSHRD pRead, RTTHREAD hThread, PCRTLOCKVALSRCPOS pSrcPos)
if (pEntry)
if ( pEntry
if (!pThread)
return VERR_INVALID_HANDLE;
return cWriteLocks;
if (!pThread)
return VERR_INVALID_HANDLE;
return cReadLocks;
return VERR_TRY_AGAIN;
return VERR_TRY_AGAIN;
return VERR_TRY_AGAIN;
return VERR_SEM_LV_DEADLOCK;
return VERR_SEM_LV_EXISTING_DEADLOCK;
static bool volatile s_fComplained = false;
if (!s_fComplained)
s_fComplained = true;
rtLockValidatorComplain(RT_SRC_POS, "lock validator stack is too small! (%zu entries)\n", RT_ELEMENTS(pStack->a));
return VINF_SUCCESS;
DECL_FORCE_INLINE(bool) rtLockValidatorDdMoreWorkLeft(PRTLOCKVALRECUNION pRec, uint32_t iEntry, PRTLOCKVALRECUNION pFirstSibling)
case RTLOCKVALRECEXCL_MAGIC:
case RTLOCKVALRECSHRD_MAGIC:
static int rtLockValidatorDdDoDetection(PRTLOCKVALDDSTACK pStack, PRTLOCKVALRECUNION const pOriginalRec,
pStack->c = 0;
case RTLOCKVALRECEXCL_MAGIC:
if ( pNextThread
case RTLOCKVALRECSHRD_MAGIC:
if ( pEntry
if (pNextThread)
if (pNextRec)
pStack->c++;
return VINF_SUCCESS;
if ( !pThread
static int rtLockValidatorDeadlockDetection(PRTLOCKVALRECUNION pRec, PRTTHREADINT pThreadSelf, PCRTLOCKVALSRCPOS pSrcPos)
#ifdef DEBUG_bird
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
RTDECL(int) RTLockValidatorCheckWriteOrderBlocking(PRTLOCKVALRECEXCL pWrite, PRTLOCKVALRECSHRD pRead,
return VINF_SUCCESS;
if (pEntry)
return VERR_SEM_LV_UPGRADE;
return VINF_SUCCESS;
RTDECL(int) RTLockValidatorCheckReadOrderBlocking(PRTLOCKVALRECSHRD pRead, PRTLOCKVALRECEXCL pWrite,
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
* isn't any other place to check for this. semmutex-win.cpp for instance.
if (fRecursiveOk)
return VINF_SUCCESS;
return VERR_SEM_LV_NESTED;
return VINF_SUCCESS;