critsect-generic.cpp revision 4b0369e0c9bcae37f2801e0f7b92509bbbaf4bec
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* $Id$ */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** @file
fa9e4066f08beec538e775443c5be79dd423fcabahrens * IPRT - Critical Section, Generic.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright (C) 2006-2009 Sun Microsystems, Inc.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This file is part of VirtualBox Open Source Edition (OSE), as
fa9e4066f08beec538e775443c5be79dd423fcabahrens * available from http://www.virtualbox.org. This file is free software;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * you can redistribute it and/or modify it under the terms of the GNU
fa9e4066f08beec538e775443c5be79dd423fcabahrens * General Public License (GPL) as published by the Free Software
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Foundation, in version 2 as it comes in the "COPYING" file of the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file may alternatively be used under the terms
fa9e4066f08beec538e775443c5be79dd423fcabahrens * of the Common Development and Distribution License Version 1.0
fa9e4066f08beec538e775443c5be79dd423fcabahrens * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * VirtualBox OSE distribution, in which case the provisions of the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL are applicable instead of those of the GPL.
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You may elect to license modified versions of this file under the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * terms and conditions of either the GPL or the CDDL or both.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Clara, CA 95054 USA or visit http://www.sun.com if you need
fa9e4066f08beec538e775443c5be79dd423fcabahrens * additional information or have any questions.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*******************************************************************************
fa9e4066f08beec538e775443c5be79dd423fcabahrens* Header Files *
fa9e4066f08beec538e775443c5be79dd423fcabahrens*******************************************************************************/
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <iprt/critsect.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "internal/iprt.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <iprt/semaphore.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <iprt/thread.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <iprt/assert.h>
71eb05381846ad14a2087631474e832d0f316654Chris Kirby#include <iprt/asm.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <iprt/err.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "internal/thread.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "internal/strict.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* In strict mode we're redefining these, so undefine them now for the implementation. */
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee#undef RTCritSectEnter
fa9e4066f08beec538e775443c5be79dd423fcabahrens#undef RTCritSectTryEnter
fa9e4066f08beec538e775443c5be79dd423fcabahrens#undef RTCritSectEnterMultiple
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTCritSectInit(PRTCRITSECT pCritSect)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens return RTCritSectInitEx(pCritSect, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectInit);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
44cd46cadd9aab751dae6a4023c1cb5bf316d274billmRTDECL(int) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags)
44cd46cadd9aab751dae6a4023c1cb5bf316d274billm{
a2eea2e101e6a163a537dcc6d4e3c4da2a0ea5b2ahrens /*
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Initialize the structure and
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens pCritSect->u32Magic = RTCRITSECT_MAGIC;
fa9e4066f08beec538e775443c5be79dd423fcabahrens pCritSect->fFlags = fFlags;
fa9e4066f08beec538e775443c5be79dd423fcabahrens pCritSect->cNestings = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens pCritSect->cLockers = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens pCritSect->NativeThreadOwner = NIL_RTNATIVETHREAD;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc = RTLockValidatorCreate(&pCritSect->pValidatorRec, NIL_RTLOCKVALIDATORCLASS, 0, NULL, pCritSect);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (RT_SUCCESS(rc))
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = RTSemEventCreate(&pCritSect->EventSem);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (RT_SUCCESS(rc))
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VINF_SUCCESS;
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTLockValidatorDestroy(&pCritSect->pValidatorRec);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens AssertRC(rc);
fa9e4066f08beec538e775443c5be79dd423fcabahrens pCritSect->EventSem = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens pCritSect->u32Magic = (uint32_t)rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectInitEx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
1649cd4b1641110b549d9f70a902cafc2007bd77tabriz#ifdef RTCRITSECT_STRICT
87e5029a3226958edab1512d6182bc74d8d80c9aahrensRTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTUINTPTR uId, RT_SRC_POS_DECL)
87e5029a3226958edab1512d6182bc74d8d80c9aahrens#else
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects)
1649cd4b1641110b549d9f70a902cafc2007bd77tabriz#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens Assert(cCritSects > 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtr(papCritSects);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Try get them all.
893a6d32980d24be1349478f44169009d4801c25ahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc = VERR_INVALID_PARAMETER;
fa9e4066f08beec538e775443c5be79dd423fcabahrens size_t i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < cCritSects; i++)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = RTCritSectTryEnterDebug(papCritSects[i], uId, RT_SRC_POS_ARGS);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock rc = RTCritSectTryEnter(papCritSects[i]);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock#endif
06eeb2ad640ce72d394ac521094bed7681044408ek if (RT_FAILURE(rc))
06eeb2ad640ce72d394ac521094bed7681044408ek break;
b1b8ab34de515a5e83206da22c3d7e563241b021lling }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The retry loop.
088f389458728c464569a5506b58070254fa4f7dahrens */
088f389458728c464569a5506b58070254fa4f7dahrens for (unsigned cTries = 0; ; cTries++)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens /*
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby * We've failed, release any locks we might have gotten. ('i' is the lock that failed btw.)
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens size_t j = i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens while (j-- > 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc2 = RTCritSectLeave(papCritSects[j]);
fa9e4066f08beec538e775443c5be79dd423fcabahrens AssertRC(rc2);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (rc != VERR_SEM_BUSY)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Try prevent any theoretical synchronous races with other threads.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens Assert(cTries < 1000000);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (cTries > 10000)
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTThreadSleep(cTries % 3);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Wait on the one we failed to get.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = RTCritSectEnterDebug(papCritSects[i], uId, RT_SRC_POS_ARGS);
0b69c2f001a429251e2d38f25aca860396551214ahrens#else
0b69c2f001a429251e2d38f25aca860396551214ahrens rc = RTCritSectEnter(papCritSects[i]);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (RT_FAILURE(rc))
fa9e4066f08beec538e775443c5be79dd423fcabahrens return rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Try take the others.
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee */
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (j = 0; j < cCritSects; j++)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (j != i)
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = RTCritSectTryEnterDebug(papCritSects[j], uId, RT_SRC_POS_ARGS);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens rc = RTCritSectTryEnter(papCritSects[j]);
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens#endif
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens if (RT_FAILURE(rc))
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens break;
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens }
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens }
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens if (RT_SUCCESS(rc))
1934e92fc930c49429ad71a8ca97340f33227e78maybee return rc;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks /*
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens * We failed.
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens */
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby if (i > j)
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby {
ea2f5b9e5bf4966630882d6d681a94768aea1d75Matthew Ahrens int rc2 = RTCritSectLeave(papCritSects[i]);
ea2f5b9e5bf4966630882d6d681a94768aea1d75Matthew Ahrens AssertRC(rc2);
cdf5b4ca0fa5ca7622b06bcb271be9e8a8245fecmmusante }
cdf5b4ca0fa5ca7622b06bcb271be9e8a8245fecmmusante i = j;
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectEnterMultipleDebug);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectEnterMultiple);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens return RTCritSectEnterMultipleDebug(cCritSects, papCritSects, 0, RT_SRC_POS);
99653d4ee642c6528e88224f12409a5f23060994eschrock}
99653d4ee642c6528e88224f12409a5f23060994eschrockRT_EXPORT_SYMBOL(RTCritSectEnterMultiple);
99653d4ee642c6528e88224f12409a5f23060994eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else /* !RTCRITSECT_STRICT */
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTUINTPTR uId, RT_SRC_POS_DECL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return RTCritSectEnterMultiple(cCritSects, papCritSects);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
99653d4ee642c6528e88224f12409a5f23060994eschrockRT_EXPORT_SYMBOL(RTCritSectEnterMultipleDebug);
99653d4ee642c6528e88224f12409a5f23060994eschrock#endif /* !RTCRITSECT_STRICT */
06eeb2ad640ce72d394ac521094bed7681044408ek
b1b8ab34de515a5e83206da22c3d7e563241b021lling
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan#ifdef RTCRITSECT_STRICT
ca45db4129beff691dc46576c328149443788af2Chris KirbyRTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else
088f389458728c464569a5506b58070254fa4f7dahrensRTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect)
088f389458728c464569a5506b58070254fa4f7dahrens#endif
088f389458728c464569a5506b58070254fa4f7dahrens{
088f389458728c464569a5506b58070254fa4f7dahrens Assert(pCritSect);
088f389458728c464569a5506b58070254fa4f7dahrens Assert(pCritSect->u32Magic == RTCRITSECT_MAGIC);
088f389458728c464569a5506b58070254fa4f7dahrens RTNATIVETHREAD NativeThreadSelf = RTThreadNativeSelf();
088f389458728c464569a5506b58070254fa4f7dahrens#ifdef RTCRITSECT_STRICT
088f389458728c464569a5506b58070254fa4f7dahrens RTTHREAD ThreadSelf = RTThreadSelf();
088f389458728c464569a5506b58070254fa4f7dahrens if (ThreadSelf == NIL_RTTHREAD)
088f389458728c464569a5506b58070254fa4f7dahrens RTThreadAdopt(RTTHREADTYPE_DEFAULT, 0, NULL, &ThreadSelf);
088f389458728c464569a5506b58070254fa4f7dahrens#endif
088f389458728c464569a5506b58070254fa4f7dahrens
088f389458728c464569a5506b58070254fa4f7dahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Try take the lock. (cLockers is -1 if it's free)
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!ASMAtomicCmpXchgS32(&pCritSect->cLockers, 0, -1))
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Somebody is owning it (or will be soon). Perhaps it's us?
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pCritSect->NativeThreadOwner == NativeThreadSelf)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!(pCritSect->fFlags & RTCRITSECT_FLAGS_NO_NESTING))
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASMAtomicIncS32(&pCritSect->cLockers);
fa9e4066f08beec538e775443c5be79dd423fcabahrens pCritSect->cNestings++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VINF_SUCCESS;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens AssertMsgFailed(("Nested entry of critsect %p\n", pCritSect));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VERR_SEM_NESTED;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VERR_SEM_BUSY;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * First time
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens pCritSect->cNestings = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NativeThreadSelf);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTLOCKVALIDATORSRCPOS SrcPos = RTLOCKVALIDATORSRCPOS_INIT_DEBUG_API();
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTLockValidatorSetOwner(pCritSect->pValidatorRec, ThreadSelf, &SrcPos);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VINF_SUCCESS;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectTryEnterDebug);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectTryEnter);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens return RTCritSectTryEnterDebug(pCritSect, 0, RT_SRC_POS);
6754306ec9a89fd28806908d10c76141e8fbba3fahrens}
6754306ec9a89fd28806908d10c76141e8fbba3fahrensRT_EXPORT_SYMBOL(RTCritSectTryEnter);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else /* !RTCRITSECT_STRICT */
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
6754306ec9a89fd28806908d10c76141e8fbba3fahrens return RTCritSectTryEnter(pCritSect);
6754306ec9a89fd28806908d10c76141e8fbba3fahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectTryEnterDebug);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif /* !RTCRITSECT_STRICT */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect)
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens Assert(pCritSect);
fa9e4066f08beec538e775443c5be79dd423fcabahrens Assert(pCritSect->u32Magic == RTCRITSECT_MAGIC);
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTNATIVETHREAD NativeThreadSelf = RTThreadNativeSelf();
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTLOCKVALIDATORSRCPOS SrcPos = RTLOCKVALIDATORSRCPOS_INIT_DEBUG_API();
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTLockValidatorCheckOrder(pCritSect->pValidatorRec, hThreadSelf, &SrcPos);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** If the critical section has already been destroyed, then inform the caller. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pCritSect->u32Magic != RTCRITSECT_MAGIC)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VERR_SEM_DESTROYED;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Increment the waiter counter.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This becomes 0 when the section is free.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ASMAtomicIncS32(&pCritSect->cLockers) > 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
44cd46cadd9aab751dae6a4023c1cb5bf316d274billm /*
44cd46cadd9aab751dae6a4023c1cb5bf316d274billm * Nested?
44cd46cadd9aab751dae6a4023c1cb5bf316d274billm */
44cd46cadd9aab751dae6a4023c1cb5bf316d274billm if (pCritSect->NativeThreadOwner == NativeThreadSelf)
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens {
44cd46cadd9aab751dae6a4023c1cb5bf316d274billm if (!(pCritSect->fFlags & RTCRITSECT_FLAGS_NO_NESTING))
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens pCritSect->cNestings++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VINF_SUCCESS;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens AssertBreakpoint(); /* don't do normal assertion here, the logger uses this code too. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASMAtomicDecS32(&pCritSect->cLockers);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VERR_SEM_NESTED;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Wait for the current owner to release it.
1934e92fc930c49429ad71a8ca97340f33227e78maybee */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifndef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTTHREAD hThreadSelf = RTThreadSelf();
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (;;)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc9 = RTLockValidatorCheckBlocking(pCritSect->pValidatorRec, hThreadSelf, RTTHREADSTATE_CRITSECT,
fa9e4066f08beec538e775443c5be79dd423fcabahrens !(pCritSect->fFlags & RTCRITSECT_FLAGS_NO_NESTING),
fa9e4066f08beec538e775443c5be79dd423fcabahrens &SrcPos);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (RT_FAILURE(rc9))
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASMAtomicDecS32(&pCritSect->cLockers);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return rc9;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock RTThreadBlocking(hThreadSelf, RTTHREADSTATE_CRITSECT);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc = RTSemEventWait(pCritSect->EventSem, RT_INDEFINITE_WAIT);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_CRITSECT);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pCritSect->u32Magic != RTCRITSECT_MAGIC)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VERR_SEM_DESTROYED;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (rc == VINF_SUCCESS)
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens AssertMsg(rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED, ("rc=%Rrc\n", rc));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens AssertMsg(pCritSect->NativeThreadOwner == NIL_RTNATIVETHREAD, ("pCritSect->NativeThreadOwner=%p\n", pCritSect->NativeThreadOwner));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * First time
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee */
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee pCritSect->cNestings = 1;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NativeThreadSelf);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTLockValidatorSetOwner(pCritSect->pValidatorRec, hThreadSelf, &SrcPos);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VINF_SUCCESS;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectEnterDebug);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectEnter);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens return RTCritSectEnterDebug(pCritSect, 0, RT_SRC_POS);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectEnter);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else /* !RTCRITSECT_STRICT */
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens return RTCritSectEnter(pCritSect);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectEnterDebug);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif /* !RTCRITSECT_STRICT */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTCritSectLeave(PRTCRITSECT pCritSect)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Assert ownership and so on.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens Assert(pCritSect);
fa9e4066f08beec538e775443c5be79dd423fcabahrens Assert(pCritSect->u32Magic == RTCRITSECT_MAGIC);
fa9e4066f08beec538e775443c5be79dd423fcabahrens Assert(pCritSect->cNestings > 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens Assert(pCritSect->cLockers >= 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens Assert(pCritSect->NativeThreadOwner == RTThreadNativeSelf());
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Decrement nestings, if <= 0 when we'll release the critsec.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens pCritSect->cNestings--;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pCritSect->cNestings > 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASMAtomicDecS32(&pCritSect->cLockers);
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi else
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi {
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi /*
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * Set owner to zero.
3d6926289465757c3da780cea696825b0d730283Sanjeev Bagewadi * Decrement waiters, if >= 0 then we have to wake one of them up.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef RTCRITSECT_STRICT
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTLockValidatorUnsetOwner(pCritSect->pValidatorRec);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NIL_RTNATIVETHREAD);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ASMAtomicDecS32(&pCritSect->cLockers) >= 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc = RTSemEventSignal(pCritSect->EventSem);
fa9e4066f08beec538e775443c5be79dd423fcabahrens AssertReleaseMsg(RT_SUCCESS(rc), ("RTSemEventSignal -> %Rrc\n", rc));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VINF_SUCCESS;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectLeave);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc = VINF_SUCCESS;
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (size_t i = 0; i < cCritSects; i++)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc2 = RTCritSectLeave(papCritSects[i]);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = rc2;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectLeaveMultiple);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
8a2f1b9190d1dc288470a1fd2776d79ce82cb129ahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTCritSectDelete(PRTCRITSECT pCritSect)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia /*
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * Assert free waiters and so on.
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Assert(pCritSect);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Assert(pCritSect->u32Magic == RTCRITSECT_MAGIC);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Assert(pCritSect->cNestings == 0);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Assert(pCritSect->cLockers == -1);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia Assert(pCritSect->NativeThreadOwner == NIL_RTNATIVETHREAD);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia /*
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * Invalidate the structure and free the mutex.
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia * In case someone is waiting we'll signal the semaphore cLockers + 1 times.
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia */
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia ASMAtomicWriteU32(&pCritSect->u32Magic, ~RTCRITSECT_MAGIC);
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia pCritSect->fFlags = 0;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia pCritSect->cNestings = 0;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia pCritSect->NativeThreadOwner= NIL_RTNATIVETHREAD;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia RTSEMEVENT EventSem = pCritSect->EventSem;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia pCritSect->EventSem = NIL_RTSEMEVENT;
d20e665c84abf083a9e8b62cca93383ecb55afdfRicardo M. Correia
fa9e4066f08beec538e775443c5be79dd423fcabahrens while (pCritSect->cLockers-- >= 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTSemEventSignal(EventSem);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASMAtomicWriteS32(&pCritSect->cLockers, -1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc = RTSemEventDestroy(EventSem);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock AssertRC(rc);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee RTLockValidatorDestroy(&pCritSect->pValidatorRec);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee return rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTCritSectDelete);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens