Fix "holding ThreadListLock while doing condition variable wait on HeapLock"
Now we release the ThreadListLock if we are going to wait on the heap condition variable in WaitForConcurrentGC.
Change-Id: I506c8ff93f4b79ee74c98b7936a7d155be833b90
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 72ab76e..6640430 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -211,6 +211,7 @@
src/runtime.cc \
src/runtime_support.cc \
src/scoped_thread_list_lock.cc \
+ src/scoped_thread_list_lock_releaser.cc \
src/signal_catcher.cc \
src/space.cc \
src/stack.cc \
diff --git a/src/heap.cc b/src/heap.cc
index 0c4c6ff..55a8afe 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -30,6 +30,7 @@
#include "object_utils.h"
#include "os.h"
#include "scoped_heap_lock.h"
+#include "scoped_thread_list_lock_releaser.h"
#include "ScopedLocalRef.h"
#include "space.h"
#include "stl_util.h"
@@ -737,8 +738,10 @@
// Busy wait for GC to finish
if (is_gc_running_) {
uint64_t wait_start = NanoTime();
+
do {
ScopedThreadStateChange tsc(Thread::Current(), kVmWait);
+ ScopedThreadListLockReleaser list_lock_releaser;
condition_->Wait(*lock_);
} while (is_gc_running_);
uint64_t wait_time = NanoTime() - wait_start;
diff --git a/src/scoped_thread_list_lock_releaser.cc b/src/scoped_thread_list_lock_releaser.cc
new file mode 100644
index 0000000..3ac22a5
--- /dev/null
+++ b/src/scoped_thread_list_lock_releaser.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "scoped_thread_list_lock_releaser.h"
+
+#include "runtime.h"
+#include "thread_list.h"
+
+namespace art {
+
+ScopedThreadListLockReleaser::ScopedThreadListLockReleaser() {
+ if (Thread::Current()->held_mutexes_[kThreadListLock] > 0) {
+ Runtime::Current()->GetThreadList()->thread_list_lock_.Unlock();
+ unlocked_ = true;
+ } else {
+ unlocked_ = false;
+ }
+}
+
+ScopedThreadListLockReleaser::~ScopedThreadListLockReleaser() {
+ if (unlocked_) {
+ Runtime::Current()->GetThreadList()->thread_list_lock_.Lock();
+ }
+}
+
+} // namespace art
diff --git a/src/scoped_thread_list_lock_releaser.h b/src/scoped_thread_list_lock_releaser.h
new file mode 100644
index 0000000..af656d5
--- /dev/null
+++ b/src/scoped_thread_list_lock_releaser.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_SCOPED_THREAD_LIST_LOCK_RELEASER_H_
+#define ART_SRC_SCOPED_THREAD_LIST_LOCK_RELEASER_H_
+
+#include "macros.h"
+
+namespace art {
+
+class ScopedThreadListLockReleaser {
+ public:
+ ScopedThreadListLockReleaser();
+ ~ScopedThreadListLockReleaser();
+
+ private:
+ // Whether or not we unlocked the thread list lock.
+ bool unlocked_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedThreadListLockReleaser);
+};
+
+} // namespace art
+
+#endif // ART_SRC_SCOPED_THREAD_LIST_LOCK_RELEASER_H_
diff --git a/src/thread.h b/src/thread.h
index c674ded..ad07498 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -651,6 +651,7 @@
EntryPoints entrypoints_;
private:
+ friend class ScopedThreadListLockReleaser;
DISALLOW_COPY_AND_ASSIGN(Thread);
};
diff --git a/src/thread_list.h b/src/thread_list.h
index 36cd094..ef475fe 100644
--- a/src/thread_list.h
+++ b/src/thread_list.h
@@ -92,6 +92,7 @@
friend class Thread;
friend class ScopedThreadListLock;
+ friend class ScopedThreadListLockReleaser;
DISALLOW_COPY_AND_ASSIGN(ThreadList);
};