# HG changeset patch # User rehn # Date 1499461893 -7200 # Node ID a5813fb66270af7c6671871e6785bb6c48796d15 # Parent cb5f289ba033e07dbdf6ea9ce2b0c2d9c7672e04 8183925: Decouple crash protection from watcher thread Reviewed-by: dcubed, coleenp diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/os/posix/vm/os_posix.cpp --- 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(); } } } diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/os/posix/vm/os_posix.hpp --- 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; }; diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/os/windows/vm/os_windows.cpp --- 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; } diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/os/windows/vm/os_windows.hpp --- 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 { diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp --- 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); diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp --- 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); diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/os_cpu/linux_arm/vm/os_linux_arm.cpp --- 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); diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/os_cpu/linux_s390/vm/os_linux_s390.cpp --- 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); diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp --- 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); diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp --- 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); diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp --- 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); diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp --- 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); diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/share/vm/runtime/mutex.cpp --- 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) { diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/share/vm/runtime/os.cpp --- 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 diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/share/vm/runtime/thread.cpp --- 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; diff -r cb5f289ba033 -r a5813fb66270 hotspot/src/share/vm/runtime/thread.hpp --- 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; };