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 // Thread Safe Memory Reclamation (Thread-SMR) support.
  32 //
  33 // ThreadsListHandles are used to safely perform operations on one or more
  34 // threads without the risk of the thread or threads exiting during the
  35 // operation. It is no longer necessary to hold the Threads_lock to safely
  36 // perform an operation on a target thread.
  37 //
  38 // There are several different ways to refer to java.lang.Thread objects
  39 // so we have a few ways to get a protected JavaThread *:
  40 //
  41 // JNI jobject example:
  42 //   jobject jthread = ...;
  43 //   :
  44 //   ThreadsListHandle tlh;
  45 //   JavaThread* jt = NULL;
  46 //   bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &jt, NULL);
  47 //   if (is_alive) {
  48 //     :  // do stuff with 'jt'...
  49 //   }
  50 //
  51 // JVM/TI jthread example:
  52 //   jthread thread = ...;
  53 //   :
  54 //   JavaThread* jt = NULL;
  55 //   ThreadsListHandle tlh;
  56 //   jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &jt, NULL);
  57 //   if (err != JVMTI_ERROR_NONE) {
  58 //     return err;
  59 //   }
  60 //   :  // do stuff with 'jt'...
  61 //
  62 // JVM/TI oop example (this one should be very rare):
  63 //   oop thread_obj = ...;
  64 //   :
  65 //   JavaThread *jt = NULL;
  66 //   ThreadsListHandle tlh;
  67 //   jvmtiError err = JvmtiExport::cv_oop_to_JavaThread(tlh.list(), thread_obj, &jt);
  68 //   if (err != JVMTI_ERROR_NONE) {
  69 //     return err;
  70 //   }
  71 //   :  // do stuff with 'jt'...
  72 //
  73 // A JavaThread * that is included in the ThreadsList that is held by
  74 // a ThreadsListHandle is protected as long as the ThreadsListHandle
  75 // remains in scope. The target JavaThread * may have logically exited,
  76 // but that target JavaThread * will not be deleted until it is no
  77 // longer protected by a ThreadsListHandle.
  78 
  79 
  80 // SMR Support for the Threads class.
  81 //
  82 class ThreadsSMRSupport : AllStatic {
  83   // The coordination between ThreadsSMRSupport::release_stable_list() and
  84   // ThreadsSMRSupport::smr_delete() uses the smr_delete_lock in order to
  85   // reduce the traffic on the Threads_lock.
  86   static Monitor*              _smr_delete_lock;
  87   // The '_cnt', '_max' and '_times" fields are enabled via
  88   // -XX:+EnableThreadSMRStatistics (see thread.cpp for a
  89   // description about each field):
  90   static uint                  _smr_delete_lock_wait_cnt;
  91   static uint                  _smr_delete_lock_wait_max;
  92   // The smr_delete_notify flag is used for proper double-check
  93   // locking in order to reduce the traffic on the smr_delete_lock.
  94   static volatile uint         _smr_delete_notify;
  95   static volatile uint         _smr_deleted_thread_cnt;
  96   static volatile uint         _smr_deleted_thread_time_max;
  97   static volatile uint         _smr_deleted_thread_times;
  98   static ThreadsList* volatile _smr_java_thread_list;
  99   static uint64_t              _smr_java_thread_list_alloc_cnt;
 100   static uint64_t              _smr_java_thread_list_free_cnt;
 101   static uint                  _smr_java_thread_list_max;
 102   static uint                  _smr_nested_thread_list_max;
 103   static volatile uint         _smr_tlh_cnt;
 104   static volatile uint         _smr_tlh_time_max;
 105   static volatile uint         _smr_tlh_times;
 106   static ThreadsList*          _smr_to_delete_list;
 107   static uint                  _smr_to_delete_list_cnt;
 108   static uint                  _smr_to_delete_list_max;
 109 
 110   static ThreadsList *acquire_stable_list_fast_path(Thread *self);
 111   static ThreadsList *acquire_stable_list_nested_path(Thread *self);
 112   static void add_smr_deleted_thread_times(uint add_value);
 113   static void clear_smr_delete_notify();
 114   static void inc_smr_deleted_thread_cnt();
 115   static bool is_a_protected_JavaThread(JavaThread *thread);
 116   static void release_stable_list_fast_path(Thread *self);
 117   static void release_stable_list_nested_path(Thread *self);
 118   static void release_stable_list_wake_up(char *log_str);
 119   static void set_smr_delete_notify();
 120   static Monitor* smr_delete_lock() { return _smr_delete_lock; }
 121   static bool smr_delete_notify();
 122   static void update_smr_deleted_thread_time_max(uint new_value);
 123 
 124  public:
 125   static ThreadsList *acquire_stable_list(Thread *self, bool is_ThreadsListSetter);
 126   static void add_smr_tlh_times(uint add_value);
 127   static ThreadsList* get_smr_java_thread_list();
 128   static void inc_smr_java_thread_list_alloc_cnt();
 129   static void inc_smr_tlh_cnt();
 130   static bool is_a_protected_JavaThread_with_lock(JavaThread *thread) {
 131     MutexLockerEx ml(Threads_lock->owned_by_self() ? NULL : Threads_lock);
 132     return is_a_protected_JavaThread(thread);
 133   }
 134   static void release_stable_list(Thread *self);
 135   static void smr_delete(JavaThread *thread);
 136   static void smr_free_list(ThreadsList* threads);
 137   static void update_smr_java_thread_list_max(uint new_value);
 138   static void update_smr_tlh_time_max(uint new_value);
 139   static ThreadsList* xchg_smr_java_thread_list(ThreadsList* new_list);
 140 
 141   // Logging and printing support:
 142   static void log_smr_statistics();
 143   static void print_smr_info_elements_on(outputStream* st, ThreadsList* t_list);
 144   static void print_smr_info_on(outputStream* st);
 145 };
 146 
 147 // A fast list of JavaThreads.
 148 //
 149 class ThreadsList : public CHeapObj<mtThread> {
 150   friend class ThreadsSMRSupport;  // for next_list(), set_next_list() access
 151 
 152   const uint _length;
 153   ThreadsList* _next_list;
 154   JavaThread *const *const _threads;
 155 
 156   template <class T>
 157   void threads_do_dispatch(T *cl, JavaThread *const thread) const;
 158 
 159   ThreadsList *next_list() const        { return _next_list; }
 160   void set_next_list(ThreadsList *list) { _next_list = list; }
 161 
 162 public:
 163   ThreadsList(int entries);
 164   ~ThreadsList();
 165 
 166   template <class T>
 167   void threads_do(T *cl) const;
 168 
 169   uint length() const                       { return _length; }
 170 
 171   JavaThread *const thread_at(uint i) const { return _threads[i]; }
 172 
 173   JavaThread *const *threads() const        { return _threads; }
 174 
 175   // Returns -1 if target is not found.
 176   int find_index_of_JavaThread(JavaThread* target);
 177   JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const;
 178   bool includes(const JavaThread * const p) const;
 179 
 180   static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread);
 181   static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread);
 182 };
 183 
 184 // Linked list of ThreadsLists to support nested ThreadsListHandles.
 185 class NestedThreadsList : public CHeapObj<mtThread> {
 186   ThreadsList*const _t_list;
 187   NestedThreadsList* _next;
 188 
 189 public:
 190   NestedThreadsList(ThreadsList* t_list) : _t_list(t_list) {
 191     assert(Threads_lock->owned_by_self(),
 192            "must own Threads_lock for saved t_list to be valid.");
 193   }
 194 
 195   ThreadsList* t_list() { return _t_list; }
 196   NestedThreadsList* next() { return _next; }
 197   void set_next(NestedThreadsList* value) { _next = value; }
 198 };
 199 
 200 // A helper to optionally set the hazard ptr in ourself. This helper can
 201 // be used by ourself or by another thread. If the hazard ptr is set(),
 202 // then the destructor will release it.
 203 //
 204 class ThreadsListSetter : public StackObj {
 205 private:
 206   bool _target_needs_release;  // needs release only when set()
 207   Thread * _target;
 208 
 209 public:
 210   ThreadsListSetter() : _target_needs_release(false), _target(Thread::current()) {
 211   }
 212   ~ThreadsListSetter();
 213   ThreadsList* list();
 214   void set();
 215   bool target_needs_release() { return _target_needs_release; }
 216 };
 217 
 218 // This stack allocated ThreadsListHandle keeps all JavaThreads in the
 219 // ThreadsList from being deleted until it is safe.
 220 //
 221 class ThreadsListHandle : public StackObj {
 222   ThreadsList * _list;
 223   Thread *const _self;
 224   elapsedTimer _timer;  // Enabled via -XX:+EnableThreadSMRStatistics.
 225 
 226 public:
 227   ThreadsListHandle(Thread *self = Thread::current());
 228   ~ThreadsListHandle();
 229 
 230   ThreadsList *list() const {
 231     return _list;
 232   }
 233 
 234   template <class T>
 235   void threads_do(T *cl) const {
 236     return _list->threads_do(cl);
 237   }
 238 
 239   bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p);
 240 
 241   bool includes(JavaThread* p) {
 242     return _list->includes(p);
 243   }
 244 
 245   uint length() const {
 246     return _list->length();
 247   }
 248 };
 249 
 250 // This stack allocated JavaThreadIterator is used to walk the
 251 // specified ThreadsList using the following style:
 252 //
 253 //   JavaThreadIterator jti(t_list);
 254 //   for (JavaThread *jt = jti.first(); jt != NULL; jt = jti.next()) {
 255 //     ...
 256 //   }
 257 //
 258 class JavaThreadIterator : public StackObj {
 259   ThreadsList * _list;
 260   uint _index;
 261 
 262 public:
 263   JavaThreadIterator(ThreadsList *list) : _list(list), _index(0) {
 264     assert(list != NULL, "ThreadsList must not be NULL.");
 265   }
 266 
 267   JavaThread *first() {
 268     _index = 0;
 269     return _list->thread_at(_index);
 270   }
 271 
 272   uint length() const {
 273     return _list->length();
 274   }
 275 
 276   ThreadsList *list() const {
 277     return _list;
 278   }
 279 
 280   JavaThread *next() {
 281     if (++_index >= length()) {
 282       return NULL;
 283     }
 284     return _list->thread_at(_index);
 285   }
 286 };
 287 
 288 // This stack allocated ThreadsListHandle and JavaThreadIterator combo
 289 // is used to walk the ThreadsList in the included ThreadsListHandle
 290 // using the following style:
 291 //
 292 //   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
 293 //     ...
 294 //   }
 295 //
 296 class JavaThreadIteratorWithHandle : public StackObj {
 297   ThreadsListHandle _tlh;
 298   uint _index;
 299 
 300 public:
 301   JavaThreadIteratorWithHandle() : _index(0) {}
 302 
 303   uint length() const {
 304     return _tlh.length();
 305   }
 306 
 307   ThreadsList *list() const {
 308     return _tlh.list();
 309   }
 310 
 311   JavaThread *next() {
 312     if (_index >= length()) {
 313       return NULL;
 314     }
 315     return _tlh.list()->thread_at(_index++);
 316   }
 317 
 318   void rewind() {
 319     _index = 0;
 320   }
 321 };
 322 
 323 #endif // SHARE_VM_RUNTIME_THREADSMR_HPP