]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
lib/lock: got native
authorVMware, Inc <>
Mon, 26 Jul 2010 17:57:47 +0000 (10:57 -0700)
committerMarcelo Vanzin <mvanzin@vmware.com>
Mon, 26 Jul 2010 17:57:47 +0000 (10:57 -0700)
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 <mvanzin@vmware.com>
open-vm-tools/lib/include/userlock.h
open-vm-tools/lib/lock/ul.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

index 85a5db9228b7d055b2679823d9be7c3e5ff086ea..67e40911ae88890b1eb0d973e5e1f3687ffa7d4e 100644 (file)
@@ -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);
index 52809c0e1fc29886abe5f6f0413efdc6f168b048..845bf78160a716a83b32404f1a07e29516845a2f 100644 (file)
@@ -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;
index 9f439558b617a4a9a51be4f17d5c156e22b8456d..8b6c2a73b3a3ab9f5630d8a63e3a95711a2745c7 100644 (file)
@@ -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
 }
 
index 723f7838ff19a635541b3f46f825de31002af37a..c3305d995b0d0784cbb00c29d60a63338165308f 100644 (file)
@@ -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
  */
index f5f4ac1d90bcced6896e4d0132f488aa92fd80d8..fea90394ce93846e2b1b2287c85a039f1e7d85db 100644 (file)
@@ -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) {
index 1e018f0b8ba8e67dcf68bbdc89e11b3f0e7a2669..a3038ddeeb1b9f98ece4424c1bc390a247fcc5e0 100644 (file)
@@ -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);