summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/jit/jit.cc19
-rw-r--r--runtime/jit/jit.h14
-rw-r--r--runtime/thread_pool.cc6
-rw-r--r--runtime/thread_pool.h7
-rw-r--r--runtime/thread_pool_test.cc18
-rw-r--r--test/913-heaps/heaps.cc9
-rw-r--r--test/913-heaps/src/Main.java4
7 files changed, 62 insertions, 15 deletions
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 23a5ddd071..803e9d5e61 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -701,5 +701,24 @@ void Jit::WaitForCompilationToFinish(Thread* self) {
}
}
+ScopedJitSuspend::ScopedJitSuspend() {
+ jit::Jit* jit = Runtime::Current()->GetJit();
+ was_on_ = (jit != nullptr) && (jit->GetThreadPool() != nullptr);
+ if (was_on_) {
+ Thread* self = Thread::Current();
+ jit->WaitForCompilationToFinish(self);
+ jit->GetThreadPool()->StopWorkers(self);
+ jit->WaitForCompilationToFinish(self);
+ }
+}
+
+ScopedJitSuspend::~ScopedJitSuspend() {
+ if (was_on_) {
+ DCHECK(Runtime::Current()->GetJit() != nullptr);
+ DCHECK(Runtime::Current()->GetJit()->GetThreadPool() != nullptr);
+ Runtime::Current()->GetJit()->GetThreadPool()->StartWorkers(Thread::Current());
+ }
+}
+
} // namespace jit
} // namespace art
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index a7824378c2..a230c78033 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -175,6 +175,10 @@ class Jit {
static bool LoadCompilerLibrary(std::string* error_msg);
+ ThreadPool* GetThreadPool() const {
+ return thread_pool_.get();
+ }
+
private:
Jit();
@@ -278,6 +282,16 @@ class JitOptions {
DISALLOW_COPY_AND_ASSIGN(JitOptions);
};
+// Helper class to stop the JIT for a given scope. This will wait for the JIT to quiesce.
+class ScopedJitSuspend {
+ public:
+ ScopedJitSuspend();
+ ~ScopedJitSuspend();
+
+ private:
+ bool was_on_;
+};
+
} // namespace jit
} // namespace art
diff --git a/runtime/thread_pool.cc b/runtime/thread_pool.cc
index b14f340c4c..65fd99985b 100644
--- a/runtime/thread_pool.cc
+++ b/runtime/thread_pool.cc
@@ -177,7 +177,7 @@ Task* ThreadPool::GetTask(Thread* self) {
}
++waiting_count_;
- if (waiting_count_ == GetThreadCount() && tasks_.empty()) {
+ if (waiting_count_ == GetThreadCount() && !HasOutstandingTasks()) {
// We may be done, lets broadcast to the completion condition.
completion_condition_.Broadcast(self);
}
@@ -200,7 +200,7 @@ Task* ThreadPool::TryGetTask(Thread* self) {
}
Task* ThreadPool::TryGetTaskLocked() {
- if (started_ && !tasks_.empty()) {
+ if (HasOutstandingTasks()) {
Task* task = tasks_.front();
tasks_.pop_front();
return task;
@@ -218,7 +218,7 @@ void ThreadPool::Wait(Thread* self, bool do_work, bool may_hold_locks) {
}
// Wait until each thread is waiting and the task list is empty.
MutexLock mu(self, task_queue_lock_);
- while (!shutting_down_ && (waiting_count_ != GetThreadCount() || !tasks_.empty())) {
+ while (!shutting_down_ && (waiting_count_ != GetThreadCount() || HasOutstandingTasks())) {
if (!may_hold_locks) {
completion_condition_.Wait(self);
} else {
diff --git a/runtime/thread_pool.h b/runtime/thread_pool.h
index b6c6f02db8..2ff33a6053 100644
--- a/runtime/thread_pool.h
+++ b/runtime/thread_pool.h
@@ -100,7 +100,8 @@ class ThreadPool {
ThreadPool(const char* name, size_t num_threads);
virtual ~ThreadPool();
- // Wait for all tasks currently on queue to get completed.
+ // Wait for all tasks currently on queue to get completed. If the pool has been stopped, only
+ // wait till all already running tasks are done.
void Wait(Thread* self, bool do_work, bool may_hold_locks) REQUIRES(!task_queue_lock_);
size_t GetTaskCount(Thread* self) REQUIRES(!task_queue_lock_);
@@ -130,6 +131,10 @@ class ThreadPool {
return shutting_down_;
}
+ bool HasOutstandingTasks() const REQUIRES(task_queue_lock_) {
+ return started_ && !tasks_.empty();
+ }
+
const std::string name_;
Mutex task_queue_lock_;
ConditionVariable task_queue_condition_ GUARDED_BY(task_queue_lock_);
diff --git a/runtime/thread_pool_test.cc b/runtime/thread_pool_test.cc
index d5f17d17b1..2ae2ecff4e 100644
--- a/runtime/thread_pool_test.cc
+++ b/runtime/thread_pool_test.cc
@@ -98,6 +98,24 @@ TEST_F(ThreadPoolTest, StopStart) {
thread_pool.Wait(self, false, false);
}
+TEST_F(ThreadPoolTest, StopWait) {
+ Thread* self = Thread::Current();
+ ThreadPool thread_pool("Thread pool test thread pool", num_threads);
+
+ AtomicInteger count(0);
+ static const int32_t num_tasks = num_threads * 100;
+ for (int32_t i = 0; i < num_tasks; ++i) {
+ thread_pool.AddTask(self, new CountTask(&count));
+ }
+
+ // Signal the threads to start processing tasks.
+ thread_pool.StartWorkers(self);
+ usleep(200);
+ thread_pool.StopWorkers(self);
+
+ thread_pool.Wait(self, false, false); // We should not deadlock here.
+}
+
class TreeTask : public Task {
public:
TreeTask(ThreadPool* const thread_pool, AtomicInteger* count, int depth)
diff --git a/test/913-heaps/heaps.cc b/test/913-heaps/heaps.cc
index 0c627d6af8..49437b150f 100644
--- a/test/913-heaps/heaps.cc
+++ b/test/913-heaps/heaps.cc
@@ -261,6 +261,8 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_followReferences(JNIEnv* env
std::vector<std::string> lines_;
};
+ jit::ScopedJitSuspend sjs; // Wait to avoid JIT influence (e.g., JNI globals).
+
// If jniRef isn't null, add a local and a global ref.
ScopedLocalRef<jobject> jni_local_ref(env, nullptr);
jobject jni_global_ref = nullptr;
@@ -299,12 +301,5 @@ jint OnLoad(JavaVM* vm,
return 0;
}
-extern "C" JNIEXPORT void JNICALL Java_Main_waitForJitCompilation(JNIEnv*, jclass) {
- jit::Jit* jit = Runtime::Current()->GetJit();
- if (jit != nullptr) {
- jit->WaitForCompilationToFinish(Thread::Current());
- }
-}
-
} // namespace Test913Heaps
} // namespace art
diff --git a/test/913-heaps/src/Main.java b/test/913-heaps/src/Main.java
index fc00ada916..a6ace9aeba 100644
--- a/test/913-heaps/src/Main.java
+++ b/test/913-heaps/src/Main.java
@@ -101,8 +101,6 @@ public class Main {
private static void doFollowReferencesTestImpl(A root, int stopAfter, int followSet,
Object asRoot, Verifier v, String additionalEnabled) {
- waitForJitCompilation(); // Wait to avoid JIT influence (e.g., JNI globals).
-
String[] lines =
followReferences(0, null, root, stopAfter, followSet, asRoot);
@@ -388,6 +386,4 @@ public class Main {
private static native String[] followReferences(int heapFilter, Class<?> klassFilter,
Object initialObject, int stopAfter, int followSet, Object jniRef);
-
- private static native void waitForJitCompilation();
}