Fix level when using pthreads recursive mutex

When using the pthreads recursive mutex, the level method was only able
to return either zero or one, but a recursive mutex can be locked more
than once.

Additionally, the way this detected if the mutex was already locked was
to test whether it can be locked again. If testing from the thread that
is currently holding the lock, this locking attempt always succeeds, and
therefore determines that the lock is _not_ held at all. This is
especially bad, as this operation only makes sense to perform from the
thread that holds the lock -- if any thread not holding the lock queries
the number of times the lock is held, that answer can change before the
thread can used it.

Signed-off-by: Bobby Bingham <koorogi@koorogi.info>
(cherry picked from commit 999cebcb5d)
r14.1.x
Bobby Bingham 2 years ago committed by Michele Calgaro
parent d7c0502bf9
commit c87fb38122
Signed by: MicheleC
GPG Key ID: 2A75B7CA8ADED5CF

@ -88,6 +88,7 @@ public:
int level(); int level();
bool recursive; bool recursive;
int count;
}; };
#ifndef Q_RECURSIVE_MUTEX_TYPE #ifndef Q_RECURSIVE_MUTEX_TYPE
@ -127,7 +128,7 @@ TQMutexPrivate::~TQMutexPrivate()
// real mutex class // real mutex class
TQRealMutexPrivate::TQRealMutexPrivate(bool recurs) TQRealMutexPrivate::TQRealMutexPrivate(bool recurs)
: recursive(recurs) : count(0), recursive(recurs)
{ {
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); pthread_mutexattr_init(&attr);
@ -146,36 +147,31 @@ void TQRealMutexPrivate::lock()
{ {
int ret = pthread_mutex_lock(&handle); int ret = pthread_mutex_lock(&handle);
if (!ret) {
count++;
} else {
#ifdef QT_CHECK_RANGE #ifdef QT_CHECK_RANGE
if (ret)
tqWarning("Mutex lock failure: %s", strerror(ret)); tqWarning("Mutex lock failure: %s", strerror(ret));
#endif #endif
}
} }
void TQRealMutexPrivate::unlock() void TQRealMutexPrivate::unlock()
{ {
count--;
int ret = pthread_mutex_unlock(&handle); int ret = pthread_mutex_unlock(&handle);
if (ret) {
count++;
#ifdef QT_CHECK_RANGE #ifdef QT_CHECK_RANGE
if (ret)
tqWarning("Mutex unlock failure: %s", strerror(ret)); tqWarning("Mutex unlock failure: %s", strerror(ret));
#endif #endif
}
} }
bool TQRealMutexPrivate::locked() bool TQRealMutexPrivate::locked()
{ {
int ret = pthread_mutex_trylock(&handle); return count > 0;
if (ret == EBUSY) {
return TRUE;
} else if (ret) {
#ifdef QT_CHECK_RANGE
tqWarning("Mutex locktest failure: %s", strerror(ret));
#endif
} else
pthread_mutex_unlock(&handle);
return FALSE;
} }
bool TQRealMutexPrivate::trylock() bool TQRealMutexPrivate::trylock()
@ -201,7 +197,7 @@ int TQRealMutexPrivate::type() const
int TQRealMutexPrivate::level() int TQRealMutexPrivate::level()
{ {
return locked(); return count;
} }

Loading…
Cancel
Save