void MXUser_ReleaseRecLock(MXUserRecLock *lock) // IN/OUT: { ASSERT(lock); MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC); ASSERT(Atomic_Read(&lock->refCount) > 0); if (UNLIKELY(lock->vmmLock != NULL)) { ASSERT(MXUserMX_UnlockRec); (*MXUserMX_UnlockRec)(lock->vmmLock); } else { if (vmx86_stats) { MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem); if (LIKELY(heldStats != NULL)) { if (MXRecLockCount(&lock->recursiveLock) == 1) { MXUserHeldStats *heldStats; heldStats = Atomic_ReadPtr(&lock->heldStatsMem); if (UNLIKELY(heldStats != NULL)) { VmTimeType value; MXUserHisto *histo = Atomic_ReadPtr(&heldStats->histo); value = Hostinfo_SystemTimerNS() - heldStats->holdStart; MXUserBasicStatsSample(&heldStats->data, value); if (UNLIKELY(histo != NULL)) { MXUserHistoSample(histo, value, GetReturnAddress()); } } } } } if (vmx86_debug) { if (MXRecLockCount(&lock->recursiveLock) == 0) { MXUserDumpAndPanic(&lock->header, "%s: Release of an unacquired recursive lock\n", __FUNCTION__); } if (!MXRecLockIsOwner(&lock->recursiveLock)) { MXUserDumpAndPanic(&lock->header, "%s: Non-owner release of an recursive lock\n", __FUNCTION__); } } MXUserReleaseTracking(&lock->header); MXRecLockRelease(&lock->recursiveLock); } }
void MXUser_ReleaseExclLock(MXUserExclLock *lock) // IN/OUT: { ASSERT(lock); MXUserValidateHeader(&lock->header, MXUSER_TYPE_EXCL); if (vmx86_stats) { MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); if (LIKELY(stats != NULL)) { MXUserHisto *histo; VmTimeType value = Hostinfo_SystemTimerNS() - stats->holdStart; MXUserBasicStatsSample(&stats->heldStats, value); histo = Atomic_ReadPtr(&stats->heldHisto); if (UNLIKELY(histo != NULL)) { MXUserHistoSample(histo, value, GetReturnAddress()); } } } if (vmx86_debug && !MXRecLockIsOwner(&lock->recursiveLock)) { int lockCount = MXRecLockCount(&lock->recursiveLock); MXUserDumpAndPanic(&lock->header, "%s: Non-owner release of an %s exclusive lock\n", __FUNCTION__, lockCount == 0 ? "unacquired" : "acquired"); } MXUserReleaseTracking(&lock->header); MXRecLockRelease(&lock->recursiveLock); }
void MXUserAcquisitionSample(MXUserAcquisitionStats *stats, // IN/OUT: Bool wasAcquired, // IN: Bool wasContended, // IN: uint64 elapsedTime) // IN: { stats->numAttempts++; if (wasAcquired) { stats->numSuccesses++; if (wasContended) { stats->numSuccessesContended++; stats->totalContentionTime += elapsedTime; stats->successContentionTime += elapsedTime; } MXUserBasicStatsSample(&stats->basicStats, elapsedTime); } else { ASSERT(wasContended); stats->totalContentionTime += elapsedTime; } }
void MXUser_ReleaseRWLock(MXUserRWLock *lock) // IN/OUT: { HolderContext *myContext; ASSERT(lock); MXUserValidateHeader(&lock->header, MXUSER_TYPE_RW); myContext = MXUserGetHolderContext(lock); if (vmx86_stats) { MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); if (LIKELY(stats != NULL)) { MXUserHisto *histo; VmTimeType duration = Hostinfo_SystemTimerNS() - myContext->holdStart; /* * The statistics are not always atomically safe so protect them * when necessary */ if ((myContext->state == RW_LOCKED_FOR_READ) && lock->useNative) { MXRecLockAcquire(&lock->recursiveLock, NULL); // non-stats } MXUserBasicStatsSample(&stats->heldStats, duration); histo = Atomic_ReadPtr(&stats->heldHisto); if (UNLIKELY(histo != NULL)) { MXUserHistoSample(histo, duration, GetReturnAddress()); } if ((myContext->state == RW_LOCKED_FOR_READ) && lock->useNative) { MXRecLockRelease(&lock->recursiveLock); } } } if (UNLIKELY(myContext->state == RW_UNLOCKED)) { uint32 lockCount = Atomic_Read(&lock->holderCount); MXUserDumpAndPanic(&lock->header, "%s: Non-owner release of an %s read-write lock\n", __FUNCTION__, lockCount == 0 ? "unacquired" : "acquired"); } MXUserReleaseTracking(&lock->header); Atomic_Dec(&lock->holderCount); if (LIKELY(lock->useNative)) { int err = MXUserNativeRWRelease(&lock->nativeLock, myContext->state == RW_LOCKED_FOR_READ); if (UNLIKELY(err != 0)) { MXUserDumpAndPanic(&lock->header, "%s: Internal error (%d)\n", __FUNCTION__, err); } } else { ASSERT(Atomic_Read(&lock->holderCount) == 0); MXRecLockRelease(&lock->recursiveLock); } myContext->state = RW_UNLOCKED; }