Skip to content

Commit

Permalink
libbinder: avoid global mutex every binder call
Browse files Browse the repository at this point in the history
We can't get rid of a mutex (or similar) for the rarer
ProcessState::selfOrNull access, but for ProcessState::self() accesses,
which happen at least once every binder call, we can use the very fast
once flags.

Bug: 161336582
Test: boots
Change-Id: I66fee6be0260f59f80a85328228776de7e68c7fb
  • Loading branch information
smore-lore authored and kdrag0n committed Mar 24, 2021
1 parent f9fe1f1 commit 6691ac1
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 33 deletions.
60 changes: 36 additions & 24 deletions libs/binder/ProcessState.cpp
Expand Up @@ -32,6 +32,7 @@

#include <errno.h>
#include <fcntl.h>
#include <mutex>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
Expand Down Expand Up @@ -73,38 +74,49 @@ class PoolThread : public Thread

sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != nullptr) {
return gProcess;
}
gProcess = new ProcessState(kDefaultDriver);
return gProcess;
return init(kDefaultDriver, false /*requireDefault*/);
}

sp<ProcessState> ProcessState::initWithDriver(const char* driver)
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != nullptr) {
// Allow for initWithDriver to be called repeatedly with the same
// driver.
if (!strcmp(gProcess->getDriverName().c_str(), driver)) {
return gProcess;
}
LOG_ALWAYS_FATAL("ProcessState was already initialized.");
}

if (access(driver, R_OK) == -1) {
ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
driver = "/dev/binder";
}

gProcess = new ProcessState(driver);
return gProcess;
return init(driver, true /*requireDefault*/);
}

sp<ProcessState> ProcessState::selfOrNull()
{
Mutex::Autolock _l(gProcessMutex);
return init(nullptr, false /*requireDefault*/);
}

sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault)
{
[[clang::no_destroy]] static sp<ProcessState> gProcess;
[[clang::no_destroy]] static std::mutex gProcessMutex;

if (driver == nullptr) {
std::lock_guard<std::mutex> l(gProcessMutex);
return gProcess;
}

[[clang::no_destroy]] static std::once_flag gProcessOnce;
std::call_once(gProcessOnce, [&](){
if (access(driver, R_OK) == -1) {
ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
driver = "/dev/binder";
}

std::lock_guard<std::mutex> l(gProcessMutex);
gProcess = new ProcessState(driver);
});

if (requireDefault) {
// Detect if we are trying to initialize with a different driver, and
// consider that an error. ProcessState will only be initialized once above.
LOG_ALWAYS_FATAL_IF(gProcess->getDriverName() != driver,
"ProcessState was already initialized with %s,"
" can't initialize with %s.",
gProcess->getDriverName().c_str(), driver);
}

return gProcess;
}

Expand Down
5 changes: 0 additions & 5 deletions libs/binder/Static.cpp
Expand Up @@ -68,9 +68,4 @@ TextOutput& alog(*new LogTextOutput());
TextOutput& aout(*new FdTextOutput(STDOUT_FILENO));
TextOutput& aerr(*new FdTextOutput(STDERR_FILENO));

// ------------ ProcessState.cpp

Mutex& gProcessMutex = *new Mutex;
sp<ProcessState> gProcess;

} // namespace android
4 changes: 0 additions & 4 deletions libs/binder/Static.h
Expand Up @@ -27,8 +27,4 @@ namespace android {
// For TextStream.cpp
extern Vector<int32_t> gTextBuffers;

// For ProcessState.cpp
extern Mutex& gProcessMutex;
extern sp<ProcessState> gProcess;

} // namespace android
4 changes: 4 additions & 0 deletions libs/binder/include/binder/ProcessState.h
Expand Up @@ -42,6 +42,8 @@ class ProcessState : public virtual RefBase
* any call to ProcessState::self(). The default is /dev/vndbinder
* for processes built with the VNDK and /dev/binder for those
* which are not.
*
* If this is called with nullptr, the behavior is the same as selfOrNull.
*/
static sp<ProcessState> initWithDriver(const char *driver);

Expand Down Expand Up @@ -90,6 +92,8 @@ class ProcessState : public virtual RefBase
void setCallRestriction(CallRestriction restriction);

private:
static sp<ProcessState> init(const char *defaultDriver, bool requireDefault);

friend class IPCThreadState;

explicit ProcessState(const char* driver);
Expand Down

0 comments on commit 6691ac1

Please sign in to comment.