src/hotspot/share/runtime/threadSMR.hpp
changeset 49956 a87f2e7a527c
parent 49756 129d60b5dac7
child 52448 bc5c7f63dbae
equal deleted inserted replaced
49955:ea246151be08 49956:a87f2e7a527c
    26 #define SHARE_VM_RUNTIME_THREADSMR_HPP
    26 #define SHARE_VM_RUNTIME_THREADSMR_HPP
    27 
    27 
    28 #include "memory/allocation.hpp"
    28 #include "memory/allocation.hpp"
    29 #include "runtime/timer.hpp"
    29 #include "runtime/timer.hpp"
    30 
    30 
       
    31 class JavaThread;
       
    32 class Monitor;
       
    33 class outputStream;
       
    34 class Thread;
    31 class ThreadClosure;
    35 class ThreadClosure;
    32 
    36 
    33 // Thread Safe Memory Reclamation (Thread-SMR) support.
    37 // Thread Safe Memory Reclamation (Thread-SMR) support.
    34 //
    38 //
    35 // ThreadsListHandles are used to safely perform operations on one or more
    39 // ThreadsListHandles are used to safely perform operations on one or more
    80 
    84 
    81 
    85 
    82 // SMR Support for the Threads class.
    86 // SMR Support for the Threads class.
    83 //
    87 //
    84 class ThreadsSMRSupport : AllStatic {
    88 class ThreadsSMRSupport : AllStatic {
       
    89   friend class SafeThreadsListPtr;  // for _nested_thread_list_max, delete_notify(), release_stable_list_wake_up() access
       
    90 
    85   // The coordination between ThreadsSMRSupport::release_stable_list() and
    91   // The coordination between ThreadsSMRSupport::release_stable_list() and
    86   // ThreadsSMRSupport::smr_delete() uses the delete_lock in order to
    92   // ThreadsSMRSupport::smr_delete() uses the delete_lock in order to
    87   // reduce the traffic on the Threads_lock.
    93   // reduce the traffic on the Threads_lock.
    88   static Monitor*              _delete_lock;
    94   static Monitor*              _delete_lock;
    89   // The '_cnt', '_max' and '_times" fields are enabled via
    95   // The '_cnt', '_max' and '_times" fields are enabled via
   120   static void free_list(ThreadsList* threads);
   126   static void free_list(ThreadsList* threads);
   121   static void inc_deleted_thread_cnt();
   127   static void inc_deleted_thread_cnt();
   122   static void inc_java_thread_list_alloc_cnt();
   128   static void inc_java_thread_list_alloc_cnt();
   123   static void inc_tlh_cnt();
   129   static void inc_tlh_cnt();
   124   static bool is_a_protected_JavaThread(JavaThread *thread);
   130   static bool is_a_protected_JavaThread(JavaThread *thread);
   125   static void release_stable_list_fast_path(Thread *self);
   131   static void release_stable_list_wake_up(bool is_nested);
   126   static void release_stable_list_nested_path(Thread *self);
       
   127   static void release_stable_list_wake_up(char *log_str);
       
   128   static void set_delete_notify();
   132   static void set_delete_notify();
   129   static void threads_do(ThreadClosure *tc);
   133   static void threads_do(ThreadClosure *tc);
   130   static void threads_do(ThreadClosure *tc, ThreadsList *list);
   134   static void threads_do(ThreadClosure *tc, ThreadsList *list);
   131   static void update_deleted_thread_time_max(uint new_value);
   135   static void update_deleted_thread_time_max(uint new_value);
   132   static void update_java_thread_list_max(uint new_value);
   136   static void update_java_thread_list_max(uint new_value);
   133   static void update_tlh_time_max(uint new_value);
   137   static void update_tlh_time_max(uint new_value);
   134   static void verify_hazard_pointer_scanned(Thread *self, ThreadsList *threads);
   138   static void verify_hazard_ptr_scanned(Thread *self, ThreadsList *threads);
   135   static ThreadsList* xchg_java_thread_list(ThreadsList* new_list);
   139   static ThreadsList* xchg_java_thread_list(ThreadsList* new_list);
   136 
   140 
   137  public:
   141  public:
   138   static ThreadsList *acquire_stable_list(Thread *self, bool is_ThreadsListSetter);
       
   139   static void add_thread(JavaThread *thread);
   142   static void add_thread(JavaThread *thread);
   140   static ThreadsList* get_java_thread_list();
   143   static ThreadsList* get_java_thread_list();
   141   static bool is_a_protected_JavaThread_with_lock(JavaThread *thread);
   144   static bool is_a_protected_JavaThread_with_lock(JavaThread *thread);
   142   static void release_stable_list(Thread *self);
       
   143   static void remove_thread(JavaThread *thread);
   145   static void remove_thread(JavaThread *thread);
   144   static void smr_delete(JavaThread *thread);
   146   static void smr_delete(JavaThread *thread);
   145   static void update_tlh_stats(uint millis);
   147   static void update_tlh_stats(uint millis);
   146 
   148 
   147   // Logging and printing support:
   149   // Logging and printing support:
   148   static void log_statistics();
   150   static void log_statistics();
   149   static void print_info_elements_on(outputStream* st, ThreadsList* t_list);
   151   static void print_info_elements_on(outputStream* st, ThreadsList* t_list);
   150   static void print_info_on(outputStream* st);
   152   static void print_info_on(outputStream* st);
       
   153   static void print_info_on(const Thread* thread, outputStream* st);
   151 };
   154 };
   152 
   155 
   153 // A fast list of JavaThreads.
   156 // A fast list of JavaThreads.
   154 //
   157 //
   155 class ThreadsList : public CHeapObj<mtThread> {
   158 class ThreadsList : public CHeapObj<mtThread> {
   156   friend class ThreadsSMRSupport;  // for next_list(), set_next_list() access
   159   friend class SafeThreadsListPtr;  // for {dec,inc}_nested_handle_cnt() access
       
   160   friend class ThreadsSMRSupport;  // for _nested_handle_cnt, {add,remove}_thread(), {,set_}next_list() access
   157 
   161 
   158   const uint _length;
   162   const uint _length;
   159   ThreadsList* _next_list;
   163   ThreadsList* _next_list;
   160   JavaThread *const *const _threads;
   164   JavaThread *const *const _threads;
       
   165   volatile intx _nested_handle_cnt;
   161 
   166 
   162   template <class T>
   167   template <class T>
   163   void threads_do_dispatch(T *cl, JavaThread *const thread) const;
   168   void threads_do_dispatch(T *cl, JavaThread *const thread) const;
   164 
   169 
   165   ThreadsList *next_list() const        { return _next_list; }
   170   ThreadsList *next_list() const        { return _next_list; }
   166   void set_next_list(ThreadsList *list) { _next_list = list; }
   171   void set_next_list(ThreadsList *list) { _next_list = list; }
       
   172 
       
   173   void inc_nested_handle_cnt();
       
   174   void dec_nested_handle_cnt();
   167 
   175 
   168   static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread);
   176   static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread);
   169   static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread);
   177   static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread);
   170 
   178 
   171 public:
   179 public:
   185   int find_index_of_JavaThread(JavaThread* target);
   193   int find_index_of_JavaThread(JavaThread* target);
   186   JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const;
   194   JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const;
   187   bool includes(const JavaThread * const p) const;
   195   bool includes(const JavaThread * const p) const;
   188 };
   196 };
   189 
   197 
   190 // Linked list of ThreadsLists to support nested ThreadsListHandles.
   198 // An abstract safe ptr to a ThreadsList comprising either a stable hazard ptr
   191 class NestedThreadsList : public CHeapObj<mtThread> {
   199 // for leaves, or a retained reference count for nested uses. The user of this
   192   ThreadsList*const _t_list;
   200 // API does not need to know which mechanism is providing the safety.
   193   NestedThreadsList* _next;
   201 class SafeThreadsListPtr {
   194 
   202   friend class ThreadsListSetter;
   195 public:
   203 
   196   NestedThreadsList(ThreadsList* t_list) : _t_list(t_list) {
   204   SafeThreadsListPtr* _previous;
   197     assert(Threads_lock->owned_by_self(),
   205   Thread*                 _thread;
   198            "must own Threads_lock for saved t_list to be valid.");
   206   ThreadsList*            _list;
   199   }
   207   bool                    _has_ref_count;
   200 
   208   bool                    _needs_release;
   201   ThreadsList* t_list() { return _t_list; }
   209 
   202   NestedThreadsList* next() { return _next; }
   210   void acquire_stable_list();
   203   void set_next(NestedThreadsList* value) { _next = value; }
   211   void acquire_stable_list_fast_path();
       
   212   void acquire_stable_list_nested_path();
       
   213 
       
   214   void release_stable_list();
       
   215 
       
   216   void verify_hazard_ptr_scanned();
       
   217 
       
   218 public:
       
   219   // Constructor that attaches the list onto a thread.
       
   220   SafeThreadsListPtr(Thread *thread, bool acquire) :
       
   221     _previous(NULL),
       
   222     _thread(thread),
       
   223     _list(NULL),
       
   224     _has_ref_count(false),
       
   225     _needs_release(false)
       
   226   {
       
   227     if (acquire) {
       
   228       acquire_stable_list();
       
   229     }
       
   230   }
       
   231 
       
   232   // Constructor that transfers ownership of the pointer.
       
   233   SafeThreadsListPtr(SafeThreadsListPtr& other) :
       
   234     _previous(other._previous),
       
   235     _thread(other._thread),
       
   236     _list(other._list),
       
   237     _has_ref_count(other._has_ref_count),
       
   238     _needs_release(other._needs_release)
       
   239   {
       
   240     other._needs_release = false;
       
   241   }
       
   242 
       
   243   ~SafeThreadsListPtr() {
       
   244     if (_needs_release) {
       
   245       release_stable_list();
       
   246     }
       
   247   }
       
   248 
       
   249   ThreadsList* list() const { return _list; }
       
   250   SafeThreadsListPtr* previous() const { return _previous; }
       
   251   void print_on(outputStream* st);
   204 };
   252 };
   205 
   253 
   206 // A helper to optionally set the hazard ptr in ourself. This helper can
   254 // A helper to optionally set the hazard ptr in ourself. This helper can
   207 // be used by ourself or by another thread. If the hazard ptr is set(),
   255 // be used by ourself or by another thread. If the hazard ptr is set(),
   208 // then the destructor will release it.
   256 // then the destructor will release it.
   209 //
   257 //
   210 class ThreadsListSetter : public StackObj {
   258 class ThreadsListSetter : public StackObj {
   211 private:
   259 private:
   212   bool _target_needs_release;  // needs release only when set()
   260   SafeThreadsListPtr _list_ptr;
   213   Thread * _target;
   261 
   214 
   262 public:
   215 public:
   263   ThreadsListSetter() : _list_ptr(Thread::current(), /* acquire */ false) {}
   216   ThreadsListSetter() : _target_needs_release(false), _target(Thread::current()) {
   264   ThreadsList* list() { return _list_ptr.list(); }
   217   }
   265   void set() { _list_ptr.acquire_stable_list(); }
   218   ~ThreadsListSetter();
   266   bool is_set() { return _list_ptr._needs_release; }
   219   ThreadsList* list();
       
   220   void set();
       
   221   bool target_needs_release() { return _target_needs_release; }
       
   222 };
   267 };
   223 
   268 
   224 // This stack allocated ThreadsListHandle keeps all JavaThreads in the
   269 // This stack allocated ThreadsListHandle keeps all JavaThreads in the
   225 // ThreadsList from being deleted until it is safe.
   270 // ThreadsList from being deleted until it is safe.
   226 //
   271 //
   227 class ThreadsListHandle : public StackObj {
   272 class ThreadsListHandle : public StackObj {
   228   ThreadsList * _list;
   273   SafeThreadsListPtr _list_ptr;
   229   Thread *const _self;
       
   230   elapsedTimer _timer;  // Enabled via -XX:+EnableThreadSMRStatistics.
   274   elapsedTimer _timer;  // Enabled via -XX:+EnableThreadSMRStatistics.
   231 
   275 
   232 public:
   276 public:
   233   ThreadsListHandle(Thread *self = Thread::current());
   277   ThreadsListHandle(Thread *self = Thread::current());
   234   ~ThreadsListHandle();
   278   ~ThreadsListHandle();
   235 
   279 
   236   ThreadsList *list() const {
   280   ThreadsList *list() const {
   237     return _list;
   281     return _list_ptr.list();
   238   }
   282   }
   239 
   283 
   240   template <class T>
   284   template <class T>
   241   void threads_do(T *cl) const {
   285   void threads_do(T *cl) const {
   242     return _list->threads_do(cl);
   286     return list()->threads_do(cl);
   243   }
   287   }
   244 
   288 
   245   bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p);
   289   bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p);
   246 
   290 
   247   bool includes(JavaThread* p) {
   291   bool includes(JavaThread* p) {
   248     return _list->includes(p);
   292     return list()->includes(p);
   249   }
   293   }
   250 
   294 
   251   uint length() const {
   295   uint length() const {
   252     return _list->length();
   296     return list()->length();
   253   }
   297   }
   254 };
   298 };
   255 
   299 
   256 // This stack allocated JavaThreadIterator is used to walk the
   300 // This stack allocated JavaThreadIterator is used to walk the
   257 // specified ThreadsList using the following style:
   301 // specified ThreadsList using the following style: