< prev index next >
src/hotspot/share/runtime/threadSMR.hpp
Print this page
rev 49939 : imported patch 8191798.eosterlund.open.patch.00
rev 49940 : imported patch 8191798.dcubed.open.cr0.00
*** 26,35 ****
--- 26,39 ----
#define SHARE_VM_RUNTIME_THREADSMR_HPP
#include "memory/allocation.hpp"
#include "runtime/timer.hpp"
+ class JavaThread;
+ class Monitor;
+ class outputStream;
+ class Thread;
class ThreadClosure;
// Thread Safe Memory Reclamation (Thread-SMR) support.
//
// ThreadsListHandles are used to safely perform operations on one or more
*** 80,89 ****
--- 84,95 ----
// SMR Support for the Threads class.
//
class ThreadsSMRSupport : AllStatic {
+ friend class SafeThreadsListPtr; // for _nested_thread_list_max, delete_notify(), release_stable_list_wake_up() access
+
// The coordination between ThreadsSMRSupport::release_stable_list() and
// ThreadsSMRSupport::smr_delete() uses the delete_lock in order to
// reduce the traffic on the Threads_lock.
static Monitor* _delete_lock;
// The '_cnt', '_max' and '_times" fields are enabled via
*** 120,172 ****
static void free_list(ThreadsList* threads);
static void inc_deleted_thread_cnt();
static void inc_java_thread_list_alloc_cnt();
static void inc_tlh_cnt();
static bool is_a_protected_JavaThread(JavaThread *thread);
! static void release_stable_list_fast_path(Thread *self);
! static void release_stable_list_nested_path(Thread *self);
! static void release_stable_list_wake_up(char *log_str);
static void set_delete_notify();
static void threads_do(ThreadClosure *tc);
static void threads_do(ThreadClosure *tc, ThreadsList *list);
static void update_deleted_thread_time_max(uint new_value);
static void update_java_thread_list_max(uint new_value);
static void update_tlh_time_max(uint new_value);
! static void verify_hazard_pointer_scanned(Thread *self, ThreadsList *threads);
static ThreadsList* xchg_java_thread_list(ThreadsList* new_list);
public:
- static ThreadsList *acquire_stable_list(Thread *self, bool is_ThreadsListSetter);
static void add_thread(JavaThread *thread);
static ThreadsList* get_java_thread_list();
static bool is_a_protected_JavaThread_with_lock(JavaThread *thread);
- static void release_stable_list(Thread *self);
static void remove_thread(JavaThread *thread);
static void smr_delete(JavaThread *thread);
static void update_tlh_stats(uint millis);
// Logging and printing support:
static void log_statistics();
static void print_info_elements_on(outputStream* st, ThreadsList* t_list);
static void print_info_on(outputStream* st);
};
// A fast list of JavaThreads.
//
class ThreadsList : public CHeapObj<mtThread> {
! friend class ThreadsSMRSupport; // for next_list(), set_next_list() access
const uint _length;
ThreadsList* _next_list;
JavaThread *const *const _threads;
template <class T>
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; }
static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread);
static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread);
public:
ThreadsList(int entries);
--- 126,180 ----
static void free_list(ThreadsList* threads);
static void inc_deleted_thread_cnt();
static void inc_java_thread_list_alloc_cnt();
static void inc_tlh_cnt();
static bool is_a_protected_JavaThread(JavaThread *thread);
! static void release_stable_list_wake_up(bool is_nested);
static void set_delete_notify();
static void threads_do(ThreadClosure *tc);
static void threads_do(ThreadClosure *tc, ThreadsList *list);
static void update_deleted_thread_time_max(uint new_value);
static void update_java_thread_list_max(uint new_value);
static void update_tlh_time_max(uint new_value);
! static void verify_hazard_ptr_scanned(Thread *self, ThreadsList *threads);
static ThreadsList* xchg_java_thread_list(ThreadsList* new_list);
public:
static void add_thread(JavaThread *thread);
static ThreadsList* get_java_thread_list();
static bool is_a_protected_JavaThread_with_lock(JavaThread *thread);
static void remove_thread(JavaThread *thread);
static void smr_delete(JavaThread *thread);
static void update_tlh_stats(uint millis);
// Logging and printing support:
static void log_statistics();
static void print_info_elements_on(outputStream* st, ThreadsList* t_list);
static void print_info_on(outputStream* st);
+ static void print_info_on(const Thread* thread, outputStream* st);
};
// A fast list of JavaThreads.
//
class ThreadsList : public CHeapObj<mtThread> {
! friend class SafeThreadsListPtr; // for {dec,inc}_nested_handle_cnt() access
! friend class ThreadsSMRSupport; // for _nested_handle_cnt, {add,remove}_thread(), {,set_}next_list() access
const uint _length;
ThreadsList* _next_list;
JavaThread *const *const _threads;
+ volatile intx _nested_handle_cnt;
template <class T>
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; }
+ void inc_nested_handle_cnt();
+ void dec_nested_handle_cnt();
+
static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread);
static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread);
public:
ThreadsList(int entries);
*** 185,257 ****
int find_index_of_JavaThread(JavaThread* target);
JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const;
bool includes(const JavaThread * const p) const;
};
! // Linked list of ThreadsLists to support nested ThreadsListHandles.
! class NestedThreadsList : public CHeapObj<mtThread> {
! 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 <class T>
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:
--- 193,301 ----
int find_index_of_JavaThread(JavaThread* target);
JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const;
bool includes(const JavaThread * const p) const;
};
! // An abstract safe ptr to a ThreadsList comprising either a stable hazard ptr
! // for leaves, or a retained reference count for nested uses. The user of this
! // API does not need to know which mechanism is providing the safety.
! class SafeThreadsListPtr {
! friend class ThreadsListSetter;
!
! SafeThreadsListPtr* _previous;
! Thread* _thread;
! ThreadsList* _list;
! bool _has_ref_count;
! bool _needs_release;
!
! void acquire_stable_list();
! void acquire_stable_list_fast_path();
! void acquire_stable_list_nested_path();
!
! void release_stable_list();
!
! void verify_hazard_ptr_scanned();
public:
! // Constructor that attaches the list onto a thread.
! SafeThreadsListPtr(Thread *thread, bool acquire) :
! _previous(NULL),
! _thread(thread),
! _list(NULL),
! _has_ref_count(false),
! _needs_release(false)
! {
! if (acquire) {
! acquire_stable_list();
! }
! }
!
! // Constructor that transfers ownership of the pointer.
! SafeThreadsListPtr(SafeThreadsListPtr& other) :
! _previous(other._previous),
! _thread(other._thread),
! _list(other._list),
! _has_ref_count(other._has_ref_count),
! _needs_release(other._needs_release)
! {
! other._needs_release = false;
! }
!
! ~SafeThreadsListPtr() {
! if (_needs_release) {
! release_stable_list();
! }
}
! ThreadsList* list() const { return _list; }
! SafeThreadsListPtr* previous() const { return _previous; }
! void print_on(outputStream* st);
};
// 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:
! SafeThreadsListPtr _list_ptr;
public:
! ThreadsListSetter() : _list_ptr(Thread::current(), /* acquire */ false) {}
! ThreadsList* list() { return _list_ptr.list(); }
! void set() { _list_ptr.acquire_stable_list(); }
! bool is_set() { return _list_ptr._needs_release; }
};
// This stack allocated ThreadsListHandle keeps all JavaThreads in the
// ThreadsList from being deleted until it is safe.
//
class ThreadsListHandle : public StackObj {
! SafeThreadsListPtr _list_ptr;
elapsedTimer _timer; // Enabled via -XX:+EnableThreadSMRStatistics.
public:
ThreadsListHandle(Thread *self = Thread::current());
~ThreadsListHandle();
ThreadsList *list() const {
! return _list_ptr.list();
}
template <class T>
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:
< prev index next >