void MXUser_PerLockData(void);
void MXUser_SetStatsFunc(void *context,
uint32 maxLineLength,
+ Bool trackHeldTime,
void (*statsFunc)(void *context,
const char *fmt,
va_list ap));
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);
__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);
}
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;
};
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;
* 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",
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;
decades = va_arg(a, uint32);
va_end(a);
- MXUserForceHisto(&stats->acquisitionHisto,
+ MXUserForceHisto(&acquireStats->histo,
MXUSER_STAT_CLASS_ACQUISITION, minValue, decades);
result = TRUE;
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;
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;
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;
MXUser_CreateExclLock(const char *userName, // IN:
MX_Rank rank) // IN:
{
- Bool doStats;
+ uint32 statsMode;
char *properName;
MXUserExclLock *lock;
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);
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);
}
}
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,
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());
}
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);
}
}
void MXUserAddToList(MXUserHeader *header);
void MXUserRemoveFromList(MXUserHeader *header);
-Bool MXUserStatsEnabled(void);
+uint32 MXUserStatsMode(void);
typedef struct MXUserHisto MXUserHisto;
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
{
Atomic_uint32 holderCount;
HashTable *holderTable;
- Atomic_Ptr statsMem;
+ Atomic_Ptr heldStatsMem;
+ Atomic_Ptr acquireStatsMem;
};
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;
* 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",
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;
decades = va_arg(a, uint32);
va_end(a);
- MXUserForceHisto(&stats->acquisitionHisto,
+ MXUserForceHisto(&acquireStats->histo,
MXUSER_STAT_CLASS_ACQUISITION, minValue, decades);
result = TRUE;
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;
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;
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;
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);
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);
}
}
if (vmx86_stats) {
VmTimeType value;
- MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem);
+ MXUserAcquireStats *acquireStats;
+
+ acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem);
if (lock->useNative) {
int err = 0;
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
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());
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)) {
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;
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());
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;
/*
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;
* 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",
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;
decades = va_arg(a, uint32);
va_end(a);
- MXUserForceHisto(&stats->acquisitionHisto,
+ MXUserForceHisto(&acquireStats->histo,
MXUSER_STAT_CLASS_ACQUISITION, minValue, decades);
result = TRUE;
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;
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;
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;
MX_Rank rank, // IN:
Bool beSilent) // IN:
{
- Bool doStats;
+ uint32 statsMode;
char *properName;
MXUserRecLock *lock;
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);
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);
}
}
}
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 {
(*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());
+ }
}
}
}
}
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);
}
}
}
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;
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;
};
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;
* 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);
}
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);
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);
}
}
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();
}
}
}
- 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());
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();
}
}
}
- 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());
}
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);
}
}
TopOwner ownerArray[TOPOWNERS]; // List of top owners
};
+static Bool mxUserTrackHeldTimes = FALSE;
static char *mxUserHistoLine = NULL;
static uint32 mxUserMaxLineLength = 0;
static void *mxUserStatsContext = NULL;
}
}
-
/*
*-----------------------------------------------------------------------------
*
- * 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
*-----------------------------------------------------------------------------
*/
-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;
+ }
}
void
MXUser_SetStatsFunc(void *context, // IN:
uint32 maxLineLength, // IN:
+ Bool trackHeldTimes, // IN:
void (*statsFunc)(void *context, // IN:
const char *fmt,
va_list ap))
mxUserStatsContext = context;
mxUserMaxLineLength = maxLineLength;
mxUserStatsFunc = statsFunc;
+ mxUserTrackHeldTimes = trackHeldTimes;
}