From: VMware, Inc <> Date: Tue, 13 Mar 2012 20:02:30 +0000 (-0700) Subject: lib/lock: Adjustable MXUser statistics overhead X-Git-Tag: 2012.03.13-651368~63 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4fd90ee2825567cff704e4cf41ad3c1a05d401dc;p=thirdparty%2Fopen-vm-tools.git lib/lock: Adjustable MXUser statistics overhead Don't let the apparent size of this change put you off, this is almost entirely a mechanical variable name change. It turns out that the timer routines used my the MXUser statistics system can be very expensive. Make the MXUser statistics overhead tunable - off, light (basic statistics) and heavy (full). "Typical" performance numbers (on my old AMD box running Linux) mode 0 - 47 ns mode 1 - 61 ns mode 2 - MUCH larger. We've got an issue with timers that Kevin filed a PR for. Signed-off-by: Dmitry Torokhov --- diff --git a/open-vm-tools/lib/include/userlock.h b/open-vm-tools/lib/include/userlock.h index 63519f550..6b24d650b 100644 --- a/open-vm-tools/lib/include/userlock.h +++ b/open-vm-tools/lib/include/userlock.h @@ -232,6 +232,7 @@ void MXUser_StatisticsControl(double contentionRatio, void MXUser_PerLockData(void); void MXUser_SetStatsFunc(void *context, uint32 maxLineLength, + Bool trackHeldTime, void (*statsFunc)(void *context, const char *fmt, va_list ap)); diff --git a/open-vm-tools/lib/lock/ul.c b/open-vm-tools/lib/lock/ul.c index aa60e7077..c635fd5c9 100644 --- a/open-vm-tools/lib/lock/ul.c +++ b/open-vm-tools/lib/lock/ul.c @@ -66,8 +66,7 @@ MXUserInternalSingleton(Atomic_Ptr *storage) // IN: MXRecLock *newLock = Util_SafeMalloc(sizeof(MXRecLock)); if (MXRecLockInit(newLock)) { - lock = (MXRecLock *) Atomic_ReadIfEqualWritePtr(storage, NULL, - (void *) newLock); + lock = Atomic_ReadIfEqualWritePtr(storage, NULL, (void *) newLock); if (lock) { MXRecLockDestroy(newLock); diff --git a/open-vm-tools/lib/lock/ulCondVar.c b/open-vm-tools/lib/lock/ulCondVar.c index 53cdc9385..47dd074cd 100644 --- a/open-vm-tools/lib/lock/ulCondVar.c +++ b/open-vm-tools/lib/lock/ulCondVar.c @@ -634,7 +634,7 @@ MXUserWaitCondVar(MXUserHeader *header, // IN: __FUNCTION__, header->name, condVar, condVar->header->name); } - if (!MXRecLockIsOwner(lock)) { + if (vmx86_debug && !MXRecLockIsOwner(lock)) { Panic("%s: lock %s for condVar (0x%p) not owned\n", __FUNCTION__, condVar->header->name, condVar); } diff --git a/open-vm-tools/lib/lock/ulExcl.c b/open-vm-tools/lib/lock/ulExcl.c index ef5366f99..ed6e8b8af 100644 --- a/open-vm-tools/lib/lock/ulExcl.c +++ b/open-vm-tools/lib/lock/ulExcl.c @@ -26,19 +26,23 @@ typedef struct { - MXUserAcquisitionStats acquisitionStats; - Atomic_Ptr acquisitionHisto; + MXUserAcquisitionStats data; + Atomic_Ptr histo; +} MXUserAcquireStats; - VmTimeType holdStart; - MXUserBasicStats heldStats; - Atomic_Ptr heldHisto; -} MXUserStats; +typedef struct +{ + VmTimeType holdStart; + MXUserBasicStats data; + Atomic_Ptr histo; +} MXUserHeldStats; struct MXUserExclLock { MXUserHeader header; MXRecLock recursiveLock; - Atomic_Ptr statsMem; + Atomic_Ptr heldStatsMem; + Atomic_Ptr acquireStatsMem; }; @@ -62,9 +66,18 @@ static void MXUserStatsActionExcl(MXUserHeader *header) // IN: { MXUserExclLock *lock = (MXUserExclLock *) header; - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem); + MXUserAcquireStats *acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); + + if (UNLIKELY(heldStats != NULL)) { + MXUserDumpBasicStats(&heldStats->data, header); + + if (Atomic_ReadPtr(&heldStats->histo) != NULL) { + MXUserHistoDump(Atomic_ReadPtr(&heldStats->histo), header); + } + } - if (stats) { + if (LIKELY(acquireStats != NULL)) { Bool isHot; Bool doLog; double contentionRatio; @@ -73,34 +86,30 @@ MXUserStatsActionExcl(MXUserHeader *header) // IN: * Dump the statistics for the specified lock. */ - MXUserDumpAcquisitionStats(&stats->acquisitionStats, header); + MXUserDumpAcquisitionStats(&acquireStats->data, header); - if (Atomic_ReadPtr(&stats->acquisitionHisto) != NULL) { - MXUserHistoDump(Atomic_ReadPtr(&stats->acquisitionHisto), header); - } - - MXUserDumpBasicStats(&stats->heldStats, header); - - if (Atomic_ReadPtr(&stats->heldHisto) != NULL) { - MXUserHistoDump(Atomic_ReadPtr(&stats->heldHisto), header); + if (Atomic_ReadPtr(&acquireStats->histo) != NULL) { + MXUserHistoDump(Atomic_ReadPtr(&acquireStats->histo), header); } /* * Has the lock gone "hot"? If so, implement the hot actions. */ - MXUserKitchen(&stats->acquisitionStats, &contentionRatio, &isHot, - &doLog); + MXUserKitchen(&acquireStats->data, &contentionRatio, &isHot, &doLog); - if (isHot) { - MXUserForceHisto(&stats->acquisitionHisto, + if (UNLIKELY(isHot)) { + MXUserForceHisto(&acquireStats->histo, MXUSER_STAT_CLASS_ACQUISITION, MXUSER_DEFAULT_HISTO_MIN_VALUE_NS, MXUSER_DEFAULT_HISTO_DECADES); - MXUserForceHisto(&stats->heldHisto, - MXUSER_STAT_CLASS_HELD, - MXUSER_DEFAULT_HISTO_MIN_VALUE_NS, - MXUSER_DEFAULT_HISTO_DECADES); + + if (UNLIKELY(heldStats != NULL)) { + MXUserForceHisto(&heldStats->histo, + MXUSER_STAT_CLASS_HELD, + MXUSER_DEFAULT_HISTO_MIN_VALUE_NS, + MXUSER_DEFAULT_HISTO_DECADES); + } if (doLog) { Log("HOT LOCK (%s); contention ratio %f\n", @@ -141,9 +150,11 @@ MXUser_ControlExclLock(MXUserExclLock *lock, // IN/OUT: switch (command) { case MXUSER_CONTROL_ACQUISITION_HISTO: { if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); - if (stats == NULL) { + if (acquireStats == NULL) { result = FALSE; } else { va_list a; @@ -155,7 +166,7 @@ MXUser_ControlExclLock(MXUserExclLock *lock, // IN/OUT: decades = va_arg(a, uint32); va_end(a); - MXUserForceHisto(&stats->acquisitionHisto, + MXUserForceHisto(&acquireStats->histo, MXUSER_STAT_CLASS_ACQUISITION, minValue, decades); result = TRUE; @@ -170,9 +181,9 @@ MXUser_ControlExclLock(MXUserExclLock *lock, // IN/OUT: case MXUSER_CONTROL_HELD_HISTO: { if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem); - if (stats == NULL) { + if (heldStats == NULL) { result = FALSE; } else { va_list a; @@ -184,7 +195,7 @@ MXUser_ControlExclLock(MXUserExclLock *lock, // IN/OUT: decades = va_arg(a, uint32); va_end(a); - MXUserForceHisto(&stats->heldHisto, MXUSER_STAT_CLASS_HELD, + MXUserForceHisto(&heldStats->histo, MXUSER_STAT_CLASS_HELD, minValue, decades); result = TRUE; @@ -198,19 +209,45 @@ MXUser_ControlExclLock(MXUserExclLock *lock, // IN/OUT: case MXUSER_CONTROL_ENABLE_STATS: { if (vmx86_stats) { - MXUserStats *stats; - MXUserStats *before; + va_list a; + Bool trackHeldTimes; + MXUserHeldStats *heldStats; + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); + + if (LIKELY(acquireStats == NULL)) { + MXUserAcquireStats *before; + + acquireStats = Util_SafeCalloc(1, sizeof(*acquireStats)); + MXUserAcquisitionStatsSetUp(&acquireStats->data); + + before = Atomic_ReadIfEqualWritePtr(&lock->acquireStatsMem, NULL, + (void *) acquireStats); + + if (before) { + free(acquireStats); + } + } + + va_start(a, command); + trackHeldTimes = va_arg(a, int); + va_end(a); + + heldStats = Atomic_ReadPtr(&lock->heldStatsMem); - stats = Util_SafeCalloc(1, sizeof(*stats)); + if ((heldStats == NULL) && trackHeldTimes) { + MXUserHeldStats *before; - MXUserAcquisitionStatsSetUp(&stats->acquisitionStats); - MXUserBasicStatsSetUp(&stats->heldStats, MXUSER_STAT_CLASS_HELD); + heldStats = Util_SafeCalloc(1, sizeof(*heldStats)); + MXUserBasicStatsSetUp(&heldStats->data, MXUSER_STAT_CLASS_HELD); - before = Atomic_ReadIfEqualWritePtr(&lock->statsMem, NULL, - (void *) stats); + before = Atomic_ReadIfEqualWritePtr(&lock->heldStatsMem, NULL, + (void *) heldStats); - if (before) { - free(stats); + if (before) { + free(heldStats); + } } lock->header.statsFunc = MXUserStatsActionExcl; @@ -285,7 +322,7 @@ MXUserExclLock * MXUser_CreateExclLock(const char *userName, // IN: MX_Rank rank) // IN: { - Bool doStats; + uint32 statsMode; char *properName; MXUserExclLock *lock; @@ -310,17 +347,25 @@ MXUser_CreateExclLock(const char *userName, // IN: lock->header.serialNumber = MXUserAllocSerialNumber(); lock->header.dumpFunc = MXUserDumpExclLock; - if (vmx86_stats) { - doStats = MXUserStatsEnabled(); - } else { - doStats = FALSE; - } + statsMode = MXUserStatsMode(); - if (doStats) { - MXUser_ControlExclLock(lock, MXUSER_CONTROL_ENABLE_STATS); - } else { + switch (statsMode) { + case 0: lock->header.statsFunc = NULL; - Atomic_WritePtr(&lock->statsMem, NULL); + Atomic_WritePtr(&lock->acquireStatsMem, NULL); + Atomic_WritePtr(&lock->heldStatsMem, NULL); + break; + + case 1: + MXUser_ControlExclLock(lock, MXUSER_CONTROL_ENABLE_STATS, FALSE); + break; + + case 2: + MXUser_ControlExclLock(lock, MXUSER_CONTROL_ENABLE_STATS, TRUE); + break; + + default: + Panic("%s: unknown stats mode: %d!\n", __FUNCTION__, statsMode); } MXUserAddToList(&lock->header); @@ -364,16 +409,25 @@ MXUser_DestroyExclLock(MXUserExclLock *lock) // IN: MXUserRemoveFromList(&lock->header); if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserHeldStats *heldStats; + MXUserAcquireStats *acquireStats; - if (LIKELY(stats != NULL)) { - MXUserAcquisitionStatsTearDown(&stats->acquisitionStats); - MXUserHistoTearDown(Atomic_ReadPtr(&stats->acquisitionHisto)); + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); - MXUserBasicStatsTearDown(&stats->heldStats); - MXUserHistoTearDown(Atomic_ReadPtr(&stats->heldHisto)); + if (LIKELY(acquireStats != NULL)) { + MXUserAcquisitionStatsTearDown(&acquireStats->data); + MXUserHistoTearDown(Atomic_ReadPtr(&acquireStats->histo)); - free(stats); + free(acquireStats); + } + + heldStats = Atomic_ReadPtr(&lock->heldStatsMem); + + if (UNLIKELY(heldStats != NULL)) { + MXUserBasicStatsTearDown(&heldStats->data); + MXUserHistoTearDown(Atomic_ReadPtr(&heldStats->histo)); + + free(heldStats); } } @@ -410,23 +464,31 @@ MXUser_AcquireExclLock(MXUserExclLock *lock) // IN/OUT: if (vmx86_stats) { VmTimeType value = 0; - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserHeldStats *heldStats; + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); - MXRecLockAcquire(&lock->recursiveLock, (stats == NULL) ? NULL : &value); + MXRecLockAcquire(&lock->recursiveLock, + (acquireStats == NULL) ? NULL : &value); - if (LIKELY(stats != NULL)) { + if (LIKELY(acquireStats != NULL)) { MXUserHisto *histo; - MXUserAcquisitionSample(&stats->acquisitionStats, TRUE, value != 0, + MXUserAcquisitionSample(&acquireStats->data, TRUE, value != 0, value); - histo = Atomic_ReadPtr(&stats->acquisitionHisto); + histo = Atomic_ReadPtr(&acquireStats->histo); if (UNLIKELY(histo != NULL)) { MXUserHistoSample(histo, value, GetReturnAddress()); } - stats->holdStart = Hostinfo_SystemTimerNS(); + heldStats = Atomic_ReadPtr(&lock->heldStatsMem); + + if (UNLIKELY(heldStats != NULL)) { + heldStats->holdStart = Hostinfo_SystemTimerNS(); + } } } else { MXRecLockAcquire(&lock->recursiveLock, @@ -464,15 +526,13 @@ MXUser_ReleaseExclLock(MXUserExclLock *lock) // IN/OUT: MXUserValidateHeader(&lock->header, MXUSER_TYPE_EXCL); if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem); - if (LIKELY(stats != NULL)) { - MXUserHisto *histo; - VmTimeType value = Hostinfo_SystemTimerNS() - stats->holdStart; + if (UNLIKELY(heldStats != NULL)) { + VmTimeType value = Hostinfo_SystemTimerNS() - heldStats->holdStart; + MXUserHisto *histo = Atomic_ReadPtr(&heldStats->histo); - MXUserBasicStatsSample(&stats->heldStats, value); - - histo = Atomic_ReadPtr(&stats->heldHisto); + MXUserBasicStatsSample(&heldStats->data, value); if (UNLIKELY(histo != NULL)) { MXUserHistoSample(histo, value, GetReturnAddress()); @@ -541,10 +601,12 @@ MXUser_TryAcquireExclLock(MXUserExclLock *lock) // IN/OUT: } if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); - if (LIKELY(stats != NULL)) { - MXUserAcquisitionSample(&stats->acquisitionStats, success, !success, + if (LIKELY(acquireStats != NULL)) { + MXUserAcquisitionSample(&acquireStats->data, success, !success, 0ULL); } } diff --git a/open-vm-tools/lib/lock/ulInt.h b/open-vm-tools/lib/lock/ulInt.h index 58a60e57d..d72559c63 100644 --- a/open-vm-tools/lib/lock/ulInt.h +++ b/open-vm-tools/lib/lock/ulInt.h @@ -539,7 +539,7 @@ uint32 MXUserAllocSerialNumber(void); void MXUserAddToList(MXUserHeader *header); void MXUserRemoveFromList(MXUserHeader *header); -Bool MXUserStatsEnabled(void); +uint32 MXUserStatsMode(void); typedef struct MXUserHisto MXUserHisto; diff --git a/open-vm-tools/lib/lock/ulRW.c b/open-vm-tools/lib/lock/ulRW.c index 9de291870..a46859435 100644 --- a/open-vm-tools/lib/lock/ulRW.c +++ b/open-vm-tools/lib/lock/ulRW.c @@ -245,13 +245,17 @@ typedef struct { VmTimeType holdStart; } HolderContext; -typedef struct { - MXUserAcquisitionStats acquisitionStats; - Atomic_Ptr acquisitionHisto; +typedef struct +{ + MXUserAcquisitionStats data; + Atomic_Ptr histo; +} MXUserAcquireStats; - MXUserBasicStats heldStats; - Atomic_Ptr heldHisto; -} MXUserStats; +typedef struct +{ + MXUserBasicStats data; + Atomic_Ptr histo; +} MXUserHeldStats; struct MXUserRWLock { @@ -264,7 +268,8 @@ struct MXUserRWLock Atomic_uint32 holderCount; HashTable *holderTable; - Atomic_Ptr statsMem; + Atomic_Ptr heldStatsMem; + Atomic_Ptr acquireStatsMem; }; @@ -288,9 +293,18 @@ static void MXUserStatsActionRW(MXUserHeader *header) // IN: { MXUserRWLock *lock = (MXUserRWLock *) header; - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem); + MXUserAcquireStats *acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); + + if (heldStats) { + MXUserDumpBasicStats(&heldStats->data, header); + + if (Atomic_ReadPtr(&heldStats->histo) != NULL) { + MXUserHistoDump(Atomic_ReadPtr(&heldStats->histo), header); + } + } - if (stats) { + if (acquireStats) { Bool isHot; Bool doLog; double contentionRatio; @@ -299,35 +313,30 @@ MXUserStatsActionRW(MXUserHeader *header) // IN: * Dump the statistics for the specified lock. */ - MXUserDumpAcquisitionStats(&stats->acquisitionStats, header); - - if (Atomic_ReadPtr(&stats->acquisitionHisto) != NULL) { - MXUserHistoDump(Atomic_ReadPtr(&stats->acquisitionHisto), header); - } - - MXUserDumpBasicStats(&stats->heldStats, header); + MXUserDumpAcquisitionStats(&acquireStats->data, header); - if (Atomic_ReadPtr(&stats->heldHisto) != NULL) { - MXUserHistoDump(Atomic_ReadPtr(&stats->heldHisto), header); + if (Atomic_ReadPtr(&acquireStats->histo) != NULL) { + MXUserHistoDump(Atomic_ReadPtr(&acquireStats->histo), header); } /* * Has the lock gone "hot"? If so, implement the hot actions. - * Allow the read and write statistics to go independently hot. */ - MXUserKitchen(&stats->acquisitionStats, &contentionRatio, &isHot, - &doLog); + MXUserKitchen(&acquireStats->data, &contentionRatio, &isHot, &doLog); if (isHot) { - MXUserForceHisto(&stats->acquisitionHisto, + MXUserForceHisto(&acquireStats->histo, MXUSER_STAT_CLASS_ACQUISITION, MXUSER_DEFAULT_HISTO_MIN_VALUE_NS, MXUSER_DEFAULT_HISTO_DECADES); - MXUserForceHisto(&stats->heldHisto, - MXUSER_STAT_CLASS_HELD, - MXUSER_DEFAULT_HISTO_MIN_VALUE_NS, - MXUSER_DEFAULT_HISTO_DECADES); + + if (heldStats) { + MXUserForceHisto(&heldStats->histo, + MXUSER_STAT_CLASS_HELD, + MXUSER_DEFAULT_HISTO_MIN_VALUE_NS, + MXUSER_DEFAULT_HISTO_DECADES); + } if (doLog) { Log("HOT LOCK (%s); contention ratio %f\n", @@ -368,9 +377,11 @@ MXUser_ControlRWLock(MXUserRWLock *lock, // IN/OUT: switch (command) { case MXUSER_CONTROL_ACQUISITION_HISTO: { if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); - if (stats == NULL) { + if (acquireStats == NULL) { result = FALSE; } else { va_list a; @@ -382,7 +393,7 @@ MXUser_ControlRWLock(MXUserRWLock *lock, // IN/OUT: decades = va_arg(a, uint32); va_end(a); - MXUserForceHisto(&stats->acquisitionHisto, + MXUserForceHisto(&acquireStats->histo, MXUSER_STAT_CLASS_ACQUISITION, minValue, decades); result = TRUE; @@ -396,9 +407,9 @@ MXUser_ControlRWLock(MXUserRWLock *lock, // IN/OUT: case MXUSER_CONTROL_HELD_HISTO: { if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem); - if (stats == NULL) { + if (heldStats == NULL) { result = FALSE; } else { va_list a; @@ -410,7 +421,7 @@ MXUser_ControlRWLock(MXUserRWLock *lock, // IN/OUT: decades = va_arg(a, uint32); va_end(a); - MXUserForceHisto(&stats->heldHisto, MXUSER_STAT_CLASS_HELD, + MXUserForceHisto(&heldStats->histo, MXUSER_STAT_CLASS_HELD, minValue, decades); result = TRUE; @@ -424,19 +435,45 @@ MXUser_ControlRWLock(MXUserRWLock *lock, // IN/OUT: case MXUSER_CONTROL_ENABLE_STATS: { if (vmx86_stats) { - MXUserStats *stats; - MXUserStats *before; + va_list a; + Bool trackHeldTimes; + MXUserHeldStats *heldStats; + MXUserAcquireStats *acquireStats; - stats = Util_SafeCalloc(1, sizeof(*stats)); + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); - MXUserAcquisitionStatsSetUp(&stats->acquisitionStats); - MXUserBasicStatsSetUp(&stats->heldStats, MXUSER_STAT_CLASS_HELD); + if (LIKELY(acquireStats == NULL)) { + MXUserAcquireStats *before; - before = Atomic_ReadIfEqualWritePtr(&lock->statsMem, NULL, - (void *) stats); + acquireStats = Util_SafeCalloc(1, sizeof(*acquireStats)); + MXUserAcquisitionStatsSetUp(&acquireStats->data); - if (before) { - free(stats); + before = Atomic_ReadIfEqualWritePtr(&lock->acquireStatsMem, NULL, + (void *) acquireStats); + + if (before) { + free(acquireStats); + } + } + + va_start(a, command); + trackHeldTimes = va_arg(a, int); + va_end(a); + + heldStats = Atomic_ReadPtr(&lock->heldStatsMem); + + if ((heldStats == NULL) && trackHeldTimes) { + MXUserHeldStats *before; + + heldStats = Util_SafeCalloc(1, sizeof(*heldStats)); + MXUserBasicStatsSetUp(&heldStats->data, MXUSER_STAT_CLASS_HELD); + + before = Atomic_ReadIfEqualWritePtr(&lock->heldStatsMem, NULL, + (void *) heldStats); + + if (before) { + free(heldStats); + } } lock->header.statsFunc = MXUserStatsActionRW; @@ -554,23 +591,31 @@ MXUser_CreateRWLock(const char *userName, // IN: lockInited = MXRecLockInit(&lock->recursiveLock); if (LIKELY(lockInited)) { - Bool doStats; + uint32 statsMode; lock->holderTable = HashTable_Alloc(256, HASH_INT_KEY | HASH_FLAG_ATOMIC, MXUserFreeHashEntry); - if (vmx86_stats) { - doStats = MXUserStatsEnabled(); - } else { - doStats = FALSE; - } + statsMode = MXUserStatsMode(); - if (doStats) { - MXUser_ControlRWLock(lock, MXUSER_CONTROL_ENABLE_STATS); - } else { + switch (statsMode) { + case 0: lock->header.statsFunc = NULL; - Atomic_WritePtr(&lock->statsMem, NULL); + Atomic_WritePtr(&lock->acquireStatsMem, NULL); + Atomic_WritePtr(&lock->heldStatsMem, NULL); + break; + + case 1: + MXUser_ControlRWLock(lock, MXUSER_CONTROL_ENABLE_STATS, FALSE); + break; + + case 2: + MXUser_ControlRWLock(lock, MXUSER_CONTROL_ENABLE_STATS, TRUE); + break; + + default: + Panic("%s: unknown stats mode: %d!\n", __FUNCTION__, statsMode); } MXUserAddToList(&lock->header); @@ -632,16 +677,25 @@ MXUser_DestroyRWLock(MXUserRWLock *lock) // IN: MXUserRemoveFromList(&lock->header); if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserHeldStats *heldStats; + MXUserAcquireStats *acquireStats; - if (LIKELY(stats != NULL)) { - MXUserAcquisitionStatsTearDown(&stats->acquisitionStats); - MXUserHistoTearDown(Atomic_ReadPtr(&stats->acquisitionHisto)); + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); - MXUserBasicStatsTearDown(&stats->heldStats); - MXUserHistoTearDown(Atomic_ReadPtr(&stats->heldHisto)); + if (LIKELY(acquireStats != NULL)) { + MXUserAcquisitionStatsTearDown(&acquireStats->data); + MXUserHistoTearDown(Atomic_ReadPtr(&acquireStats->histo)); - free(stats); + free(acquireStats); + } + + heldStats = Atomic_ReadPtr(&lock->heldStatsMem); + + if (UNLIKELY(heldStats != NULL)) { + MXUserBasicStatsTearDown(&heldStats->data); + MXUserHistoTearDown(Atomic_ReadPtr(&heldStats->histo)); + + free(heldStats); } } @@ -736,7 +790,9 @@ MXUserAcquisition(MXUserRWLock *lock, // IN/OUT: if (vmx86_stats) { VmTimeType value; - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); if (lock->useNative) { int err = 0; @@ -755,11 +811,12 @@ MXUserAcquisition(MXUserRWLock *lock, // IN/OUT: value = 0; MXRecLockAcquire(&lock->recursiveLock, - (stats == NULL) ? NULL : &value); + (acquireStats == NULL) ? NULL : &value); } - if (LIKELY(stats != NULL)) { + if (LIKELY(acquireStats != NULL)) { MXUserHisto *histo; + MXUserHeldStats *heldStats; /* * The statistics are not atomically safe so protect them when @@ -771,10 +828,9 @@ MXUserAcquisition(MXUserRWLock *lock, // IN/OUT: NULL); // non-stats } - MXUserAcquisitionSample(&stats->acquisitionStats, TRUE, value != 0, - value); + MXUserAcquisitionSample(&acquireStats->data, TRUE, value != 0, value); - histo = Atomic_ReadPtr(&stats->acquisitionHisto); + histo = Atomic_ReadPtr(&acquireStats->histo); if (UNLIKELY(histo != NULL)) { MXUserHistoSample(histo, value, GetReturnAddress()); @@ -784,7 +840,11 @@ MXUserAcquisition(MXUserRWLock *lock, // IN/OUT: MXRecLockRelease(&lock->recursiveLock); } - myContext->holdStart = Hostinfo_SystemTimerNS(); + heldStats = Atomic_ReadPtr(&lock->heldStatsMem); + + if (UNLIKELY(heldStats != NULL)) { + myContext->holdStart = Hostinfo_SystemTimerNS(); + } } } else { if (LIKELY(lock->useNative)) { @@ -931,9 +991,9 @@ MXUser_ReleaseRWLock(MXUserRWLock *lock) // IN/OUT: myContext = MXUserGetHolderContext(lock); if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem); - if (LIKELY(stats != NULL)) { + if (UNLIKELY(heldStats != NULL)) { MXUserHisto *histo; VmTimeType duration = Hostinfo_SystemTimerNS() - myContext->holdStart; @@ -947,9 +1007,9 @@ MXUser_ReleaseRWLock(MXUserRWLock *lock) // IN/OUT: NULL); // non-stats } - MXUserBasicStatsSample(&stats->heldStats, duration); + MXUserBasicStatsSample(&heldStats->data, duration); - histo = Atomic_ReadPtr(&stats->heldHisto); + histo = Atomic_ReadPtr(&heldStats->histo); if (UNLIKELY(histo != NULL)) { MXUserHistoSample(histo, duration, GetReturnAddress()); diff --git a/open-vm-tools/lib/lock/ulRec.c b/open-vm-tools/lib/lock/ulRec.c index ee07d00ea..b678b458f 100644 --- a/open-vm-tools/lib/lock/ulRec.c +++ b/open-vm-tools/lib/lock/ulRec.c @@ -26,19 +26,23 @@ typedef struct { - MXUserAcquisitionStats acquisitionStats; - Atomic_Ptr acquisitionHisto; + MXUserAcquisitionStats data; + Atomic_Ptr histo; +} MXUserAcquireStats; - uint64 holdStart; - MXUserBasicStats heldStats; - Atomic_Ptr heldHisto; -} MXUserStats; +typedef struct +{ + VmTimeType holdStart; + MXUserBasicStats data; + Atomic_Ptr histo; +} MXUserHeldStats; struct MXUserRecLock { MXUserHeader header; MXRecLock recursiveLock; - Atomic_Ptr statsMem; + Atomic_Ptr heldStatsMem; + Atomic_Ptr acquireStatsMem; Atomic_uint32 refCount; /* @@ -76,9 +80,18 @@ static void MXUserStatsActionRec(MXUserHeader *header) // IN: { MXUserRecLock *lock = (MXUserRecLock *) header; - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem); + MXUserAcquireStats *acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); + + if (UNLIKELY(heldStats != NULL)) { + MXUserDumpBasicStats(&heldStats->data, header); + + if (Atomic_ReadPtr(&heldStats->histo) != NULL) { + MXUserHistoDump(Atomic_ReadPtr(&heldStats->histo), header); + } + } - if (stats) { + if (LIKELY(acquireStats != NULL)) { Bool isHot; Bool doLog; double contentionRatio; @@ -87,34 +100,30 @@ MXUserStatsActionRec(MXUserHeader *header) // IN: * Dump the statistics for the specified lock. */ - MXUserDumpAcquisitionStats(&stats->acquisitionStats, header); + MXUserDumpAcquisitionStats(&acquireStats->data, header); - if (Atomic_ReadPtr(&stats->acquisitionHisto) != NULL) { - MXUserHistoDump(Atomic_ReadPtr(&stats->acquisitionHisto), header); - } - - MXUserDumpBasicStats(&stats->heldStats, header); - - if (Atomic_ReadPtr(&stats->heldHisto) != NULL) { - MXUserHistoDump(Atomic_ReadPtr(&stats->heldHisto), header); + if (Atomic_ReadPtr(&acquireStats->histo) != NULL) { + MXUserHistoDump(Atomic_ReadPtr(&acquireStats->histo), header); } /* * Has the lock gone "hot"? If so, implement the hot actions. */ - MXUserKitchen(&stats->acquisitionStats, &contentionRatio, &isHot, - &doLog); + MXUserKitchen(&acquireStats->data, &contentionRatio, &isHot, &doLog); - if (isHot) { - MXUserForceHisto(&stats->acquisitionHisto, + if (UNLIKELY(isHot)) { + MXUserForceHisto(&acquireStats->histo, MXUSER_STAT_CLASS_ACQUISITION, MXUSER_DEFAULT_HISTO_MIN_VALUE_NS, MXUSER_DEFAULT_HISTO_DECADES); - MXUserForceHisto(&stats->heldHisto, - MXUSER_STAT_CLASS_HELD, - MXUSER_DEFAULT_HISTO_MIN_VALUE_NS, - MXUSER_DEFAULT_HISTO_DECADES); + + if (UNLIKELY(heldStats != NULL)) { + MXUserForceHisto(&heldStats->histo, + MXUSER_STAT_CLASS_HELD, + MXUSER_DEFAULT_HISTO_MIN_VALUE_NS, + MXUSER_DEFAULT_HISTO_DECADES); + } if (doLog) { Log("HOT LOCK (%s); contention ratio %f\n", @@ -157,9 +166,11 @@ MXUser_ControlRecLock(MXUserRecLock *lock, // IN/OUT: switch (command) { case MXUSER_CONTROL_ACQUISITION_HISTO: { if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); - if ((stats != NULL) && (lock->vmmLock == NULL)) { + if ((acquireStats != NULL) && (lock->vmmLock == NULL)) { va_list a; uint32 decades; uint64 minValue; @@ -169,7 +180,7 @@ MXUser_ControlRecLock(MXUserRecLock *lock, // IN/OUT: decades = va_arg(a, uint32); va_end(a); - MXUserForceHisto(&stats->acquisitionHisto, + MXUserForceHisto(&acquireStats->histo, MXUSER_STAT_CLASS_ACQUISITION, minValue, decades); result = TRUE; @@ -185,9 +196,9 @@ MXUser_ControlRecLock(MXUserRecLock *lock, // IN/OUT: case MXUSER_CONTROL_HELD_HISTO: { if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem); - if ((stats != NULL) && (lock->vmmLock == NULL)) { + if ((heldStats != NULL) && (lock->vmmLock == NULL)) { va_list a; uint32 decades; uint32 minValue; @@ -197,7 +208,7 @@ MXUser_ControlRecLock(MXUserRecLock *lock, // IN/OUT: decades = va_arg(a, uint32); va_end(a); - MXUserForceHisto(&stats->heldHisto, MXUSER_STAT_CLASS_HELD, + MXUserForceHisto(&heldStats->histo, MXUSER_STAT_CLASS_HELD, minValue, decades); result = TRUE; @@ -208,24 +219,50 @@ MXUser_ControlRecLock(MXUserRecLock *lock, // IN/OUT: result = FALSE; } - break; + break; } case MXUSER_CONTROL_ENABLE_STATS: { if (vmx86_stats) { - MXUserStats *stats; - MXUserStats *before; + va_list a; + Bool trackHeldTimes; + MXUserHeldStats *heldStats; + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); + + if (LIKELY(acquireStats == NULL)) { + MXUserAcquireStats *before; + + acquireStats = Util_SafeCalloc(1, sizeof(*acquireStats)); + MXUserAcquisitionStatsSetUp(&acquireStats->data); + + before = Atomic_ReadIfEqualWritePtr(&lock->acquireStatsMem, NULL, + (void *) acquireStats); + + if (before) { + free(acquireStats); + } + } + + va_start(a, command); + trackHeldTimes = va_arg(a, int); + va_end(a); + + heldStats = Atomic_ReadPtr(&lock->heldStatsMem); - stats = Util_SafeCalloc(1, sizeof(*stats)); + if ((heldStats == NULL) && trackHeldTimes) { + MXUserHeldStats *before; - MXUserAcquisitionStatsSetUp(&stats->acquisitionStats); - MXUserBasicStatsSetUp(&stats->heldStats, MXUSER_STAT_CLASS_HELD); + heldStats = Util_SafeCalloc(1, sizeof(*heldStats)); + MXUserBasicStatsSetUp(&heldStats->data, MXUSER_STAT_CLASS_HELD); - before = Atomic_ReadIfEqualWritePtr(&lock->statsMem, NULL, - (void *) stats); + before = Atomic_ReadIfEqualWritePtr(&lock->heldStatsMem, NULL, + (void *) heldStats); - if (before) { - free(stats); + if (before) { + free(heldStats); + } } lock->header.statsFunc = MXUserStatsActionRec; @@ -315,7 +352,7 @@ MXUserCreateRecLock(const char *userName, // IN: MX_Rank rank, // IN: Bool beSilent) // IN: { - Bool doStats; + uint32 statsMode; char *properName; MXUserRecLock *lock; @@ -343,17 +380,25 @@ MXUserCreateRecLock(const char *userName, // IN: lock->header.serialNumber = MXUserAllocSerialNumber(); lock->header.dumpFunc = MXUserDumpRecLock; - if (beSilent) { - doStats = FALSE; - } else { - doStats = vmx86_stats && MXUserStatsEnabled(); - } + statsMode = beSilent ? 0 : MXUserStatsMode(); - if (doStats) { - MXUser_ControlRecLock(lock, MXUSER_CONTROL_ENABLE_STATS); - } else { + switch (statsMode) { + case 0: lock->header.statsFunc = NULL; - Atomic_WritePtr(&lock->statsMem, NULL); + Atomic_WritePtr(&lock->acquireStatsMem, NULL); + Atomic_WritePtr(&lock->heldStatsMem, NULL); + break; + + case 1: + MXUser_ControlRecLock(lock, MXUSER_CONTROL_ENABLE_STATS, FALSE); + break; + + case 2: + MXUser_ControlRecLock(lock, MXUSER_CONTROL_ENABLE_STATS, TRUE); + break; + + default: + Panic("%s: unknown stats mode: %d!\n", __FUNCTION__, statsMode); } MXUserAddToList(&lock->header); @@ -457,16 +502,25 @@ MXUserCondDestroyRecLock(MXUserRecLock *lock) // IN: MXUserRemoveFromList(&lock->header); if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserHeldStats *heldStats; + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); - if (LIKELY(stats != NULL)) { - MXUserAcquisitionStatsTearDown(&stats->acquisitionStats); - MXUserHistoTearDown(Atomic_ReadPtr(&stats->acquisitionHisto)); + if (acquireStats) { + MXUserAcquisitionStatsTearDown(&acquireStats->data); + MXUserHistoTearDown(Atomic_ReadPtr(&acquireStats->histo)); - MXUserBasicStatsTearDown(&stats->heldStats); - MXUserHistoTearDown(Atomic_ReadPtr(&stats->heldHisto)); + free(acquireStats); + } + + heldStats = Atomic_ReadPtr(&lock->heldStatsMem); + + if (UNLIKELY(heldStats != NULL)) { + MXUserBasicStatsTearDown(&heldStats->data); + MXUserHistoTearDown(Atomic_ReadPtr(&heldStats->histo)); - free(stats); + free(heldStats); } } } @@ -522,25 +576,32 @@ MXUser_AcquireRecLock(MXUserRecLock *lock) // IN/OUT: if (vmx86_stats) { VmTimeType value = 0; - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); MXRecLockAcquire(&lock->recursiveLock, - (stats == NULL) ? NULL : &value); + (acquireStats == NULL) ? NULL : &value); - if (LIKELY(stats != NULL)) { + if (LIKELY(acquireStats != NULL)) { if (MXRecLockCount(&lock->recursiveLock) == 1) { - MXUserHisto *histo; + MXUserHeldStats *heldStats; + MXUserHisto *histo = Atomic_ReadPtr(&acquireStats->histo); - MXUserAcquisitionSample(&stats->acquisitionStats, TRUE, + MXUserAcquisitionSample(&acquireStats->data, TRUE, value != 0, value); - histo = Atomic_ReadPtr(&stats->acquisitionHisto); + histo = Atomic_ReadPtr(&acquireStats->histo); if (UNLIKELY(histo != NULL)) { MXUserHistoSample(histo, value, GetReturnAddress()); } - stats->holdStart = Hostinfo_SystemTimerNS(); + heldStats = Atomic_ReadPtr(&lock->heldStatsMem); + + if (UNLIKELY(heldStats != NULL)) { + heldStats->holdStart = Hostinfo_SystemTimerNS(); + } } } } else { @@ -584,17 +645,25 @@ MXUser_ReleaseRecLock(MXUserRecLock *lock) // IN/OUT: (*MXUserMX_UnlockRec)(lock->vmmLock); } else { if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem); - if (LIKELY(stats != NULL)) { + if (LIKELY(heldStats != NULL)) { if (MXRecLockCount(&lock->recursiveLock) == 1) { - VmTimeType value = Hostinfo_SystemTimerNS() - stats->holdStart; - MXUserHisto *histo = Atomic_ReadPtr(&stats->heldHisto); + MXUserHeldStats *heldStats; - MXUserBasicStatsSample(&stats->heldStats, value); + heldStats = Atomic_ReadPtr(&lock->heldStatsMem); - if (UNLIKELY(histo != NULL)) { - MXUserHistoSample(histo, value, GetReturnAddress()); + 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()); + } } } } @@ -673,11 +742,13 @@ MXUser_TryAcquireRecLock(MXUserRecLock *lock) // IN/OUT: } if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem); + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem); - if (LIKELY(stats != NULL)) { - MXUserAcquisitionSample(&stats->acquisitionStats, success, - !success, 0ULL); + if (LIKELY(acquireStats != NULL)) { + MXUserAcquisitionSample(&acquireStats->data, success, !success, + 0ULL); } } } @@ -1031,7 +1102,8 @@ MXUser_BindMXMutexRec(struct MX_MutexRec *mutex, // IN: lock->header.dumpFunc = NULL; lock->header.statsFunc = NULL; - Atomic_WritePtr(&lock->statsMem, NULL); + Atomic_WritePtr(&lock->acquireStatsMem, NULL); + Atomic_WritePtr(&lock->heldStatsMem, NULL); Atomic_Write(&lock->refCount, 1); lock->vmmLock = mutex; diff --git a/open-vm-tools/lib/lock/ulSema.c b/open-vm-tools/lib/lock/ulSema.c index 4cd87f1e1..d1f2b5970 100644 --- a/open-vm-tools/lib/lock/ulSema.c +++ b/open-vm-tools/lib/lock/ulSema.c @@ -57,16 +57,16 @@ typedef sem_t NativeSemaphore; typedef struct { - MXUserAcquisitionStats acquisitionStats; - Atomic_Ptr acquisitionHisto; -} MXUserStats; + MXUserAcquisitionStats data; + Atomic_Ptr histo; +} MXUserAcquireStats; struct MXUserSemaphore { MXUserHeader header; Atomic_uint32 activeUserCount; NativeSemaphore nativeSemaphore; - Atomic_Ptr statsMem; + Atomic_Ptr acquireStatsMem; }; @@ -403,9 +403,9 @@ static void MXUserStatsActionSema(MXUserHeader *header) // IN: { MXUserSemaphore *sema = (MXUserSemaphore *) header; - MXUserStats *stats = (MXUserStats *) Atomic_ReadPtr(&sema->statsMem); + MXUserAcquireStats *acquireStats = Atomic_ReadPtr(&sema->acquireStatsMem); - if (stats) { + if (LIKELY(acquireStats != NULL)) { Bool isHot; Bool doLog; double contentionRatio; @@ -414,21 +414,20 @@ MXUserStatsActionSema(MXUserHeader *header) // IN: * Dump the statistics for the specified semaphore. */ - MXUserDumpAcquisitionStats(&stats->acquisitionStats, header); + MXUserDumpAcquisitionStats(&acquireStats->data, header); - if (Atomic_ReadPtr(&stats->acquisitionHisto) != NULL) { - MXUserHistoDump(Atomic_ReadPtr(&stats->acquisitionHisto), header); + if (Atomic_ReadPtr(&acquireStats->histo) != NULL) { + MXUserHistoDump(Atomic_ReadPtr(&acquireStats->histo), header); } /* * Has the semaphore gone "hot"? If so, implement the hot actions. */ - MXUserKitchen(&stats->acquisitionStats, &contentionRatio, &isHot, - &doLog); + MXUserKitchen(&acquireStats->data, &contentionRatio, &isHot, &doLog); if (isHot) { - MXUserForceHisto(&stats->acquisitionHisto, + MXUserForceHisto(&acquireStats->histo, MXUSER_STAT_CLASS_ACQUISITION, MXUSER_DEFAULT_HISTO_MIN_VALUE_NS, MXUSER_DEFAULT_HISTO_DECADES); @@ -511,32 +510,24 @@ MXUser_CreateSemaphore(const char *userName, // IN: } if (LIKELY(MXUserInit(&sema->nativeSemaphore) == 0)) { - Bool doStats; - MXUserStats *stats; - sema->header.signature = MXUserGetSignature(MXUSER_TYPE_SEMA); sema->header.name = properName; sema->header.rank = rank; sema->header.serialNumber = MXUserAllocSerialNumber(); sema->header.dumpFunc = MXUserDumpSemaphore; - if (vmx86_stats) { - doStats = MXUserStatsEnabled(); + if (MXUserStatsMode() == 0) { + sema->header.statsFunc = NULL; + Atomic_WritePtr(&sema->acquireStatsMem, NULL); } else { - doStats = FALSE; - } + MXUserAcquireStats *acquireStats; - if (doStats) { - sema->header.statsFunc = MXUserStatsActionSema; - - stats = Util_SafeCalloc(1, sizeof(*stats)); + acquireStats = Util_SafeCalloc(1, sizeof(*acquireStats)); - MXUserAcquisitionStatsSetUp(&stats->acquisitionStats); + MXUserAcquisitionStatsSetUp(&acquireStats->data); - Atomic_WritePtr(&sema->statsMem, stats); - } else { - sema->header.statsFunc = NULL; - Atomic_WritePtr(&sema->statsMem, NULL); + sema->header.statsFunc = MXUserStatsActionSema; + Atomic_WritePtr(&sema->acquireStatsMem, acquireStats); } MXUserAddToList(&sema->header); @@ -592,13 +583,15 @@ MXUser_DestroySemaphore(MXUserSemaphore *sema) // IN: MXUserRemoveFromList(&sema->header); if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&sema->statsMem); + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&sema->acquireStatsMem); - if (LIKELY(stats != NULL)) { - MXUserAcquisitionStatsTearDown(&stats->acquisitionStats); - MXUserHistoTearDown(Atomic_ReadPtr(&stats->acquisitionHisto)); + if (LIKELY(acquireStats != NULL)) { + MXUserAcquisitionStatsTearDown(&acquireStats->data); + MXUserHistoTearDown(Atomic_ReadPtr(&acquireStats->histo)); - free(stats); + free(acquireStats); } } @@ -642,9 +635,11 @@ MXUser_DownSemaphore(MXUserSemaphore *sema) // IN/OUT: if (vmx86_stats) { VmTimeType start = 0; Bool tryDownSuccess = FALSE; - MXUserStats *stats = Atomic_ReadPtr(&sema->statsMem); + MXUserAcquireStats *acquireStats; - if (LIKELY(stats != NULL)) { + acquireStats = Atomic_ReadPtr(&sema->acquireStatsMem); + + if (LIKELY(acquireStats != NULL)) { start = Hostinfo_SystemTimerNS(); } @@ -656,14 +651,14 @@ MXUser_DownSemaphore(MXUserSemaphore *sema) // IN/OUT: } } - if (LIKELY((err == 0) && (stats != NULL))) { + if (LIKELY((err == 0) && (acquireStats != NULL))) { MXUserHisto *histo; VmTimeType value = Hostinfo_SystemTimerNS() - start; - MXUserAcquisitionSample(&stats->acquisitionStats, TRUE, + MXUserAcquisitionSample(&acquireStats->data, TRUE, !tryDownSuccess, value); - histo = Atomic_ReadPtr(&stats->acquisitionHisto); + histo = Atomic_ReadPtr(&acquireStats->histo); if (UNLIKELY(histo != NULL)) { MXUserHistoSample(histo, value, GetReturnAddress()); @@ -720,9 +715,11 @@ MXUser_TimedDownSemaphore(MXUserSemaphore *sema, // IN/OUT: if (vmx86_stats) { VmTimeType start = 0; Bool tryDownSuccess = FALSE; - MXUserStats *stats = Atomic_ReadPtr(&sema->statsMem); + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&sema->acquireStatsMem); - if (LIKELY(stats != NULL)) { + if (LIKELY(acquireStats != NULL)) { start = Hostinfo_SystemTimerNS(); } @@ -737,14 +734,14 @@ MXUser_TimedDownSemaphore(MXUserSemaphore *sema, // IN/OUT: } } - if (LIKELY((err == 0) && (stats != NULL))) { + if (LIKELY((err == 0) && (acquireStats != NULL))) { VmTimeType value = Hostinfo_SystemTimerNS() - start; - MXUserAcquisitionSample(&stats->acquisitionStats, downOccurred, + MXUserAcquisitionSample(&acquireStats->data, downOccurred, !tryDownSuccess, value); if (downOccurred) { - MXUserHisto *histo = Atomic_ReadPtr(&stats->acquisitionHisto); + MXUserHisto *histo = Atomic_ReadPtr(&acquireStats->histo); if (UNLIKELY(histo != NULL)) { MXUserHistoSample(histo, value, GetReturnAddress()); @@ -809,10 +806,12 @@ MXUser_TryDownSemaphore(MXUserSemaphore *sema) // IN/OUT: } if (vmx86_stats) { - MXUserStats *stats = Atomic_ReadPtr(&sema->statsMem); + MXUserAcquireStats *acquireStats; + + acquireStats = Atomic_ReadPtr(&sema->acquireStatsMem); - if (LIKELY(stats != NULL)) { - MXUserAcquisitionSample(&stats->acquisitionStats, downOccurred, + if (LIKELY(acquireStats != NULL)) { + MXUserAcquisitionSample(&acquireStats->data, downOccurred, !downOccurred, 0ULL); } } diff --git a/open-vm-tools/lib/lock/ulStats.c b/open-vm-tools/lib/lock/ulStats.c index 4f9a98f21..f3bb892f9 100644 --- a/open-vm-tools/lib/lock/ulStats.c +++ b/open-vm-tools/lib/lock/ulStats.c @@ -56,6 +56,7 @@ struct MXUserHisto { TopOwner ownerArray[TOPOWNERS]; // List of top owners }; +static Bool mxUserTrackHeldTimes = FALSE; static char *mxUserHistoLine = NULL; static uint32 mxUserMaxLineLength = 0; static void *mxUserStatsContext = NULL; @@ -904,17 +905,17 @@ MXUserForceHisto(Atomic_Ptr *histoPtr, // IN/OUT: } } - /* *----------------------------------------------------------------------------- * - * MXUserStatsEnabled -- + * MXUserStatsMode -- * - * Are statistics keeping enabled + * What's to be done with statistics? * * Results: - * TRUE Yes - * FALSE NO + * 0 Statstics are disabled + * 1 Collect statistics without tracking held times + * 2 Collect statistics with track held times * * Side effects: * None @@ -922,10 +923,14 @@ MXUserForceHisto(Atomic_Ptr *histoPtr, // IN/OUT: *----------------------------------------------------------------------------- */ -Bool -MXUserStatsEnabled(void) +uint32 +MXUserStatsMode(void) { - return (mxUserStatsFunc != NULL) && (mxUserMaxLineLength > 0); + if (vmx86_stats && (mxUserStatsFunc != NULL) && (mxUserMaxLineLength > 0)) { + return mxUserTrackHeldTimes ? 2 : 1; + } else { + return 0; + } } @@ -952,6 +957,7 @@ MXUserStatsEnabled(void) void MXUser_SetStatsFunc(void *context, // IN: uint32 maxLineLength, // IN: + Bool trackHeldTimes, // IN: void (*statsFunc)(void *context, // IN: const char *fmt, va_list ap)) @@ -964,6 +970,7 @@ MXUser_SetStatsFunc(void *context, // IN: mxUserStatsContext = context; mxUserMaxLineLength = maxLineLength; mxUserStatsFunc = statsFunc; + mxUserTrackHeldTimes = trackHeldTimes; }