summaryrefslogtreecommitdiff
path: root/libs/binder/IPCThreadState.cpp
diff options
context:
space:
mode:
author Frederick Mayle <fmayle@google.com> 2024-05-30 14:54:27 -0700
committer Frederick Mayle <fmayle@google.com> 2024-05-31 13:10:08 -0700
commit263507f9e3709bb4fff70ddd8e26c5dff46152ac (patch)
tree4fad64b17b25dd7a6dd7662836e6f52106c6ad01 /libs/binder/IPCThreadState.cpp
parentafbfd4c28ad6a0e23dd031d2c4ed8a85e5232aa2 (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.cpp76
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;
}