]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
lib/lock: timed condVar waiting
authorVMware, Inc <>
Thu, 17 Jun 2010 21:28:40 +0000 (14:28 -0700)
committerMarcelo Vanzin <mvanzin@vmware.com>
Thu, 17 Jun 2010 21:28:40 +0000 (14:28 -0700)
Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/include/userlock.h
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/ulRec.c

index ff316474cddcee63bbee6b5c6b1734220dbd084e..04901c82466cb0c015794ae945d8e501c043a7f3 100644 (file)
@@ -63,6 +63,10 @@ MXUser_CreateCondVarExclLock(MXUserExclLock *lock);
 void MXUser_WaitCondVarExclLock(MXUserExclLock *lock,
                                 MXUserCondVar *condVar);
 
+Bool MXUser_TimedWaitCondVarExclLock(MXUserExclLock *lock,
+                                     MXUserCondVar *condVar,
+                                     uint32 msecWait);
+
 
 /*
  * Recursive lock.
@@ -93,6 +97,10 @@ MXUser_CreateCondVarRecLock(MXUserRecLock *lock);
 void MXUser_WaitCondVarRecLock(MXUserRecLock *lock,
                                MXUserCondVar *condVar);
 
+Bool MXUser_TimedWaitCondVarRecLock(MXUserRecLock *lock,
+                                    MXUserCondVar *condVar,
+                                    uint32 msecWait);
+
 /*
  * Read-write lock
  */
