Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d26d3de9 authored by Martijn Coenen's avatar Martijn Coenen Committed by Steven Moreland
Browse files

Support initializing ProcessState with custom binder window size.

While the binder kernel driver allocates memory lazily, using
a 1MB binder window does mean 1MB of vmalloc address space is lost.
This can be a problem on 32-bit devices, where the address space
available for vmalloc is very limited.

This change allows initializing ProcessState with a custom mmap
size. Note that this API must be called as early as possible in
the process, before any other hwbinder (API) calls or HIDL calls
have been made.

c/p from 32507d340df9c654ae3129ce666c6a2b5d708719

Bug: 129785390
Test: verify kernel output after calling API
Change-Id: I62cdbcb4ffcad1a6d7b3eeae5560eb3e5e602515
parent a9ed1a64
Loading
Loading
Loading
Loading
+25 −8
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@
#include <sys/stat.h>
#include <sys/types.h>

#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
#define DEFAULT_BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
#define DEFAULT_MAX_BINDER_THREADS 15

#ifdef __ANDROID_VNDK__
@@ -77,7 +77,13 @@ sp<ProcessState> ProcessState::self()
    if (gProcess != nullptr) {
        return gProcess;
    }
    gProcess = new ProcessState(kDefaultDriver);
    gProcess = new ProcessState(kDefaultDriver, DEFAULT_BINDER_VM_SIZE);
    return gProcess;
}

sp<ProcessState> ProcessState::selfOrNull()
{
    Mutex::Autolock _l(gProcessMutex);
    return gProcess;
}

@@ -98,13 +104,19 @@ sp<ProcessState> ProcessState::initWithDriver(const char* driver)
        driver = "/dev/binder";
    }

    gProcess = new ProcessState(driver);
    gProcess = new ProcessState(driver, DEFAULT_BINDER_VM_SIZE);
    return gProcess;
}

sp<ProcessState> ProcessState::selfOrNull()
{
sp<ProcessState> ProcessState::initWithMmapSize(size_t mmap_size) {
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != nullptr) {
        LOG_ALWAYS_FATAL_IF(mmap_size != gProcess->getMmapSize(),
                "ProcessState already initialized with a different mmap size.");
        return gProcess;
    }

    gProcess = new ProcessState(kDefaultDriver, mmap_size);
    return gProcess;
}

@@ -234,6 +246,10 @@ ssize_t ProcessState::getKernelReferences(size_t buf_count, uintptr_t* buf)
    return count;
}

size_t ProcessState::getMmapSize() {
    return mMmapSize;
}

void ProcessState::setCallRestriction(CallRestriction restriction) {
    LOG_ALWAYS_FATAL_IF(IPCThreadState::selfOrNull(), "Call restrictions must be set before the threadpool is started.");

@@ -418,7 +434,7 @@ static int open_driver(const char *driver)
    return fd;
}

ProcessState::ProcessState(const char *driver)
ProcessState::ProcessState(const char *driver, size_t mmap_size)
    : mDriverName(String8(driver))
    , mDriverFD(open_driver(driver))
    , mVMStart(MAP_FAILED)
@@ -432,11 +448,12 @@ ProcessState::ProcessState(const char *driver)
    , mBinderContextUserData(nullptr)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
    , mMmapSize(mmap_size)
    , mCallRestriction(CallRestriction::NONE)
{
    if (mDriverFD >= 0) {
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        mVMStart = mmap(nullptr, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
@@ -453,7 +470,7 @@ ProcessState::~ProcessState()
{
    if (mDriverFD >= 0) {
        if (mVMStart != MAP_FAILED) {
            munmap(mVMStart, BINDER_VM_SIZE);
            munmap(mVMStart, mMmapSize);
        }
        close(mDriverFD);
    }
+5 −1
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ class ProcessState : public virtual RefBase
public:
    static  sp<ProcessState>    self();
    static  sp<ProcessState>    selfOrNull();
    // Note: don't call self() or selfOrNull() before initWithMmapSize()
    static  sp<ProcessState>    initWithMmapSize(size_t mmapSize); // size in bytes

    /* initWithDriver() can be used to configure libbinder to use
     * a different binder driver dev node. It must be called *before*
@@ -76,6 +78,7 @@ public:
            String8             getDriverName();

            ssize_t             getKernelReferences(size_t count, uintptr_t* buf);
            size_t              getMmapSize();

            enum class CallRestriction {
                // all calls okay
@@ -92,7 +95,7 @@ public:
private:
    friend class IPCThreadState;
    
            explicit            ProcessState(const char* driver);
            explicit            ProcessState(const char* driver, size_t mmap_size);
                                ~ProcessState();

                                ProcessState(const ProcessState& o);
@@ -135,6 +138,7 @@ private:
            String8             mRootDir;
            bool                mThreadPoolStarted;
    volatile int32_t            mThreadPoolSeq;
            size_t              mMmapSize;

            CallRestriction     mCallRestriction;
};