From ffad7d1fdc8297df8285f16592f6f2ec3cab9828 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Mon, 6 May 2013 14:25:20 -0700 Subject: [PATCH] Add new Looper API to check whether the looper is idle. This is just to support the watchdog to give it a faster way to determine if a thread is deadlocked without having to post a message to it. Change-Id: I068dc8b9387caf94fe5811fb4aeb0f9b57b1a080 --- include/utils/Looper.h | 11 +++++++++++ libs/utils/Looper.cpp | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/utils/Looper.h b/include/utils/Looper.h index d4a0067fd..2e0651a3c 100644 --- a/include/utils/Looper.h +++ b/include/utils/Looper.h @@ -296,6 +296,13 @@ public: */ void removeMessages(const sp& handler, int what); + /** + * Return whether this looper's thread is currently idling -- that is, whether it + * stopped waiting for more work to do. Note that this is intrinsically racy, since + * its state can change before you get the result back. + */ + bool isIdling() const; + /** * Prepares a looper associated with the calling thread, and returns it. * If the thread already has a looper, it is returned. Otherwise, a new @@ -353,6 +360,10 @@ private: Vector mMessageEnvelopes; // guarded by mLock bool mSendingMessage; // guarded by mLock + // Whether we are currently waiting for work. Not protected by a lock, + // any use of it is racy anyway. + volatile bool mIdling; + int mEpollFd; // immutable // Locked list of file descriptor monitoring requests. diff --git a/libs/utils/Looper.cpp b/libs/utils/Looper.cpp index a5e66458c..c51df2d1a 100644 --- a/libs/utils/Looper.cpp +++ b/libs/utils/Looper.cpp @@ -84,6 +84,8 @@ Looper::Looper(bool allowNonCallbacks) : LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d", errno); + mIdling = false; + // Allocate the epoll instance and register the wake pipe. mEpollFd = epoll_create(EPOLL_SIZE_HINT); LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno); @@ -214,9 +216,15 @@ int Looper::pollInner(int timeoutMillis) { mResponses.clear(); mResponseIndex = 0; + // We are about to idle. + mIdling = true; + struct epoll_event eventItems[EPOLL_MAX_EVENTS]; int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis); + // No longer idling. + mIdling = false; + // Acquire lock. mLock.lock(); @@ -558,4 +566,8 @@ void Looper::removeMessages(const sp& handler, int what) { } // release lock } +bool Looper::isIdling() const { + return mIdling; +} + } // namespace android