summaryrefslogtreecommitdiffstats
path: root/runtime/entrypoints
diff options
context:
space:
mode:
authorYevgeny Rouban <yevgeny.y.rouban@intel.com>2014-05-19 16:19:36 +0700
committerMathieu Chartier <mathieuc@google.com>2014-05-20 10:44:00 -0700
commit35aef2ce9d9cbfb37e9b2f6776afce3caed37063 (patch)
treedb1ce2f734a7ff0ad8cd4107a1aef85e7fdf8e0a /runtime/entrypoints
parent27a2b70f612af9afc0fb5392fb10059f6a0a3569 (diff)
downloadart-35aef2ce9d9cbfb37e9b2f6776afce3caed37063.zip
art-35aef2ce9d9cbfb37e9b2f6776afce3caed37063.tar.gz
art-35aef2ce9d9cbfb37e9b2f6776afce3caed37063.tar.bz2
Fix race condition between GCDaemon and DeleteLocalReference
There is a race condition between the GCDaemon visiting thread local roots starting from the thread's indirect ref table (IRT) and another thread calling JNI::DeleteLocalReference, which is clearing one of the indirect references. To cope with the race condition the DeleteLocalReference used to transit from suspended to running state by creating a ScopedObjectReference(env). But this transition was removed with the following patch: https://android.googlesource.com/platform/art/+/ef28b14268ed0f9db0c7bbd571aa514354a360bd%5E!/#F0 If so the GCDaemon must be careful to work with IRT entries. This new patch: 1. calls the visitor only if the reference is not null. This if-null behavior of ART GC is consistent with what Dalvik GC does. 2. But this might be not enough for some future sophisticated GC algorithms. For example, if GC moves an object, then the IRT entry must be changed with CAS only if it has not been cleared. So, for the safety reasons the patch put backs the ScopedObjectReference soa(env) to DeleteLocalReference. Only one of those two changes would be enough. mathieuc note: I decided to delete the root null check but kept the ScopedObjectAccess in DeleteLocalRef and added missing annotations as well as more ScopedObjectAccess in jni internals. Bug: 14626564 Change-Id: I90d4b8494f61404579ecdd2918d1482093d99387 Signed-off-by: Yevgeny Rouban <yevgeny.y.rouban@intel.com> Signed-off-by: Yang Chang <yang.chang@intel.com>
Diffstat (limited to 'runtime/entrypoints')
-rw-r--r--runtime/entrypoints/portable/portable_jni_entrypoints.cc3
-rw-r--r--runtime/entrypoints/quick/quick_jni_entrypoints.cc3
2 files changed, 4 insertions, 2 deletions
diff --git a/runtime/entrypoints/portable/portable_jni_entrypoints.cc b/runtime/entrypoints/portable/portable_jni_entrypoints.cc
index 17ad4d0..3e7b30a 100644
--- a/runtime/entrypoints/portable/portable_jni_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_jni_entrypoints.cc
@@ -37,7 +37,8 @@ extern "C" uint32_t art_portable_jni_method_start_synchronized(jobject to_lock,
return art_portable_jni_method_start(self);
}
-static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) {
+static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
JNIEnvExt* env = self->GetJniEnv();
env->locals.SetSegmentState(env->local_ref_cookie);
env->local_ref_cookie = saved_local_ref_cookie;
diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
index 9c9cca8..5d36b4c 100644
--- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
@@ -61,7 +61,8 @@ static void GoToRunnable(Thread* self) NO_THREAD_SAFETY_ANALYSIS {
}
}
-static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) {
+static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
JNIEnvExt* env = self->GetJniEnv();
env->locals.SetSegmentState(env->local_ref_cookie);
env->local_ref_cookie = saved_local_ref_cookie;