From: VMware, Inc <> Date: Mon, 26 Jul 2010 17:57:47 +0000 (-0700) Subject: lib/lock: got native X-Git-Tag: 2010.07.25-280253~118 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ff656cf9c844210ed9db43cf5e603969e50ce6d1;p=thirdparty%2Fopen-vm-tools.git lib/lock: got native Remove all usage of the VThreadID data type from MXUser. This includes calling VThread_CurID. This prevents a host of chicken before the egg problems that are wrapped around vthreadBase.c. In order to do this two APIs had to change: 1) The per thread contention statistics had to be removed. This is a loss since there are no tools that were interested in the data. 2) MXUser_AnyLocksHeld Changed so a VThreadID wasn't coming in. Trivial. It's MXUser_IsCurThreadHoldingLocks now. The check across everything thread case isn't necessary. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/lib/include/userlock.h b/open-vm-tools/lib/include/userlock.h index 85a5db922..67e40911a 100644 --- a/open-vm-tools/lib/include/userlock.h +++ b/open-vm-tools/lib/include/userlock.h @@ -179,7 +179,7 @@ MXUserRecLock *MXUser_InitFromMXRec(const char *name, #endif #if defined(MXUSER_DEBUG) -Bool MXUser_AnyLocksHeld(VThreadID tid); +Bool MXUser_IsCurThreadHoldingLocks(void); void MXUser_TryAcquireFailureControl(Bool (*func)(const char *lockName)); #endif @@ -188,9 +188,6 @@ void MXUser_StatisticsControl(double contentionRatio, uint64 minCount); void MXUser_PerLockData(void); -void MXUser_PerThreadData(VThreadID tid, - uint64 *totalAcquisitions, - uint64 *contendedAcquisitions); #endif void MXUser_SetInPanic(void); diff --git a/open-vm-tools/lib/lock/ul.c b/open-vm-tools/lib/lock/ul.c index 52809c0e1..845bf7816 100644 --- a/open-vm-tools/lib/lock/ul.c +++ b/open-vm-tools/lib/lock/ul.c @@ -37,38 +37,15 @@ Bool (*MXUserMX_TryLockRec)(struct MX_MutexRec *lock) = NULL; Bool (*MXUserMX_IsLockedByCurThreadRec)(const struct MX_MutexRec *lock) = NULL; -#if defined(MXUSER_DEBUG) || defined(MXUSER_STATS) -/* - *----------------------------------------------------------------------------- - * - * MXUserMaintainMaxTid -- - * - * Maintain the maximum known thread ID. - * - * Results: - * As Above. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -static Atomic_uint32 mxMaxThreadID; // implicitly initialized to 0 -- mbellon +#if defined(MXUSER_DEBUG) +#define MXUSER_MAX_LOCKS_PER_THREAD (2 * MXUSER_MAX_REC_DEPTH) -static void -MXUserMaintainMaxTid(VThreadID tid) // IN: -{ - while (TRUE) { - uint32 curValue = Atomic_Read(&mxMaxThreadID); +typedef struct { + uint32 locksHeld; + MXUserHeader *lockArray[MXUSER_MAX_LOCKS_PER_THREAD]; +} MXUserPerThread; - if (tid <= curValue) { - break; - } - - Atomic_ReadIfEqualWrite(&mxMaxThreadID, curValue, tid); - } -} +static Atomic_Ptr hashTableMem; /* @@ -93,64 +70,18 @@ MXUserMaintainMaxTid(VThreadID tid) // IN: */ MXUserPerThread * -MXUserGetPerThread(VThreadID tid, // IN: thread ID +MXUserGetPerThread(void *tid, // IN: native thread ID Bool mayAlloc) // IN: alloc perThread if not present? { - MXUserPerThread *perThread; - -#if defined(VMX86_VMX) - /* - * Inside the VMX we have a tightly controlled environment with a rigidly - * controlled maximum number of threads. That being the case, use a simple, - * low memory usage and *VERY* fast scheme to manage the perThread data. - */ - - static Atomic_Ptr perThreadArray[VTHREAD_MAX_THREADS]; - - if (tid >= VTHREAD_MAX_THREADS) { - Panic("%s: tid out of bounds (%u)\n", __FUNCTION__, tid); - } - - perThread = Atomic_ReadPtr(&perThreadArray[tid]); - - if ((perThread == NULL) && mayAlloc) { - MXUserPerThread *before; - - perThread = Util_SafeCalloc(1, sizeof(MXUserPerThread)); - - before = Atomic_ReadIfEqualWritePtr(&perThreadArray[tid], NULL, - (void *) perThread); - - if (before) { - free(perThread); - } - - MXUserMaintainMaxTid(tid); // track the maximum known tid - - perThread = Atomic_ReadPtr(&perThreadArray[tid]); - ASSERT(perThread); - } -#else - /* - * Outside the VMX there are no controls on the number of threads that can - * use MXUser locks. Here use an open ended, reasonably fast scheme for - * managing the perThread data. - * - * Use an atomic hash table to manage the perThread data. This avoids a - * great deal of locking and syncronization overhead. - */ - HashTable *hash; - - static Atomic_Ptr hashTableMem; + MXUserPerThread *perThread; hash = HashTable_AllocOnce(&hashTableMem, 1024, HASH_INT_KEY | HASH_FLAG_ATOMIC, NULL); perThread = NULL; - if (!HashTable_Lookup(hash, (void *) (uintptr_t) tid, - (void **) &perThread)) { + if (!HashTable_Lookup(hash, tid, (void **) &perThread)) { /* No entry for this tid was found, allocate one? */ if (mayAlloc) { @@ -163,8 +94,7 @@ MXUserGetPerThread(VThreadID tid, // IN: thread ID * the mess. */ - perThread = HashTable_LookupOrInsert(hash, (void *) (uintptr_t) tid, - newEntry); + perThread = HashTable_LookupOrInsert(hash, tid, newEntry); ASSERT(perThread); if (perThread != newEntry) { @@ -176,28 +106,17 @@ MXUserGetPerThread(VThreadID tid, // IN: thread ID perThread = NULL; } } -#endif return perThread; } -#endif -#if defined(MXUSER_DEBUG) /* *----------------------------------------------------------------------------- * - * MXUser_AnyLocksHeld -- - * - * Are any MXUser locks held? - * - * A tid of VTHREAD_INVALID_ID asks to check locks across all threads - * (via an linear search over all threads); such a check may return an - * incorrect or stale result in an active multi-threaded environment. + * MXUser_IsCurThreadHoldingLocks -- * - * A tid other than VTHREAD_INVALID_ID will check locks for the specified - * thread. The results of this check are always valid for the calling - * thread but may be incorrect or stale for other threads. + * Are any MXUser locks held by the calling thread? * * Results: * TRUE Yes @@ -210,31 +129,12 @@ MXUserGetPerThread(VThreadID tid, // IN: thread ID */ Bool -MXUser_AnyLocksHeld(VThreadID tid) // IN: +MXUser_IsCurThreadHoldingLocks(void) { - Bool result; - - if (tid == VTHREAD_INVALID_ID) { - uint32 i; - uint32 maxThreadID = Atomic_Read(&mxMaxThreadID); - - result = FALSE; - - for (i = 0; i < maxThreadID; i++) { - MXUserPerThread *perThread = MXUserGetPerThread(i, FALSE); - - if (perThread && (perThread->locksHeld != 0)) { - result = TRUE; - break; - } - } - } else { - MXUserPerThread *perThread = MXUserGetPerThread(tid, FALSE); - - result = (perThread == NULL) ? FALSE : (perThread->locksHeld != 0); - } + MXUserPerThread *perThread = MXUserGetPerThread(MXUserGetNativeTID(), + FALSE); - return result; + return (perThread == NULL) ? FALSE : (perThread->locksHeld != 0); } @@ -259,8 +159,7 @@ void MXUserAcquisitionTracking(MXUserHeader *header, // IN: Bool checkRank) // IN: { - VThreadID tid = VThread_CurID(); - MXUserPerThread *perThread = MXUserGetPerThread(tid, TRUE); + MXUserPerThread *perThread = MXUserGetPerThread(MXUserGetNativeTID(), TRUE); ASSERT_NOT_IMPLEMENTED(perThread->locksHeld < MXUSER_MAX_LOCKS_PER_THREAD); @@ -353,12 +252,12 @@ MXUserReleaseTracking(MXUserHeader *header) // IN: lock, via its header { uint32 i; uint32 lastEntry; - VThreadID tid = VThread_CurID(); + void *tid = MXUserGetNativeTID(); MXUserPerThread *perThread = MXUserGetPerThread(tid, FALSE); /* MXUserAcquisitionTracking should have already created a perThread */ if (UNLIKELY(perThread == NULL)) { - MXUserDumpAndPanic(header, "%s: perThread not found! (thread %u)\n", + MXUserDumpAndPanic(header, "%s: perThread not found! (thread %p)\n", __FUNCTION__, tid); } @@ -371,7 +270,7 @@ MXUserReleaseTracking(MXUserHeader *header) // IN: lock, via its header /* The argument lock had better be in the perThread */ if (UNLIKELY(i >= perThread->locksHeld)) { - MXUserDumpAndPanic(header, "%s: lock not found! (thread %u; count %u)\n", + MXUserDumpAndPanic(header, "%s: lock not found! (thread %p; count %u)\n", __FUNCTION__, tid, perThread->locksHeld); } @@ -629,7 +528,8 @@ void MXUserListLocks(void) { #if defined(MXUSER_DEBUG) - MXUserPerThread *perThread = MXUserGetPerThread(VThread_CurID(), FALSE); + MXUserPerThread *perThread = MXUserGetPerThread(MXUserGetNativeTID(), + FALSE); if (perThread != NULL) { uint32 i; diff --git a/open-vm-tools/lib/lock/ulExcl.c b/open-vm-tools/lib/lock/ulExcl.c index 9f439558b..8b6c2a73b 100644 --- a/open-vm-tools/lib/lock/ulExcl.c +++ b/open-vm-tools/lib/lock/ulExcl.c @@ -140,7 +140,6 @@ MXUserDumpExclLock(MXUserHeader *header) // IN: #if defined(MXUSER_DEBUG) Warning("\tcaller 0x%p\n", lock->recursiveLock.ownerRetAddr); - Warning("\tVThreadID %d\n", (int) lock->recursiveLock.portableThreadID); #endif } diff --git a/open-vm-tools/lib/lock/ulInt.h b/open-vm-tools/lib/lock/ulInt.h index 723f7838f..c3305d995 100644 --- a/open-vm-tools/lib/lock/ulInt.h +++ b/open-vm-tools/lib/lock/ulInt.h @@ -63,7 +63,6 @@ typedef struct { MXThreadID nativeThreadID; // Native thread ID #if defined(MXUSER_DEBUG) - VThreadID portableThreadID; // VThreadID, when available const void *ownerRetAddr; // return address of acquisition routine #endif } MXRecLock; @@ -233,7 +232,6 @@ MXRecLockInit(MXRecLock *lock) // IN/OUT: lock->referenceCount = 0; #if defined(MXUSER_DEBUG) - lock->portableThreadID = VTHREAD_INVALID_ID; lock->ownerRetAddr = NULL; #endif } @@ -267,10 +265,7 @@ MXRecLockIncCount(MXRecLock *lock, // IN/OUT: { if (MXRecLockCount(lock) == 0) { #if defined(MXUSER_DEBUG) - ASSERT(lock->portableThreadID == VTHREAD_INVALID_ID); - lock->ownerRetAddr = location; - lock->portableThreadID = VThread_CurID(); #endif MXRecLockSetOwner(lock); @@ -360,7 +355,6 @@ MXRecLockDecCount(MXRecLock *lock, // IN/OUT: #if defined(MXUSER_DEBUG) lock->ownerRetAddr = NULL; - lock->portableThreadID = VTHREAD_INVALID_ID; #endif } } @@ -385,6 +379,38 @@ MXRecLockRelease(MXRecLock *lock) // IN/OUT: } +/* + *----------------------------------------------------------------------------- + * + * MXUserGetNativeTID -- + * + * Gets a native representation of the thread ID, which can be stored + * in a pointer. + * + * Results: + * Native representation of a thread ID. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static INLINE void * +MXUserGetNativeTID(void) +{ + /* All thread types must fit into a uintptr_t */ + +#if defined(_WIN32) + ASSERT_ON_COMPILE(sizeof(DWORD) <= sizeof (void *)); + return (void *) (uintptr_t) GetCurrentThreadId(); +#else + ASSERT_ON_COMPILE(sizeof(pthread_t) <= sizeof (void *)); + return (void *) (uintptr_t) pthread_self(); +#endif +} + + /* * MXUser header - all MXUser objects start with this */ @@ -403,29 +429,6 @@ typedef struct MXUserHeader { } MXUserHeader; -/* - * The per thread information. - */ - -#if defined(MXUSER_DEBUG) || defined(MXUSER_STATS) -#define MXUSER_MAX_LOCKS_PER_THREAD (2 * MXUSER_MAX_REC_DEPTH) - -typedef struct { -#if defined(MXUSER_DEBUG) - uint32 locksHeld; - MXUserHeader *lockArray[MXUSER_MAX_LOCKS_PER_THREAD]; -#endif - -#if defined(MXUSER_STATS) - uint64 totalAcquisitions; // total thread lock acquisitions - uint64 contendedAcquisitions; // contended subset of above -#endif -} MXUserPerThread; - -MXUserPerThread *MXUserGetPerThread(VThreadID tid, - Bool mayAlloc); -#endif - /* * Internal functions */ diff --git a/open-vm-tools/lib/lock/ulRW.c b/open-vm-tools/lib/lock/ulRW.c index f5f4ac1d9..fea90394c 100644 --- a/open-vm-tools/lib/lock/ulRW.c +++ b/open-vm-tools/lib/lock/ulRW.c @@ -362,7 +362,6 @@ MXUserDumpRWLock(MXUserHeader *header) // IN: #if defined(MXUSER_DEBUG) Warning("\tcaller 0x%p\n", lock->recursiveLock.ownerRetAddr); - Warning("\tVThreadID %d\n", (int) lock->recursiveLock.portableThreadID); #endif } @@ -551,12 +550,11 @@ static HolderContext * MXUserGetHolderContext(MXUserRWLock *lock) // IN: { HolderContext *result; - VThreadID tid = VThread_CurID(); + void *threadID = MXUserGetNativeTID(); ASSERT(lock->holderTable); - if (!HashTable_Lookup(lock->holderTable, (void *) (uintptr_t) tid, - (void **) &result)) { + if (!HashTable_Lookup(lock->holderTable, threadID, (void **) &result)) { HolderContext *newContext = Util_SafeMalloc(sizeof(HolderContext)); #if defined(MXUSER_STATS) @@ -565,8 +563,7 @@ MXUserGetHolderContext(MXUserRWLock *lock) // IN: newContext->state = RW_UNLOCKED; - result = HashTable_LookupOrInsert(lock->holderTable, - (void *) (uintptr_t) tid, + result = HashTable_LookupOrInsert(lock->holderTable, threadID, (void *) newContext); if (result != newContext) { diff --git a/open-vm-tools/lib/lock/ulRec.c b/open-vm-tools/lib/lock/ulRec.c index 1e018f0b8..a3038ddee 100644 --- a/open-vm-tools/lib/lock/ulRec.c +++ b/open-vm-tools/lib/lock/ulRec.c @@ -153,7 +153,6 @@ MXUserDumpRecLock(MXUserHeader *header) // IN: #if defined(MXUSER_DEBUG) Warning("\tcaller 0x%p\n", lock->recursiveLock.ownerRetAddr); - Warning("\tVThreadID %d\n", (int) lock->recursiveLock.portableThreadID); #endif } else { Warning("\tvmmLock 0x%p\n", lock->vmmLock);