Beispiel #1
0
RTDECL(int) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
                             const char *pszNameFmt, ...)
{
    AssertReturn(!(fFlags & ~(RTCRITSECT_FLAGS_NO_NESTING | RTCRITSECT_FLAGS_NO_LOCK_VAL | RTCRITSECT_FLAGS_BOOTSTRAP_HACK | RTCRITSECT_FLAGS_NOP)),
                 VERR_INVALID_PARAMETER);

    /*
     * Initialize the structure and
     */
    pCritSect->u32Magic             = RTCRITSECT_MAGIC;
    pCritSect->fFlags               = fFlags;
    pCritSect->cNestings            = 0;
    pCritSect->cLockers             = -1;
    pCritSect->NativeThreadOwner    = NIL_RTNATIVETHREAD;
    pCritSect->pValidatorRec        = NULL;
    int rc = VINF_SUCCESS;
#ifdef RTCRITSECT_STRICT
    if (!(fFlags & (RTCRITSECT_FLAGS_BOOTSTRAP_HACK | RTCRITSECT_FLAGS_NOP)))
    {
        if (!pszNameFmt)
        {
            static uint32_t volatile s_iCritSectAnon = 0;
            rc = RTLockValidatorRecExclCreate(&pCritSect->pValidatorRec, hClass, uSubClass, pCritSect,
                                              !(fFlags & RTCRITSECT_FLAGS_NO_LOCK_VAL),
                                              "RTCritSect-%u", ASMAtomicIncU32(&s_iCritSectAnon) - 1);
        }
        else
        {
            va_list va;
            va_start(va, pszNameFmt);
            rc = RTLockValidatorRecExclCreateV(&pCritSect->pValidatorRec, hClass, uSubClass, pCritSect,
                                               !(fFlags & RTCRITSECT_FLAGS_NO_LOCK_VAL), pszNameFmt, va);
            va_end(va);
        }
    }
#endif
    if (RT_SUCCESS(rc))
    {
        rc = RTSemEventCreateEx(&pCritSect->EventSem,
                                fFlags & RTCRITSECT_FLAGS_BOOTSTRAP_HACK
                                ? RTSEMEVENT_FLAGS_NO_LOCK_VAL | RTSEMEVENT_FLAGS_BOOTSTRAP_HACK
                                : RTSEMEVENT_FLAGS_NO_LOCK_VAL,
                                NIL_RTLOCKVALCLASS,
                                NULL);
        if (RT_SUCCESS(rc))
            return VINF_SUCCESS;
        RTLockValidatorRecExclDestroy(&pCritSect->pValidatorRec);
    }

    AssertRC(rc);
    pCritSect->EventSem = NULL;
    pCritSect->u32Magic = (uint32_t)rc;
    return rc;
}
Beispiel #2
0
RTDECL(int) RTCritSectRwInitEx(PRTCRITSECTRW pThis, uint32_t fFlags,
                               RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
{
    int rc;
    AssertReturn(!(fFlags & ~( RTCRITSECT_FLAGS_NO_NESTING | RTCRITSECT_FLAGS_NO_LOCK_VAL | RTCRITSECT_FLAGS_BOOTSTRAP_HACK
                              | RTCRITSECT_FLAGS_NOP )),
                 VERR_INVALID_PARAMETER);

    /*
     * Initialize the structure, allocate the lock validator stuff and sems.
     */
    pThis->u32Magic         = RTCRITSECTRW_MAGIC_DEAD;
    pThis->fNeedReset       = false;
#ifdef IN_RING0
    pThis->fFlags           = (uint16_t)(fFlags | RTCRITSECT_FLAGS_RING0);
#else
    pThis->fFlags           = (uint16_t)(fFlags & ~RTCRITSECT_FLAGS_RING0);
#endif
    pThis->u64State         = 0;
    pThis->hNativeWriter    = NIL_RTNATIVETHREAD;
    pThis->cWriterReads     = 0;
    pThis->cWriteRecursions = 0;
    pThis->hEvtWrite        = NIL_RTSEMEVENT;
    pThis->hEvtRead         = NIL_RTSEMEVENTMULTI;
    pThis->pValidatorWrite  = NULL;
    pThis->pValidatorRead   = NULL;
#if HC_ARCH_BITS == 32
    pThis->HCPtrPadding     = NIL_RTHCPTR;
#endif

#ifdef RTCRITSECTRW_STRICT
    bool const fLVEnabled = !(fFlags & RTCRITSECT_FLAGS_NO_LOCK_VAL);
    if (!pszNameFmt)
    {
        static uint32_t volatile s_iAnon = 0;
        uint32_t i = ASMAtomicIncU32(&s_iAnon) - 1;
        rc = RTLockValidatorRecExclCreate(&pThis->pValidatorWrite, hClass, uSubClass, pThis,
                                          fLVEnabled, "RTCritSectRw-%u", i);
        if (RT_SUCCESS(rc))
            rc = RTLockValidatorRecSharedCreate(&pThis->pValidatorRead, hClass, uSubClass, pThis,
                                                false /*fSignaller*/, fLVEnabled, "RTCritSectRw-%u", i);
    }
    else
    {
        va_list va;
        va_start(va, pszNameFmt);
        rc = RTLockValidatorRecExclCreateV(&pThis->pValidatorWrite, hClass, uSubClass, pThis,
                                           fLVEnabled, pszNameFmt, va);
        va_end(va);
        if (RT_SUCCESS(rc))
        {
            va_start(va, pszNameFmt);
            RTLockValidatorRecSharedCreateV(&pThis->pValidatorRead, hClass, uSubClass, pThis,
                                            false /*fSignaller*/, fLVEnabled, pszNameFmt, va);
            va_end(va);
        }
    }
    if (RT_SUCCESS(rc))
        rc = RTLockValidatorRecMakeSiblings(&pThis->pValidatorWrite->Core, &pThis->pValidatorRead->Core);

    if (RT_SUCCESS(rc))
#endif
    {
        rc = RTSemEventMultiCreate(&pThis->hEvtRead);
        if (RT_SUCCESS(rc))
        {
            rc = RTSemEventCreate(&pThis->hEvtWrite);
            if (RT_SUCCESS(rc))
            {
                pThis->u32Magic = RTCRITSECTRW_MAGIC;
                return VINF_SUCCESS;
            }
            RTSemEventMultiDestroy(pThis->hEvtRead);
        }
    }

#ifdef RTCRITSECTRW_STRICT
    RTLockValidatorRecSharedDestroy(&pThis->pValidatorRead);
    RTLockValidatorRecExclDestroy(&pThis->pValidatorWrite);
#endif
    return rc;
}
/**
 * Initializes a critical section and inserts it into the list.
 *
 * @returns VBox status code.
 * @param   pVM             Pointer to the VM.
 * @param   pCritSect       The critical section.
 * @param   pvKey           The owner key.
 * @param   RT_SRC_POS_DECL The source position.
 * @param   pszName         The name of the critical section (for statistics).
 * @param   pszNameFmt      Format string for naming the critical section.  For
 *                          statistics and lock validation.
 * @param   va              Arguments for the format string.
 */
static int pdmR3CritSectInitOne(PVM pVM, PPDMCRITSECTINT pCritSect, void *pvKey, RT_SRC_POS_DECL,
                                const char *pszNameFmt, va_list va)
{
    VM_ASSERT_EMT(pVM);

    /*
     * Allocate the semaphore.
     */
    AssertCompile(sizeof(SUPSEMEVENT) == sizeof(pCritSect->Core.EventSem));
    int rc = SUPSemEventCreate(pVM->pSession, (PSUPSEMEVENT)&pCritSect->Core.EventSem);
    if (RT_SUCCESS(rc))
    {
        /* Only format the name once. */
        char *pszName = RTStrAPrintf2V(pszNameFmt, va); /** @todo plug the "leak"... */
        if (pszName)
        {
#ifndef PDMCRITSECT_STRICT
            pCritSect->Core.pValidatorRec = NULL;
#else
            rc = RTLockValidatorRecExclCreate(&pCritSect->Core.pValidatorRec,
# ifdef RT_LOCK_STRICT_ORDER
                                              RTLockValidatorClassForSrcPos(RT_SRC_POS_ARGS, "%s", pszName),
# else
                                              NIL_RTLOCKVALCLASS,
# endif
                                              RTLOCKVAL_SUB_CLASS_NONE,
                                              pCritSect, true, "%s", pszName);
#endif
            if (RT_SUCCESS(rc))
            {
                /*
                 * Initialize the structure (first bit is c&p from RTCritSectInitEx).
                 */
                pCritSect->Core.u32Magic             = RTCRITSECT_MAGIC;
                pCritSect->Core.fFlags               = 0;
                pCritSect->Core.cNestings            = 0;
                pCritSect->Core.cLockers             = -1;
                pCritSect->Core.NativeThreadOwner    = NIL_RTNATIVETHREAD;
                pCritSect->pVMR3                     = pVM;
                pCritSect->pVMR0                     = pVM->pVMR0;
                pCritSect->pVMRC                     = pVM->pVMRC;
                pCritSect->pvKey                     = pvKey;
                pCritSect->fAutomaticDefaultCritsect = false;
                pCritSect->fUsedByTimerOrSimilar     = false;
                pCritSect->EventToSignal             = NIL_RTSEMEVENT;
                pCritSect->pNext                     = pVM->pUVM->pdm.s.pCritSects;
                pCritSect->pszName                   = pszName;
                pVM->pUVM->pdm.s.pCritSects = pCritSect;
                STAMR3RegisterF(pVM, &pCritSect->StatContentionRZLock,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionRZLock", pCritSect->pszName);
                STAMR3RegisterF(pVM, &pCritSect->StatContentionRZUnlock,STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionRZUnlock", pCritSect->pszName);
                STAMR3RegisterF(pVM, &pCritSect->StatContentionR3,      STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionR3", pCritSect->pszName);
#ifdef VBOX_WITH_STATISTICS
                STAMR3RegisterF(pVM, &pCritSect->StatLocked,        STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, NULL, "/PDM/CritSects/%s/Locked", pCritSect->pszName);
#endif
                return VINF_SUCCESS;
            }

            RTStrFree(pszName);
        }
        else
            rc = VERR_NO_STR_MEMORY;
        SUPSemEventClose(pVM->pSession, (SUPSEMEVENT)pCritSect->Core.EventSem);
    }
    return rc;
}