8183925: Decouple crash protection from watcher thread
Reviewed-by: dcubed, coleenp
--- a/hotspot/src/os/posix/vm/os_posix.cpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/os/posix/vm/os_posix.cpp Fri Jul 07 23:11:33 2017 +0200
@@ -1285,8 +1285,11 @@
return stack_size;
}
-os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() {
- assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread");
+Thread* os::ThreadCrashProtection::_protected_thread = NULL;
+os::ThreadCrashProtection* os::ThreadCrashProtection::_crash_protection = NULL;
+volatile intptr_t os::ThreadCrashProtection::_crash_mux = 0;
+
+os::ThreadCrashProtection::ThreadCrashProtection() {
}
/*
@@ -1295,12 +1298,13 @@
* method and returns false. If none of the signals are raised, returns true.
* The callback is supposed to provide the method that should be protected.
*/
-bool os::WatcherThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
+bool os::ThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
sigset_t saved_sig_mask;
- assert(Thread::current()->is_Watcher_thread(), "Only for WatcherThread");
- assert(!WatcherThread::watcher_thread()->has_crash_protection(),
- "crash_protection already set?");
+ Thread::muxAcquire(&_crash_mux, "CrashProtection");
+
+ _protected_thread = Thread::current_or_null();
+ assert(_protected_thread != NULL, "Cannot crash protect a NULL thread");
// we cannot rely on sigsetjmp/siglongjmp to save/restore the signal mask
// since on at least some systems (OS X) siglongjmp will restore the mask
@@ -1309,34 +1313,36 @@
if (sigsetjmp(_jmpbuf, 0) == 0) {
// make sure we can see in the signal handler that we have crash protection
// installed
- WatcherThread::watcher_thread()->set_crash_protection(this);
+ _crash_protection = this;
cb.call();
// and clear the crash protection
- WatcherThread::watcher_thread()->set_crash_protection(NULL);
+ _crash_protection = NULL;
+ _protected_thread = NULL;
+ Thread::muxRelease(&_crash_mux);
return true;
}
// this happens when we siglongjmp() back
pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL);
- WatcherThread::watcher_thread()->set_crash_protection(NULL);
+ _crash_protection = NULL;
+ _protected_thread = NULL;
+ Thread::muxRelease(&_crash_mux);
return false;
}
-void os::WatcherThreadCrashProtection::restore() {
- assert(WatcherThread::watcher_thread()->has_crash_protection(),
- "must have crash protection");
-
+void os::ThreadCrashProtection::restore() {
+ assert(_crash_protection != NULL, "must have crash protection");
siglongjmp(_jmpbuf, 1);
}
-void os::WatcherThreadCrashProtection::check_crash_protection(int sig,
+void os::ThreadCrashProtection::check_crash_protection(int sig,
Thread* thread) {
if (thread != NULL &&
- thread->is_Watcher_thread() &&
- WatcherThread::watcher_thread()->has_crash_protection()) {
+ thread == _protected_thread &&
+ _crash_protection != NULL) {
if (sig == SIGSEGV || sig == SIGBUS) {
- WatcherThread::watcher_thread()->crash_protection()->restore();
+ _crash_protection->restore();
}
}
}
--- a/hotspot/src/os/posix/vm/os_posix.hpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/os/posix/vm/os_posix.hpp Fri Jul 07 23:11:33 2017 +0200
@@ -121,13 +121,20 @@
* don't call code that could leave the heap / memory in an inconsistent state,
* or anything else where we are not in control if we suddenly jump out.
*/
-class WatcherThreadCrashProtection : public StackObj {
+class ThreadCrashProtection : public StackObj {
public:
- WatcherThreadCrashProtection();
+ static bool is_crash_protected(Thread* thr) {
+ return _crash_protection != NULL && _protected_thread == thr;
+ }
+
+ ThreadCrashProtection();
bool call(os::CrashProtectionCallback& cb);
static void check_crash_protection(int signal, Thread* thread);
private:
+ static Thread* _protected_thread;
+ static ThreadCrashProtection* _crash_protection;
+ static volatile intptr_t _crash_mux;
void restore();
sigjmp_buf _jmpbuf;
};
--- a/hotspot/src/os/windows/vm/os_windows.cpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Fri Jul 07 23:11:33 2017 +0200
@@ -4822,8 +4822,11 @@
}
}
-os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() {
- assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread");
+Thread* os::ThreadCrashProtection::_protected_thread = NULL;
+os::ThreadCrashProtection* os::ThreadCrashProtection::_crash_protection = NULL;
+volatile intptr_t os::ThreadCrashProtection::_crash_mux = 0;
+
+os::ThreadCrashProtection::ThreadCrashProtection() {
}
// See the caveats for this class in os_windows.hpp
@@ -4832,20 +4835,24 @@
// true.
// The callback is supposed to provide the method that should be protected.
//
-bool os::WatcherThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
- assert(Thread::current()->is_Watcher_thread(), "Only for WatcherThread");
- assert(!WatcherThread::watcher_thread()->has_crash_protection(),
- "crash_protection already set?");
+bool os::ThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
+
+ Thread::muxAcquire(&_crash_mux, "CrashProtection");
+
+ _protected_thread = Thread::current_or_null();
+ assert(_protected_thread != NULL, "Cannot crash protect a NULL thread");
bool success = true;
__try {
- WatcherThread::watcher_thread()->set_crash_protection(this);
+ _crash_protection = this;
cb.call();
} __except(EXCEPTION_EXECUTE_HANDLER) {
// only for protection, nothing to do
success = false;
}
- WatcherThread::watcher_thread()->set_crash_protection(NULL);
+ _crash_protection = NULL;
+ _protected_thread = NULL;
+ Thread::muxRelease(&_crash_mux);
return success;
}
--- a/hotspot/src/os/windows/vm/os_windows.hpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/os/windows/vm/os_windows.hpp Fri Jul 07 23:11:33 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -146,10 +146,18 @@
* don't call code that could leave the heap / memory in an inconsistent state,
* or anything else where we are not in control if we suddenly jump out.
*/
-class WatcherThreadCrashProtection : public StackObj {
+class ThreadCrashProtection : public StackObj {
public:
- WatcherThreadCrashProtection();
+ static bool is_crash_protected(Thread* thr) {
+ return _crash_protection != NULL && _protected_thread == thr;
+ }
+
+ ThreadCrashProtection();
bool call(os::CrashProtectionCallback& cb);
+private:
+ static Thread* _protected_thread;
+ static ThreadCrashProtection* _crash_protection;
+ static volatile intptr_t _crash_mux;
};
class PlatformEvent : public CHeapObj<mtInternal> {
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Fri Jul 07 23:11:33 2017 +0200
@@ -463,7 +463,7 @@
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run)
- os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
+ os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t);
--- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Fri Jul 07 23:11:33 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -277,7 +277,7 @@
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run)
- os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
+ os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t);
--- a/hotspot/src/os_cpu/linux_arm/vm/os_linux_arm.cpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/os_cpu/linux_arm/vm/os_linux_arm.cpp Fri Jul 07 23:11:33 2017 +0200
@@ -280,7 +280,7 @@
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run)
- os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
+ os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t);
--- a/hotspot/src/os_cpu/linux_s390/vm/os_linux_s390.cpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/os_cpu/linux_s390/vm/os_linux_s390.cpp Fri Jul 07 23:11:33 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -245,7 +245,7 @@
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run).
- os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
+ os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t);
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Fri Jul 07 23:11:33 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -493,7 +493,7 @@
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run)
- os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
+ os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t);
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Fri Jul 07 23:11:33 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -283,7 +283,7 @@
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run)
- os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
+ os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t);
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Fri Jul 07 23:11:33 2017 +0200
@@ -328,7 +328,7 @@
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run)
- os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
+ os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t);
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Fri Jul 07 23:11:33 2017 +0200
@@ -411,7 +411,7 @@
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run)
- os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
+ os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t);
--- a/hotspot/src/share/vm/runtime/mutex.cpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/share/vm/runtime/mutex.cpp Fri Jul 07 23:11:33 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1389,10 +1389,8 @@
debug_only(if (rank() != Mutex::special) \
thread->check_for_valid_safepoint_state(false);)
}
- if (thread->is_Watcher_thread()) {
- assert(!WatcherThread::watcher_thread()->has_crash_protection(),
- "locking not allowed when crash protection is set");
- }
+ assert(!os::ThreadCrashProtection::is_crash_protected(thread),
+ "locking not allowed when crash protection is set");
}
void Monitor::check_block_state(Thread *thread) {
--- a/hotspot/src/share/vm/runtime/os.cpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/share/vm/runtime/os.cpp Fri Jul 07 23:11:33 2017 +0200
@@ -574,21 +574,10 @@
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
-#ifdef ASSERT
- // checking for the WatcherThread and crash_protection first
- // since os::malloc can be called when the libjvm.{dll,so} is
- // first loaded and we don't have a thread yet.
- // try to find the thread after we see that the watcher thread
- // exists and has crash protection.
- WatcherThread *wt = WatcherThread::watcher_thread();
- if (wt != NULL && wt->has_crash_protection()) {
- Thread* thread = Thread::current_or_null();
- if (thread == wt) {
- assert(!wt->has_crash_protection(),
- "Can't malloc with crash protection from WatcherThread");
- }
- }
-#endif
+ // Since os::malloc can be called when the libjvm.{dll,so} is
+ // first loaded and we don't have a thread yet we must accept NULL also here.
+ assert(!os::ThreadCrashProtection::is_crash_protected(Thread::current_or_null()),
+ "malloc() not allowed when crash protection is set");
if (size == 0) {
// return a valid pointer if size is zero
--- a/hotspot/src/share/vm/runtime/thread.cpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/share/vm/runtime/thread.cpp Fri Jul 07 23:11:33 2017 +0200
@@ -1200,7 +1200,7 @@
bool WatcherThread::_startable = false;
volatile bool WatcherThread::_should_terminate = false;
-WatcherThread::WatcherThread() : Thread(), _crash_protection(NULL) {
+WatcherThread::WatcherThread() : Thread() {
assert(watcher_thread() == NULL, "we can only allocate one WatcherThread");
if (os::create_thread(this, os::watcher_thread)) {
_watcher_thread = this;
--- a/hotspot/src/share/vm/runtime/thread.hpp Fri Jul 07 23:04:06 2017 +0200
+++ b/hotspot/src/share/vm/runtime/thread.hpp Fri Jul 07 23:11:33 2017 +0200
@@ -740,8 +740,6 @@
static bool _startable;
// volatile due to at least one lock-free read
volatile static bool _should_terminate;
-
- os::WatcherThreadCrashProtection* _crash_protection;
public:
enum SomeConstants {
delay_interval = 10 // interrupt delay in milliseconds
@@ -772,15 +770,6 @@
// Only allow start once the VM is sufficiently initialized
// Otherwise the first task to enroll will trigger the start
static void make_startable();
-
- void set_crash_protection(os::WatcherThreadCrashProtection* crash_protection) {
- assert(Thread::current()->is_Watcher_thread(), "Can only be set by WatcherThread");
- _crash_protection = crash_protection;
- }
-
- bool has_crash_protection() const { return _crash_protection != NULL; }
- os::WatcherThreadCrashProtection* crash_protection() const { return _crash_protection; }
-
private:
int sleep() const;
};