]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
lib/lock: generalize MXUser condVar support
authorVMware, Inc <>
Thu, 17 Jun 2010 21:32:28 +0000 (14:32 -0700)
committerMarcelo Vanzin <mvanzin@vmware.com>
Thu, 17 Jun 2010 21:32:28 +0000 (14:32 -0700)
The MXUser condVar code dealt only with a lock count of 1,
something that is OK for exclusive locks and recursive locks with
that lock count but not correct for recursive locks in the general
case. Fix this by properly preserving the lock count.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/lock/ulCondVar.c
open-vm-tools/lib/lock/ulInt.h

index 1e80578247cd9cd5a44c67ba8dc582a24c84c4b3..af79be90a47ca06ddda2a1561af9a245d510957f 100644 (file)
@@ -233,6 +233,7 @@ MXUserWaitInternal(MXUserHeader *header,    // IN:
    DWORD err;
    Bool signalled;
 
+   uint32 lockCount = MXRecLockCount(lock);
    DWORD waitTime = (msecWait == MXUSER_WAIT_INFINITE) ? INFINITE : msecWait;
 
    if (pSleepConditionVariableCS) {
@@ -246,11 +247,11 @@ MXUserWaitInternal(MXUserHeader *header,    // IN:
        * The MXUser internal accounting information must be maintained.
        */
 
-      MXRecLockDecCount(lock);
+      MXRecLockDecCount(lock, lockCount);
       success = (*pSleepConditionVariableCS)(&condVar->x.condObject,
                                              &lock->nativeLock, waitTime);
       err = success ? ERROR_SUCCESS : GetLastError();
-      MXRecLockIncCount(lock, GetReturnAddress());
+      MXRecLockIncCount(lock, GetReturnAddress(), lockCount);
       signalled = (err == ERROR_SUCCESS) ? TRUE : FALSE;
    } else {
       Bool done = FALSE;
@@ -259,6 +260,7 @@ MXUserWaitInternal(MXUserHeader *header,    // IN:
       condVar->x.compat.numWaiters++;
       LeaveCriticalSection(&condVar->x.compat.condVarLock);
 
+      MXRecLockDecCount(lock, lockCount - 1);
       MXRecLockRelease(lock);
 
       do {
@@ -305,6 +307,7 @@ MXUserWaitInternal(MXUserHeader *header,    // IN:
       } while (!done);
 
       MXRecLockAcquire(lock, GetReturnAddress());
+      MXRecLockIncCount(lock, GetReturnAddress(), lockCount - 1);
    }
 
    if (err != ERROR_SUCCESS) {
@@ -466,6 +469,7 @@ MXUserWaitInternal(MXUserHeader *header,    // IN:
 {
    int err;
    Bool signalled;
+   uint32 lockCount = MXRecLockCount(lock);
 
    /*
     * When using the native lock found within the MXUser lock, be sure to
@@ -475,7 +479,7 @@ MXUserWaitInternal(MXUserHeader *header,    // IN:
     * MXUser internal accounting information must be maintained.
     */
 
-   MXRecLockDecCount(lock);
+   MXRecLockDecCount(lock, lockCount);
 
    if (msecWait == MXUSER_WAIT_INFINITE) {
       err = pthread_cond_wait(&condVar->condObject, &lock->nativeLock);
@@ -497,7 +501,7 @@ MXUserWaitInternal(MXUserHeader *header,    // IN:
       }
    }
 
-   MXRecLockIncCount(lock, GetReturnAddress());
+   MXRecLockIncCount(lock, GetReturnAddress(), lockCount);
 
    if (err != 0) {
       MXUserDumpAndPanic(header, "%s: failure %d on condVar (%p; %s)\n",
@@ -633,9 +637,9 @@ MXUserWaitCondVar(MXUserHeader *header,    // IN:
                          __FUNCTION__, header->lockName, condVar->name);
    }
 
-   if (MXRecLockCount(lock) == 0) {
+   if (!MXRecLockIsOwner(lock)) {
       MXUserDumpAndPanic(header,
-                         "%s: unlocked lock %s with condVar (%p; %s)\n",
+                         "%s: do not own lock %s for condVar (%p; %s)\n",
                          __FUNCTION__, header->lockName, condVar->name);
    }
 
index b763950001e8f0408c5e082082b68029458b85ec..5d66083aabe9a4b4aed78b94740fc380bc68a4c9 100644 (file)
@@ -262,7 +262,8 @@ MXRecLockCount(const MXRecLock *lock)  // IN:
 
 static INLINE void
 MXRecLockIncCount(MXRecLock *lock,  // IN/OUT:
-                  void *location)   // IN:
+                  void *location,   // IN:
+                  uint32 count)     // IN:
 {
    if (MXRecLockCount(lock) == 0) {
 #if defined(MXUSER_DEBUG)
@@ -275,7 +276,7 @@ MXRecLockIncCount(MXRecLock *lock,  // IN/OUT:
       MXRecLockSetOwner(lock);
    }
 
-   lock->referenceCount++;
+   lock->referenceCount += count;
 }
 
 
@@ -313,7 +314,7 @@ MXRecLockAcquire(MXRecLock *lock,  // IN/OUT:
       ASSERT(lock->referenceCount == 0);
    }
 
-   MXRecLockIncCount(lock, location);
+   MXRecLockIncCount(lock, location, 1);
 
    return contended;
 }
@@ -329,7 +330,7 @@ MXRecLockTryAcquire(MXRecLock *lock,  // IN/OUT:
    err = MXRecLockTryAcquireInternal(lock);
 
    if (err == 0) {
-      MXRecLockIncCount(lock, location);
+      MXRecLockIncCount(lock, location, 1);
 
       ASSERT((MXRecLockCount(lock) > 0) &&
              (MXRecLockCount(lock) < MXUSER_MAX_REC_DEPTH));
@@ -348,9 +349,11 @@ MXRecLockTryAcquire(MXRecLock *lock,  // IN/OUT:
 }
 
 static INLINE void
-MXRecLockDecCount(MXRecLock *lock)  // IN/OUT:
+MXRecLockDecCount(MXRecLock *lock,  // IN/OUT:
+                  uint32 count)     // IN:
 {
-   lock->referenceCount--;
+   ASSERT(count <= lock->referenceCount);
+   lock->referenceCount -= count;
 
    if (MXRecLockCount(lock) == 0) {
       MXRecLockSetNoOwner(lock);
@@ -369,7 +372,7 @@ MXRecLockRelease(MXRecLock *lock)  // IN/OUT:
    ASSERT((MXRecLockCount(lock) > 0) &&
           (MXRecLockCount(lock) < MXUSER_MAX_REC_DEPTH));
 
-   MXRecLockDecCount(lock);
+   MXRecLockDecCount(lock, 1);
 
    if (MXRecLockCount(lock) == 0) {
       int err = MXRecLockReleaseInternal(lock);