1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_VM_RUNTIME_THREADSMR_HPP
  26 #define SHARE_VM_RUNTIME_THREADSMR_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "runtime/timer.hpp"
  30 
  31 // A fast list of JavaThreads.
  32 //
  33 class ThreadsList : public CHeapObj<mtThread> {
  34   friend class ScanHazardPtrGatherProtectedThreadsClosure;
  35   friend class Threads;
  36 
  37   const uint _length;
  38   ThreadsList* _next_list;
  39   JavaThread *const *const _threads;
  40 
  41   template <class T>
  42   void threads_do_dispatch(T *cl, JavaThread *const thread) const;
  43 
  44   ThreadsList *next_list() const        { return _next_list; }
  45   void set_next_list(ThreadsList *list) { _next_list = list; }
  46 
  47 public:
  48   ThreadsList(int entries);
  49   ~ThreadsList();
  50 
  51   template <class T>
  52   void threads_do(T *cl) const;
  53 
  54   uint length() const                       { return _length; }
  55 
  56   JavaThread *const thread_at(uint i) const { return _threads[i]; }
  57 
  58   JavaThread *const *threads() const        { return _threads; }
  59 
  60   // Returns -1 if target is not found.
  61   int find_index_of_JavaThread(JavaThread* target);
  62   JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const;
  63   bool includes(const JavaThread * const p) const;
  64 
  65   static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread);
  66   static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread);
  67 };
  68 
  69 // Linked list of ThreadsLists to support nested ThreadsListHandles.
  70 class NestedThreadsList : public CHeapObj<mtThread> {
  71   ThreadsList*const _t_list;
  72   NestedThreadsList* _next;
  73 
  74 public:
  75   NestedThreadsList(ThreadsList* t_list) : _t_list(t_list) {
  76     assert(Threads_lock->owned_by_self(),
  77            "must own Threads_lock for saved t_list to be valid.");
  78   }
  79 
  80   ThreadsList* t_list() { return _t_list; }
  81   NestedThreadsList* next() { return _next; }
  82   void set_next(NestedThreadsList* value) { _next = value; }
  83 };
  84 
  85 // A helper to optionally set the hazard ptr in ourself. This helper can
  86 // be used by ourself or by another thread. If the hazard ptr is set(),
  87 // then the destructor will release it.
  88 //
  89 class ThreadsListSetter : public StackObj {
  90 private:
  91   bool _target_needs_release;  // needs release only when set()
  92   Thread * _target;
  93 
  94 public:
  95   ThreadsListSetter() : _target_needs_release(false), _target(Thread::current()) {
  96   }
  97   ~ThreadsListSetter();
  98   ThreadsList* list();
  99   void set();
 100   bool target_needs_release() { return _target_needs_release; }
 101 };
 102 
 103 // This stack allocated ThreadsListHandle keeps all JavaThreads in the
 104 // ThreadsList from being deleted until it is safe.
 105 //
 106 class ThreadsListHandle : public StackObj {
 107   ThreadsList * _list;
 108   Thread *const _self;
 109   elapsedTimer _timer;  // Enabled via -XX:+EnableThreadSMRStatistics.
 110 
 111 public:
 112   ThreadsListHandle(Thread *self = Thread::current());
 113   ~ThreadsListHandle();
 114 
 115   ThreadsList *list() const {
 116     return _list;
 117   }
 118 
 119   template <class T>
 120   void threads_do(T *cl) const {
 121     return _list->threads_do(cl);
 122   }
 123 
 124   bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p);
 125 
 126   bool includes(JavaThread* p) {
 127     return _list->includes(p);
 128   }
 129 
 130   uint length() const {
 131     return _list->length();
 132   }
 133 };
 134 
 135 // This stack allocated JavaThreadIterator is used to walk the
 136 // specified ThreadsList using the following style:
 137 //
 138 //   JavaThreadIterator jti(t_list);
 139 //   for (JavaThread *jt = jti.first(); jt != NULL; jt = jti.next()) {
 140 //     ...
 141 //   }
 142 //
 143 class JavaThreadIterator : public StackObj {
 144   ThreadsList * _list;
 145   uint _index;
 146 
 147 public:
 148   JavaThreadIterator(ThreadsList *list) : _list(list), _index(0) {
 149     assert(list != NULL, "ThreadsList must not be NULL.");
 150   }
 151 
 152   JavaThread *first() {
 153     _index = 0;
 154     return _list->thread_at(_index);
 155   }
 156 
 157   uint length() const {
 158     return _list->length();
 159   }
 160 
 161   ThreadsList *list() const {
 162     return _list;
 163   }
 164 
 165   JavaThread *next() {
 166     if (++_index >= length()) {
 167       return NULL;
 168     }
 169     return _list->thread_at(_index);
 170   }
 171 };
 172 
 173 // This stack allocated ThreadsListHandle and JavaThreadIterator combo
 174 // is used to walk the ThreadsList in the included ThreadsListHandle
 175 // using the following style:
 176 //
 177 //   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
 178 //     ...
 179 //   }
 180 //
 181 class JavaThreadIteratorWithHandle : public StackObj {
 182   ThreadsListHandle _tlh;
 183   uint _index;
 184 
 185 public:
 186   JavaThreadIteratorWithHandle() : _tlh(), _index(0) {}
 187 
 188   uint length() const {
 189     return _tlh.length();
 190   }
 191 
 192   ThreadsList *list() const {
 193     return _tlh.list();
 194   }
 195 
 196   JavaThread *next() {
 197     if (_index >= length()) {
 198       return NULL;
 199     }
 200     return _tlh.list()->thread_at(_index++);
 201   }
 202 
 203   void rewind() {
 204     _index = 0;
 205   }
 206 };
 207 
 208 #endif // SHARE_VM_RUNTIME_THREADSMR_HPP