Merge "Reconcile binder JNI with earlier changes, removing lock."
This commit is contained in:
@@ -156,9 +156,8 @@ static struct thread_dispatch_offsets_t
|
|||||||
static constexpr int32_t PROXY_WARN_INTERVAL = 5000;
|
static constexpr int32_t PROXY_WARN_INTERVAL = 5000;
|
||||||
static constexpr uint32_t GC_INTERVAL = 1000;
|
static constexpr uint32_t GC_INTERVAL = 1000;
|
||||||
|
|
||||||
// Protected by gProxyLock. We warn if this gets too large.
|
static std::atomic<uint32_t> gNumProxies(0);
|
||||||
static int32_t gNumProxies = 0;
|
static std::atomic<uint32_t> gProxiesWarned(0);
|
||||||
static int32_t gProxiesWarned = 0;
|
|
||||||
|
|
||||||
// Number of GlobalRefs held by JavaBBinders.
|
// Number of GlobalRefs held by JavaBBinders.
|
||||||
static std::atomic<uint32_t> gNumLocalRefsCreated(0);
|
static std::atomic<uint32_t> gNumLocalRefsCreated(0);
|
||||||
@@ -660,12 +659,6 @@ BinderProxyNativeData* getBPNativeData(JNIEnv* env, jobject obj) {
|
|||||||
return (BinderProxyNativeData *) env->GetLongField(obj, gBinderProxyOffsets.mNativeData);
|
return (BinderProxyNativeData *) env->GetLongField(obj, gBinderProxyOffsets.mNativeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Mutex gProxyLock;
|
|
||||||
|
|
||||||
// We may cache a single BinderProxyNativeData node to avoid repeat allocation.
|
|
||||||
// All fields are null. Protected by gProxyLock.
|
|
||||||
static BinderProxyNativeData *gNativeDataCache;
|
|
||||||
|
|
||||||
// If the argument is a JavaBBinder, return the Java object that was used to create it.
|
// If the argument is a JavaBBinder, return the Java object that was used to create it.
|
||||||
// Otherwise return a BinderProxy for the IBinder. If a previous call was passed the
|
// Otherwise return a BinderProxy for the IBinder. If a previous call was passed the
|
||||||
// same IBinder, and the original BinderProxy is still alive, return the same BinderProxy.
|
// same IBinder, and the original BinderProxy is still alive, return the same BinderProxy.
|
||||||
@@ -680,36 +673,31 @@ jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the rest of the function we will hold this lock, to serialize
|
BinderProxyNativeData* nativeData = new BinderProxyNativeData();
|
||||||
// looking/creation/destruction of Java proxies for native Binder proxies.
|
nativeData->mOrgue = new DeathRecipientList;
|
||||||
AutoMutex _l(gProxyLock);
|
nativeData->mObject = val;
|
||||||
|
|
||||||
BinderProxyNativeData* nativeData = gNativeDataCache;
|
|
||||||
if (nativeData == nullptr) {
|
|
||||||
nativeData = new BinderProxyNativeData();
|
|
||||||
}
|
|
||||||
// gNativeDataCache is now logically empty.
|
|
||||||
jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
|
jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
|
||||||
gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
|
gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
|
||||||
if (env->ExceptionCheck()) {
|
if (env->ExceptionCheck()) {
|
||||||
// In the exception case, getInstance still took ownership of nativeData.
|
// In the exception case, getInstance still took ownership of nativeData.
|
||||||
gNativeDataCache = nullptr;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
|
BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
|
||||||
if (actualNativeData == nativeData) {
|
if (actualNativeData == nativeData) {
|
||||||
// New BinderProxy; we still have exclusive access.
|
// Created a new Proxy
|
||||||
nativeData->mOrgue = new DeathRecipientList;
|
uint32_t numProxies = gNumProxies.fetch_add(1, std::memory_order_relaxed);
|
||||||
nativeData->mObject = val;
|
uint32_t numLastWarned = gProxiesWarned.load(std::memory_order_relaxed);
|
||||||
gNativeDataCache = nullptr;
|
if (numProxies >= numLastWarned + PROXY_WARN_INTERVAL) {
|
||||||
++gNumProxies;
|
// Multiple threads can get here, make sure only one of them gets to
|
||||||
if (gNumProxies >= gProxiesWarned + PROXY_WARN_INTERVAL) {
|
// update the warn counter.
|
||||||
ALOGW("Unexpectedly many live BinderProxies: %d\n", gNumProxies);
|
if (gProxiesWarned.compare_exchange_strong(numLastWarned,
|
||||||
gProxiesWarned = gNumProxies;
|
numLastWarned + PROXY_WARN_INTERVAL, std::memory_order_relaxed)) {
|
||||||
|
ALOGW("Unexpectedly many live BinderProxies: %d\n", numProxies);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// nativeData wasn't used. Reuse it the next time.
|
delete nativeData;
|
||||||
gNativeDataCache = nativeData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
@@ -989,8 +977,7 @@ jint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz)
|
|||||||
|
|
||||||
jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz)
|
jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz)
|
||||||
{
|
{
|
||||||
AutoMutex _l(gProxyLock);
|
return gNumProxies.load();
|
||||||
return gNumProxies;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz)
|
jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz)
|
||||||
@@ -1385,9 +1372,6 @@ static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj,
|
|||||||
|
|
||||||
static void BinderProxy_destroy(void* rawNativeData)
|
static void BinderProxy_destroy(void* rawNativeData)
|
||||||
{
|
{
|
||||||
// Don't race with construction/initialization
|
|
||||||
AutoMutex _l(gProxyLock);
|
|
||||||
|
|
||||||
BinderProxyNativeData * nativeData = (BinderProxyNativeData *) rawNativeData;
|
BinderProxyNativeData * nativeData = (BinderProxyNativeData *) rawNativeData;
|
||||||
LOGDEATH("Destroying BinderProxy: binder=%p drl=%p\n",
|
LOGDEATH("Destroying BinderProxy: binder=%p drl=%p\n",
|
||||||
nativeData->mObject.get(), nativeData->mOrgue.get());
|
nativeData->mObject.get(), nativeData->mOrgue.get());
|
||||||
|
|||||||
Reference in New Issue
Block a user