@@ -123,6 +131,8 @@ MXUser_CreateSingletonRWLock(Atomic_Ptr *lockStorage,
  * Generic conditional variable functions.
  */
 
+#define MXUSER_WAIT_INFINITE 0xFFFFFFFF
+
 void MXUser_SignalCondVar(MXUserCondVar *condVar);
 void MXUser_BroadcastCondVar(MXUserCondVar *condVar);
 void MXUser_DestroyCondVar(MXUserCondVar *condVar);
index 9e30b3766b5f69d8728cec2f1008e16af84be72b..032d11ddba90269e9e5f04230bd2e63a1c2888cd 100644 (file)
@@ -229,25 +229,30 @@ MXUserDestroyInternal(MXUserCondVar *condVar)  // IN/OUT:
 static INLINE int
 MXUserWaitInternal(MXRecLock *lock,         // IN:
                    MXUserCondVar *condVar,  // IN:
-                   uint32 msecWait,         // IN: unused
+                   uint32 msecWait,         // IN:
                    Bool *signalled)         // OUT:
 {
    int err;
 
-   /*
-    * When using the native lock found within the MXUser lock, be sure to
-    * decrement the count before the wait/sleep and increment it after the
-    * wait/sleep - the (native) wait/sleep will perform a lock release before
-    * the wait/sleep and a lock acquisition after the wait/sleep. The
-    * MXUser internal accounting information must be maintained.
-    */
+   DWORD waitTime = (msecWait == MXUSER_WAIT_INFINITE) ? INFINITE : msecWait;
 
    if (pSleepConditionVariableCS) {
+      Bool success;
+
+      /*
+       * When using the native lock found within the MXUser lock, be sure to
+       * decrement the count before the wait/sleep and increment it after the
+       * wait/sleep - the (native) wait/sleep will perform a lock release
+       * before the wait/sleep and a lock acquisition after the wait/sleep.
+       * The MXUser internal accounting information must be maintained.
+       */
+
       MXRecLockDecCount(lock);
-      err = (*pSleepConditionVariableCS)(&condVar->x.condObject,
-                                         &lock->nativeLock, INFINITE) ?
-                                         0 : GetLastError();
+      success = (*pSleepConditionVariableCS)(&condVar->x.condObject,
+                                             &lock->nativeLock, waitTime);
       MXRecLockIncCount(lock, GetReturnAddress());
+
+      err = success ? 0 : GetLastError();
    } else {
       Bool done = FALSE;
 
@@ -258,17 +263,32 @@ MXUserWaitInternal(MXRecLock *lock,         // IN:
       MXRecLockRelease(lock);
 
       do {
-         WaitForSingleObject(condVar->x.compat.signalEvent, INFINITE);
+         DWORD status = WaitForSingleObject(condVar->x.compat.signalEvent,
+                                            waitTime);
 
          EnterCriticalSection(&condVar->x.compat.condVarLock);
 
          ASSERT(condVar->x.compat.numWaiters > 0);
 
-         if (condVar->x.compat.numForRelease > 0) {
+         if (status == WAIT_OBJECT_0) {
+            if (condVar->x.compat.numForRelease > 0) {
+               condVar->x.compat.numWaiters--;
+
+               if (--condVar->x.compat.numForRelease == 0) {
+                  ResetEvent(condVar->x.compat.signalEvent);
+               }
+
+               err = 0;
+               done = TRUE;
+            }
+         } else {
             condVar->x.compat.numWaiters--;
 
-            if (--condVar->x.compat.numForRelease == 0) {
-               ResetEvent(condVar->x.compat.signalEvent);
+            if ((status == WAIT_TIMEOUT) || (status == WAIT_ABANDONED)) {
+               err = WAIT_TIMEOUT;
+            } else {
+               ASSERT(status == WAIT_FAILED);
+               err = GetLastError();
             }
 
             done = TRUE;
@@ -278,11 +298,17 @@ MXUserWaitInternal(MXRecLock *lock,         // IN:
       } while (!done);
 
       MXRecLockAcquire(lock, GetReturnAddress());
-
-      err = 0;
    }
 
-   *signalled = TRUE;
+   if (err == 0) {
+      *signalled = TRUE;
+   } else {
+      *signalled = FALSE;
+
+      if (err == WAIT_TIMEOUT) {
+         err = 0;
+      }
+   }
 
    return err;
 }
@@ -449,10 +475,30 @@ MXUserWaitInternal(MXRecLock *lock,         // IN:
     */
 
    MXRecLockDecCount(lock);
-   err = pthread_cond_wait(&condVar->condObject, &lock->nativeLock);
+
+   if (msecWait == MXUSER_WAIT_INFINITE) {
+      err = pthread_cond_wait(&condVar->condObject, &lock->nativeLock);
+   } else {
+      struct timespec waitTime;
+
+      waitTime.tv_sec = msecWait / 1000;
+      waitTime.tv_nsec == 1000 * 1000 * (msecWait % 1000);
+
+      err = pthread_cond_timedwait(&condVar->condObject, &lock->nativeLock,
+                                   &waitTime);
+   }
+
    MXRecLockIncCount(lock, GetReturnAddress());
 
-   *signalled = TRUE;
+   if (err == 0) {
+      *signalled = TRUE;
+   } else {
+      *signalled = FALSE;
+
+      if (err == ETIMEDOUT) {
+         err = 0;
+      }
+   }
 
    return err;
 }
@@ -554,7 +600,8 @@ MXUserCreateCondVar(MXUserHeader *header,  // IN:
  *      The internal wait on a condition variable routine.
  *
  * Results:
- *      None.
+ *      TRUE   condvar was signalled
+ *      FALSE  timed out waiting for signal
  *
  * Side effects:
  *      An attempt to use a lock other than the one the specified condition
@@ -563,17 +610,19 @@ MXUserCreateCondVar(MXUserHeader *header,  // IN:
  *-----------------------------------------------------------------------------
  */
 
-void
+Bool
 MXUserWaitCondVar(MXUserHeader *header,    // IN:
                   MXRecLock *lock,         // IN:
-                  MXUserCondVar *condVar)  // IN/OUT:
+                  MXUserCondVar *condVar,  // IN:
+                  uint32 msecWait)         // IN:
 {
    int err;
-   Bool signalled;
+   Bool signalled = FALSE;
 
    ASSERT(header);
    ASSERT(lock);
    ASSERT(condVar && (condVar->signature == MXUSER_CONDVAR_SIGNATURE));
+   ASSERT(msecWait > 0);
 
    if (condVar->ownerLock != lock) {
       MXUserDumpAndPanic(header,
@@ -597,6 +646,8 @@ MXUserWaitCondVar(MXUserHeader *header,    // IN:
    }
 
    Atomic_Dec(&condVar->referenceCount);
+
+   return signalled;
 }
 
 
index 5faddaa070736fcd8b13a5aa748e9494695ee126..273098ee4202a4ccb7cce14ec69744571658d7b4 100644 (file)
@@ -598,7 +598,7 @@ MXUser_CreateCondVarExclLock(MXUserExclLock *lock)
 /*
  *-----------------------------------------------------------------------------
  *
- * MXUser_CondWaitExclLock --
+ * MXUser_WaitCondVarExclLock --
  *
  *      Block (sleep) on the specified condition variable. The specified lock
  *      is released upon blocking and is reacquired before returning from this
@@ -619,5 +619,37 @@ MXUser_WaitCondVarExclLock(MXUserExclLock *lock,    // IN:
 {
    ASSERT(lock && (lock->header.lockSignature == USERLOCK_SIGNATURE));
 
-   MXUserWaitCondVar(&lock->header, &lock->recursiveLock, condVar);
+   MXUserWaitCondVar(&lock->header, &lock->recursiveLock, condVar,
+                     MXUSER_WAIT_INFINITE);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_TimedWaitCondVarExclLock --
+ *
+ *      Block (sleep) on the specified condition variable for no longer than
+ *      the specified amount of time. The specified lock is released upon
+ *      blocking and is reacquired before returning from this function.
+ *
+ * Results:
+ *      TRUE   condVar was signalled
+ *      FALSE  timed out waiting for signal
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUser_TimedWaitCondVarExclLock(MXUserExclLock *lock,    // IN:
+                                MXUserCondVar *condVar,  // IN:
+                                uint32 msecWait)         // IN:
+{
+   ASSERT(lock && (lock->header.lockSignature == USERLOCK_SIGNATURE));
+
+   return MXUserWaitCondVar(&lock->header, &lock->recursiveLock, condVar,
+                            msecWait);
 }
index ccb3be1a313d00af905fe2b3f69eebdd6127f3f4..a1a32cb4926b78442418fda1986945d14af3d9e3 100644 (file)
@@ -466,9 +466,10 @@ MXUserTryAcquireFail(const char *lockName)  // IN:
 MXUserCondVar *MXUserCreateCondVar(MXUserHeader *header,
                                    MXRecLock *lock);
 
-void MXUserWaitCondVar(MXUserHeader *header,
+Bool MXUserWaitCondVar(MXUserHeader *header,
                        MXRecLock *lock,
-                       MXUserCondVar *condVar);
+                       MXUserCondVar *condVar,
+                       uint32 msecWait);
 
 
 #if defined(MXUSER_STATS)
index 294f93a2ad94a0a0c0ff71ac8a50110b0a59bedf..da6bba80e31bae96c7d3d07d0b769546eb4fdcef 100644 (file)
@@ -657,7 +657,39 @@ MXUser_WaitCondVarRecLock(MXUserRecLock *lock,     // IN:
    ASSERT(lock && (lock->header.lockSignature == USERLOCK_SIGNATURE));
    ASSERT(lock->vmmLock == NULL);  // only unbound locks
 
-   MXUserWaitCondVar(&lock->header, &lock->recursiveLock, condVar);
+   MXUserWaitCondVar(&lock->header, &lock->recursiveLock, condVar,
+                     MXUSER_WAIT_INFINITE);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUser_TimedWaitCondVarRecLock --
+ *
+ *      Block (sleep) on the specified condition variable for no longer than
+ *      the specified amount of time. The specified lock is released upon
+ *      blocking and is reacquired before returning from this function.
+ *
+ * Results:
+ *      TRUE   condVar was signalled
+ *      FALSE  timed out waiting for signal
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+MXUser_TimedWaitCondVarRecLock(MXUserRecLock *lock,     // IN:
+                               MXUserCondVar *condVar,  // IN:
+                               uint32 msecWait)         // IN:
+{
+   ASSERT(lock && (lock->header.lockSignature == USERLOCK_SIGNATURE));
+
+   return MXUserWaitCondVar(&lock->header, &lock->recursiveLock, condVar,
+                            msecWait);
 }