diff options
author | 2024-05-30 14:54:27 -0700 | |
---|---|---|
committer | 2024-05-31 13:10:08 -0700 | |
commit | 263507f9e3709bb4fff70ddd8e26c5dff46152ac (patch) | |
tree | 4fad64b17b25dd7a6dd7662836e6f52106c6ad01 /libs/binder/IPCThreadState.cpp | |
parent | afbfd4c28ad6a0e23dd031d2c4ed8a85e5232aa2 (diff) |
binder: remove mutex from transaction processing loop
atomic ops are enough for the various count fields, we don't need a
completely consistent view of them.
Bug: 333946800
Test: atest --test-mapping frameworks/native/libs/binder/TEST_MAPPING
Change-Id: I01f55a36f7421e4955e2b0d3a6500b183573d765
Diffstat (limited to 'libs/binder/IPCThreadState.cpp')
-rw-r--r-- | libs/binder/IPCThreadState.cpp | 76 |
1 files changed, 37 insertions, 39 deletions
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index ef96f803c3..ad20cfa11e 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -613,16 +613,20 @@ bool IPCThreadState::flushIfNeeded() void IPCThreadState::blockUntilThreadAvailable() { - pthread_mutex_lock(&mProcess->mThreadCountLock); - mProcess->mWaitingForThreads++; - while (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads) { - ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%lu mMaxThreads=%lu\n", - static_cast<unsigned long>(mProcess->mExecutingThreadsCount), - static_cast<unsigned long>(mProcess->mMaxThreads)); - pthread_cond_wait(&mProcess->mThreadCountDecrement, &mProcess->mThreadCountLock); - } - mProcess->mWaitingForThreads--; - pthread_mutex_unlock(&mProcess->mThreadCountLock); + std::unique_lock lock_guard_(mProcess->mOnThreadAvailableLock); + mProcess->mOnThreadAvailableWaiting++; + mProcess->mOnThreadAvailableCondVar.wait(lock_guard_, [&] { + size_t max = mProcess->mMaxThreads; + size_t cur = mProcess->mExecutingThreadsCount; + if (cur < max) { + return true; + } + ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%" PRId64 + " mMaxThreads=%" PRId64 "\n", + cur, max); + return false; + }); + mProcess->mOnThreadAvailableWaiting--; } status_t IPCThreadState::getAndExecuteCommand() @@ -642,34 +646,33 @@ status_t IPCThreadState::getAndExecuteCommand() ALOGI("%s", message.c_str()); } - pthread_mutex_lock(&mProcess->mThreadCountLock); - mProcess->mExecutingThreadsCount++; - if (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads && - mProcess->mStarvationStartTimeMs == 0) { - mProcess->mStarvationStartTimeMs = uptimeMillis(); + size_t newThreadsCount = mProcess->mExecutingThreadsCount.fetch_add(1) + 1; + if (newThreadsCount >= mProcess->mMaxThreads) { + int64_t expected = 0; + mProcess->mStarvationStartTimeMs.compare_exchange_strong(expected, uptimeMillis()); } - pthread_mutex_unlock(&mProcess->mThreadCountLock); result = executeCommand(cmd); - pthread_mutex_lock(&mProcess->mThreadCountLock); - mProcess->mExecutingThreadsCount--; - if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads && - mProcess->mStarvationStartTimeMs != 0) { - int64_t starvationTimeMs = uptimeMillis() - mProcess->mStarvationStartTimeMs; - if (starvationTimeMs > 100) { - ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms", - mProcess->mMaxThreads, starvationTimeMs); + size_t maxThreads = mProcess->mMaxThreads; + newThreadsCount = mProcess->mExecutingThreadsCount.fetch_sub(1) - 1; + if (newThreadsCount < maxThreads) { + size_t starvationStartTimeMs = mProcess->mStarvationStartTimeMs.exchange(0); + if (starvationStartTimeMs != 0) { + int64_t starvationTimeMs = uptimeMillis() - starvationStartTimeMs; + if (starvationTimeMs > 100) { + ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms", maxThreads, + starvationTimeMs); + } } - mProcess->mStarvationStartTimeMs = 0; } // Cond broadcast can be expensive, so don't send it every time a binder // call is processed. b/168806193 - if (mProcess->mWaitingForThreads > 0) { - pthread_cond_broadcast(&mProcess->mThreadCountDecrement); + if (mProcess->mOnThreadAvailableWaiting > 0) { + std::lock_guard lock_guard_(mProcess->mOnThreadAvailableLock); + mProcess->mOnThreadAvailableCondVar.notify_all(); } - pthread_mutex_unlock(&mProcess->mThreadCountLock); } return result; @@ -727,10 +730,9 @@ void IPCThreadState::processPostWriteDerefs() void IPCThreadState::joinThreadPool(bool isMain) { - LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid()); - pthread_mutex_lock(&mProcess->mThreadCountLock); + LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), + getpid()); mProcess->mCurrentThreads++; - pthread_mutex_unlock(&mProcess->mThreadCountLock); mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); mIsLooper = true; @@ -758,13 +760,11 @@ void IPCThreadState::joinThreadPool(bool isMain) mOut.writeInt32(BC_EXIT_LOOPER); mIsLooper = false; talkWithDriver(false); - pthread_mutex_lock(&mProcess->mThreadCountLock); - LOG_ALWAYS_FATAL_IF(mProcess->mCurrentThreads == 0, - "Threadpool thread count = 0. Thread cannot exist and exit in empty " - "threadpool\n" + size_t oldCount = mProcess->mCurrentThreads.fetch_sub(1); + LOG_ALWAYS_FATAL_IF(oldCount == 0, + "Threadpool thread count underflowed. Thread cannot exist and exit in " + "empty threadpool\n" "Misconfiguration. Increase threadpool max threads configuration\n"); - mProcess->mCurrentThreads--; - pthread_mutex_unlock(&mProcess->mThreadCountLock); } status_t IPCThreadState::setupPolling(int* fd) @@ -776,9 +776,7 @@ status_t IPCThreadState::setupPolling(int* fd) mOut.writeInt32(BC_ENTER_LOOPER); flushCommands(); *fd = mProcess->mDriverFD; - pthread_mutex_lock(&mProcess->mThreadCountLock); mProcess->mCurrentThreads++; - pthread_mutex_unlock(&mProcess->mThreadCountLock); return 0; } |