Path: blob/master/src/hotspot/share/runtime/handshake.hpp
64440 views
/*1* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_RUNTIME_HANDSHAKE_HPP25#define SHARE_RUNTIME_HANDSHAKE_HPP2627#include "memory/allocation.hpp"28#include "memory/iterator.hpp"29#include "runtime/flags/flagSetting.hpp"30#include "runtime/mutex.hpp"31#include "runtime/orderAccess.hpp"32#include "utilities/filterQueue.hpp"3334class HandshakeOperation;35class JavaThread;36class SuspendThreadHandshake;37class ThreadSelfSuspensionHandshake;3839// A handshake closure is a callback that is executed for a JavaThread40// while it is in a safepoint/handshake-safe state. Depending on the41// nature of the closure, the callback may be executed by the initiating42// thread, the target thread, or the VMThread. If the callback is not executed43// by the target thread it will remain in a blocked state until the callback completes.44class HandshakeClosure : public ThreadClosure, public CHeapObj<mtThread> {45const char* const _name;46public:47HandshakeClosure(const char* name) : _name(name) {}48virtual ~HandshakeClosure() {}49const char* name() const { return _name; }50virtual bool is_async() { return false; }51virtual bool is_suspend() { return false; }52virtual void do_thread(Thread* thread) = 0;53};5455class AsyncHandshakeClosure : public HandshakeClosure {56public:57AsyncHandshakeClosure(const char* name) : HandshakeClosure(name) {}58virtual ~AsyncHandshakeClosure() {}59virtual bool is_async() { return true; }60};6162class Handshake : public AllStatic {63public:64// Execution of handshake operation65static void execute(HandshakeClosure* hs_cl);66static void execute(HandshakeClosure* hs_cl, JavaThread* target);67static void execute(AsyncHandshakeClosure* hs_cl, JavaThread* target);68};6970class JvmtiRawMonitor;7172// The HandshakeState keeps track of an ongoing handshake for this JavaThread.73// VMThread/Handshaker and JavaThread are serialized with _lock making sure the74// operation is only done by either VMThread/Handshaker on behalf of the75// JavaThread or by the target JavaThread itself.76class HandshakeState {77friend ThreadSelfSuspensionHandshake;78friend SuspendThreadHandshake;79friend JavaThread;80// This a back reference to the JavaThread,81// the target for all operation in the queue.82JavaThread* _handshakee;83// The queue containing handshake operations to be performed on _handshakee.84FilterQueue<HandshakeOperation*> _queue;85// Provides mutual exclusion to this state and queue. Also used for86// JavaThread suspend/resume operations.87Monitor _lock;88// Set to the thread executing the handshake operation.89Thread* volatile _active_handshaker;9091bool claim_handshake();92bool possibly_can_process_handshake();93bool can_process_handshake();9495bool have_non_self_executable_operation();96HandshakeOperation* get_op_for_self(bool allow_suspend);97HandshakeOperation* get_op();98void remove_op(HandshakeOperation* op);99100void set_active_handshaker(Thread* thread) { Atomic::store(&_active_handshaker, thread); }101102class MatchOp {103HandshakeOperation* _op;104public:105MatchOp(HandshakeOperation* op) : _op(op) {}106bool operator()(HandshakeOperation* op) {107return op == _op;108}109};110111public:112HandshakeState(JavaThread* thread);113114void add_operation(HandshakeOperation* op);115116bool has_operation() {117return !_queue.is_empty();118}119bool has_a_non_suspend_operation();120121bool operation_pending(HandshakeOperation* op);122123// If the method returns true we need to check for a possible safepoint.124// This is due to a suspension handshake which put the JavaThread in blocked125// state so a safepoint may be in-progress.126bool process_by_self(bool allow_suspend);127128enum ProcessResult {129_no_operation = 0,130_not_safe,131_claim_failed,132_processed,133_succeeded,134_number_states135};136ProcessResult try_process(HandshakeOperation* match_op);137138Thread* active_handshaker() const { return Atomic::load(&_active_handshaker); }139140// Suspend/resume support141private:142// This flag is true when the thread owning this143// HandshakeState (the _handshakee) is suspended.144volatile bool _suspended;145// This flag is true while there is async handshake (trap)146// on queue. Since we do only need one, we can reuse it if147// thread gets suspended again (after a resume)148// and we have not yet processed it.149bool _async_suspend_handshake;150151// Called from the suspend handshake.152bool suspend_with_handshake();153// Called from the async handshake (the trap)154// to stop a thread from continuing execution when suspended.155void do_self_suspend();156157bool is_suspended() { return Atomic::load(&_suspended); }158void set_suspended(bool to) { return Atomic::store(&_suspended, to); }159bool has_async_suspend_handshake() { return _async_suspend_handshake; }160void set_async_suspend_handshake(bool to) { _async_suspend_handshake = to; }161162bool suspend();163bool resume();164};165166#endif // SHARE_RUNTIME_HANDSHAKE_HPP167168169