--- /dev/null Mon Nov 13 09:08:01 2017 +++ new/src/hotspot/share/runtime/threadSMR.hpp Mon Nov 13 09:08:00 2017 @@ -0,0 +1,208 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_RUNTIME_THREADSMR_HPP +#define SHARE_VM_RUNTIME_THREADSMR_HPP + +#include "memory/allocation.hpp" +#include "runtime/timer.hpp" + +// A fast list of JavaThreads. +// +class ThreadsList : public CHeapObj { + friend class ScanHazardPtrGatherProtectedThreadsClosure; + friend class Threads; + + const uint _length; + ThreadsList* _next_list; + JavaThread *const *const _threads; + + template + void threads_do_dispatch(T *cl, JavaThread *const thread) const; + + ThreadsList *next_list() const { return _next_list; } + void set_next_list(ThreadsList *list) { _next_list = list; } + +public: + ThreadsList(int entries); + ~ThreadsList(); + + template + void threads_do(T *cl) const; + + uint length() const { return _length; } + + JavaThread *const thread_at(uint i) const { return _threads[i]; } + + JavaThread *const *threads() const { return _threads; } + + // Returns -1 if target is not found. + int find_index_of_JavaThread(JavaThread* target); + JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const; + bool includes(const JavaThread * const p) const; + + static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread); + static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread); +}; + +// Linked list of ThreadsLists to support nested ThreadsListHandles. +class NestedThreadsList : public CHeapObj { + ThreadsList*const _t_list; + NestedThreadsList* _next; + +public: + NestedThreadsList(ThreadsList* t_list) : _t_list(t_list) { + assert(Threads_lock->owned_by_self(), + "must own Threads_lock for saved t_list to be valid."); + } + + ThreadsList* t_list() { return _t_list; } + NestedThreadsList* next() { return _next; } + void set_next(NestedThreadsList* value) { _next = value; } +}; + +// A helper to optionally set the hazard ptr in ourself. This helper can +// be used by ourself or by another thread. If the hazard ptr is set(), +// then the destructor will release it. +// +class ThreadsListSetter : public StackObj { +private: + bool _target_needs_release; // needs release only when set() + Thread * _target; + +public: + ThreadsListSetter() : _target_needs_release(false), _target(Thread::current()) { + } + ~ThreadsListSetter(); + ThreadsList* list(); + void set(); + bool target_needs_release() { return _target_needs_release; } +}; + +// This stack allocated ThreadsListHandle keeps all JavaThreads in the +// ThreadsList from being deleted until it is safe. +// +class ThreadsListHandle : public StackObj { + ThreadsList * _list; + Thread *const _self; + elapsedTimer _timer; // Enabled via -XX:+EnableThreadSMRStatistics. + +public: + ThreadsListHandle(Thread *self = Thread::current()); + ~ThreadsListHandle(); + + ThreadsList *list() const { + return _list; + } + + template + void threads_do(T *cl) const { + return _list->threads_do(cl); + } + + bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p); + + bool includes(JavaThread* p) { + return _list->includes(p); + } + + uint length() const { + return _list->length(); + } +}; + +// This stack allocated JavaThreadIterator is used to walk the +// specified ThreadsList using the following style: +// +// JavaThreadIterator jti(t_list); +// for (JavaThread *jt = jti.first(); jt != NULL; jt = jti.next()) { +// ... +// } +// +class JavaThreadIterator : public StackObj { + ThreadsList * _list; + uint _index; + +public: + JavaThreadIterator(ThreadsList *list) : _list(list), _index(0) { + assert(list != NULL, "ThreadsList must not be NULL."); + } + + JavaThread *first() { + _index = 0; + return _list->thread_at(_index); + } + + uint length() const { + return _list->length(); + } + + ThreadsList *list() const { + return _list; + } + + JavaThread *next() { + if (++_index >= length()) { + return NULL; + } + return _list->thread_at(_index); + } +}; + +// This stack allocated ThreadsListHandle and JavaThreadIterator combo +// is used to walk the ThreadsList in the included ThreadsListHandle +// using the following style: +// +// for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { +// ... +// } +// +class JavaThreadIteratorWithHandle : public StackObj { + ThreadsListHandle _tlh; + uint _index; + +public: + JavaThreadIteratorWithHandle() : _tlh(), _index(0) {} + + uint length() const { + return _tlh.length(); + } + + ThreadsList *list() const { + return _tlh.list(); + } + + JavaThread *next() { + if (_index >= length()) { + return NULL; + } + return _tlh.list()->thread_at(_index++); + } + + void rewind() { + _index = 0; + } +}; + +#endif // SHARE_VM_RUNTIME_THREADSMR_HPP