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

Commit 1f1bed66 authored by Steven Moreland's avatar Steven Moreland
Browse files

libbinder_ndk: eradicate global lock

Let the nightmares cease!
Without contention, peace.

Note, in the case that an ABpBinder is backed by a BBinder (this happens
when you talk in-process to something between the NDK backend and either
the C++, Rust, or Java backends of AIDL), this introduces an additional
allocation b/c the BBinder's mExtra needs to be allocated for
BBinder::withLock to work. Since this is generally frowned upon, and the
thrashing in this case is already pretty egregious, I don't mind it.
Now, binder proxies can be allocated simultaneously in a process.

Bug: 192023359
Test: CtsNdkBinderTestCases
Change-Id: Ib1c28c9488f7a03579ea9d18347a8fc08cc3f48a
parent 9e759e81
Loading
Loading
Loading
Loading
+18 −14
Original line number Diff line number Diff line
@@ -57,7 +57,6 @@ static bool has(const sp<IBinder>& binder) {

namespace ABpBinderTag {

static std::mutex gLock;
static const void* kId = "ABpBinder";
struct Value {
    wp<ABpBinder> binder;
@@ -252,23 +251,28 @@ sp<AIBinder> ABpBinder::lookupOrCreateFromBinder(const ::android::sp<::android::
        return static_cast<ABBinder*>(binder.get());
    }

    // The following code ensures that for a given binder object (remote or local), if it is not an
    // ABBinder then at most one ABpBinder object exists in a given process representing it.
    std::lock_guard<std::mutex> lock(ABpBinderTag::gLock);

    ABpBinderTag::Value* value =
            static_cast<ABpBinderTag::Value*>(binder->findObject(ABpBinderTag::kId));
    auto* value = static_cast<ABpBinderTag::Value*>(binder->findObject(ABpBinderTag::kId));
    if (value == nullptr) {
        value = new ABpBinderTag::Value;
        binder->attachObject(ABpBinderTag::kId, static_cast<void*>(value), nullptr /*cookie*/,
                             ABpBinderTag::clean);
        auto oldValue = static_cast<ABpBinderTag::Value*>(
                binder->attachObject(ABpBinderTag::kId, static_cast<void*>(value),
                                     nullptr /*cookie*/, ABpBinderTag::clean));

        // allocated by another thread
        if (oldValue) {
            delete value;
            value = oldValue;
        }
    }

    sp<ABpBinder> ret = value->binder.promote();
    sp<ABpBinder> ret;
    binder->withLock([&]() {
        ret = value->binder.promote();
        if (ret == nullptr) {
        ret = new ABpBinder(binder);
            ret = sp<ABpBinder>::make(binder);
            value->binder = ret;
        }
    });

    return ret;
}
+1 −0
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ struct ABpBinder : public AIBinder, public ::android::BpRefBase {
    ABpBinder* asABpBinder() override { return this; }

   private:
    friend android::sp<ABpBinder>;
    explicit ABpBinder(const ::android::sp<::android::IBinder>& binder);
};