From 7e1e42cbf269c4fd5bbfa0411964bd14e5ae549c Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Wed, 3 Sep 2014 09:57:58 +0200 Subject: Android: Avoid deadlocks on suspend Get rid of the rendezvous at shutdown: the android thread does not need to wait for the GUI thread. Since the GUI thread frequently does blocking calls to the android thread, this fixes several known and potential deadlocks. Task-number: QTBUG-41072 Change-Id: Ia6fa8da026b1727e7352b22f4df4d72b63b8c847 Reviewed-by: BogDan Vatra Reviewed-by: Christian Stromme --- .../platforms/android/qandroideventdispatcher.cpp | 21 +++++++++++++-------- .../platforms/android/qandroideventdispatcher.h | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/plugins/platforms/android/qandroideventdispatcher.cpp b/src/plugins/platforms/android/qandroideventdispatcher.cpp index 074ba71f80..ab5070af9d 100644 --- a/src/plugins/platforms/android/qandroideventdispatcher.cpp +++ b/src/plugins/platforms/android/qandroideventdispatcher.cpp @@ -55,20 +55,26 @@ QAndroidEventDispatcher::~QAndroidEventDispatcher() QAndroidEventDispatcherStopper::instance()->removeEventDispatcher(this); } +enum States {Running = 0, StopRequest = 1, Stopping = 2}; + void QAndroidEventDispatcher::start() { - if (m_stopRequest.testAndSetAcquire(1, 0)) { - m_dispatcherSemaphore.release(); + int prevState = m_stopRequest.fetchAndStoreAcquire(Running); + if (prevState == Stopping) { + m_semaphore.release(); wakeUp(); + } else if (prevState == Running) { + qWarning("Error: start without corresponding stop"); } + //else if prevState == StopRequest, no action needed } void QAndroidEventDispatcher::stop() { - if (m_stopRequest.testAndSetAcquire(0, 1)) { + if (m_stopRequest.testAndSetAcquire(Running, StopRequest)) wakeUp(); - m_stopperSemaphore.acquire(); - } + else + qWarning("Error: start/stop out of sync"); } void QAndroidEventDispatcher::goingToStop(bool stop) @@ -80,9 +86,8 @@ void QAndroidEventDispatcher::goingToStop(bool stop) int QAndroidEventDispatcher::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timespec *timeout) { - if (m_stopRequest.load() == 1) { - m_stopperSemaphore.release(); - m_dispatcherSemaphore.acquire(); + if (m_stopRequest.testAndSetAcquire(StopRequest, Stopping)) { + m_semaphore.acquire(); wakeUp(); } diff --git a/src/plugins/platforms/android/qandroideventdispatcher.h b/src/plugins/platforms/android/qandroideventdispatcher.h index 8d1bcf2122..284c5fd392 100644 --- a/src/plugins/platforms/android/qandroideventdispatcher.h +++ b/src/plugins/platforms/android/qandroideventdispatcher.h @@ -66,7 +66,7 @@ protected: private: QAtomicInt m_stopRequest; QAtomicInt m_goingToStop; - QSemaphore m_dispatcherSemaphore, m_stopperSemaphore; + QSemaphore m_semaphore; }; class QAndroidEventDispatcherStopper -- cgit v1.2.3