]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
lib/lock: Adjustable MXUser statistics overhead
authorVMware, Inc <>
Tue, 13 Mar 2012 20:02:30 +0000 (13:02 -0700)
committerDmitry Torokhov <dtor@vmware.com>
Wed, 14 Mar 2012 16:04:57 +0000 (09:04 -0700)
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 <dtor@vmware.com>
open-vm-tools/lib/include/userlock.h
open-vm-tools/lib/lock/ul.c
open-vm-tools/lib/lock/ulCondVar.c
open-vm-tools/lib/lock/ulExcl.c
open-vm-tools/lib/lock/ulInt.h
open-vm-tools/lib/lock/ulRW.c
open-vm-tools/lib/lock/ulRec.c
open-vm-tools/lib/lock/ulSema.c
open-vm-tools/lib/lock/ulStats.c

index 63519f550aff8b61a1bbe3195271fe18e3990b2e..6b24d650b472a3a5ffd66ed748b758b2a5a4eb89 100644 (file)
@@ -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));
index aa60e707776e62c7b02c1d7b7203b838eb1f64f2..c635fd5c99ad56c9165d0b0d5195e5533362e057 100644 (file)
@@ -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);
index 53cdc9385d0a015723ba6aa36f9f7b3675933aed..47dd074cde4b81fb808c0d6ad413f01b38a0cd43 100644 (file)
@@ -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);
    }
index ef5366f9978e3581b23f9bc618369da41d1b9075..ed6e8b8af8dc278258a21772d02330c9782e0a12 100644 (file)
 
 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);
       }
    }
index 58a60e57d36159ed5360bf8d55108f2cbd015542..d72559c63940f525c299c45168f475ddb5e324a8 100644 (file)
@@ -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;
 
index 9de2918701631728a5bf4af7db19dfec85b7cc4d..a46859435a51d876c28159018bf6efe2f261cecc 100644 (file)
@@ -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());
index ee07d00ea668f29f0524bec65f4770448b2e87f6..b678b458f606ded4c320db32502784ed72853978 100644 (file)
 
 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;
index 4cd87f1e13303ba464322f162807e3c8a0c1b1ad..d1f2b5970bccf825cd173929111b15c136892c1f 100644 (file)
@@ -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);
       }
    }
index 4f9a98f216e4589e1e6a2dc0f23dddb23a55954f..f3bb892f9bc673d74df90e2571f70362eb942a3a 100644 (file)
@@ -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;
 }