From: VMware, Inc <> Date: Thu, 17 Jun 2010 21:28:40 +0000 (-0700) Subject: lib/lock: timed condVar waiting X-Git-Tag: 2010.06.16-268169~120 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d3a6db36f5efddc085afacaa41ee07106bb7dbe1;p=thirdparty%2Fopen-vm-tools.git lib/lock: timed condVar waiting Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/lib/include/userlock.h b/open-vm-tools/lib/include/userlock.h index ff316474c..04901c824 100644 --- a/open-vm-tools/lib/include/userlock.h +++ b/open-vm-tools/lib/include/userlock.h @@ -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); diff --git a/open-vm-tools/lib/lock/ulCondVar.c b/open-vm-tools/lib/lock/ulCondVar.c index 9e30b3766..032d11ddb 100644 --- a/open-vm-tools/lib/lock/ulCondVar.c +++ b/open-vm-tools/lib/lock/ulCondVar.c @@ -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; } diff --git a/open-vm-tools/lib/lock/ulExcl.c b/open-vm-tools/lib/lock/ulExcl.c index 5faddaa07..273098ee4 100644 --- a/open-vm-tools/lib/lock/ulExcl.c +++ b/open-vm-tools/lib/lock/ulExcl.c @@ -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); } diff --git a/open-vm-tools/lib/lock/ulInt.h b/open-vm-tools/lib/lock/ulInt.h index ccb3be1a3..a1a32cb49 100644 --- a/open-vm-tools/lib/lock/ulInt.h +++ b/open-vm-tools/lib/lock/ulInt.h @@ -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) diff --git a/open-vm-tools/lib/lock/ulRec.c b/open-vm-tools/lib/lock/ulRec.c index 294f93a2a..da6bba80e 100644 --- a/open-vm-tools/lib/lock/ulRec.c +++ b/open-vm-tools/lib/lock/ulRec.c @@ -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); }