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; }
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; }