< prev index next >
src/hotspot/share/runtime/thread.hpp
Print this page
rev 47794 : Port 09.17.Thread_SMR_logging_update from JDK9 to JDK10
rev 47796 : eosterlund, stefank CR - refactor code into threadSMR.cpp and threadSMR.hpp
rev 47797 : eosterlund CR - need more inline fixes.
rev 47800 : Rebase to 2017.10.25 PIT snapshot.
*** 54,63 ****
--- 54,65 ----
#ifdef ZERO
# include "stack_zero.hpp"
#endif
class ThreadSafepointState;
+ class ThreadsList;
+ class NestedThreadsList;
class JvmtiThreadState;
class JvmtiGetLoadedClassesClosure;
class ThreadStatistics;
class ConcurrentLocksDump;
*** 98,107 ****
--- 100,110 ----
// - JavaThread
// - various subclasses eg CompilerThread, ServiceThread
// - WatcherThread
class Thread: public ThreadShadow {
+ friend class Threads;
friend class VMStructs;
friend class JVMCIVMStructs;
private:
#ifndef USE_LIBRARY_BASED_TLS_ONLY
*** 115,124 ****
--- 118,168 ----
// const char* _exception_file; // file information for exception (debugging only)
// int _exception_line; // line information for exception (debugging only)
protected:
// Support for forcing alignment of thread objects for biased locking
void* _real_malloc_address;
+ // JavaThread lifecycle support:
+ friend class ScanHazardPtrGatherProtectedThreadsClosure;
+ friend class ScanHazardPtrGatherThreadsListClosure;
+ friend class ScanHazardPtrPrintMatchingThreadsClosure;
+ friend class ThreadsListHandle;
+ friend class ThreadsListSetter;
+ ThreadsList* volatile _threads_hazard_ptr;
+ ThreadsList* cmpxchg_threads_hazard_ptr(ThreadsList* exchange_value, ThreadsList* compare_value);
+ ThreadsList* get_threads_hazard_ptr();
+ void set_threads_hazard_ptr(ThreadsList* new_list);
+ static bool is_hazard_ptr_tagged(ThreadsList* list) {
+ return (intptr_t(list) & intptr_t(1)) == intptr_t(1);
+ }
+ static ThreadsList* tag_hazard_ptr(ThreadsList* list) {
+ return (ThreadsList*)(intptr_t(list) | intptr_t(1));
+ }
+ static ThreadsList* untag_hazard_ptr(ThreadsList* list) {
+ return (ThreadsList*)(intptr_t(list) & ~intptr_t(1));
+ }
+ NestedThreadsList* _nested_threads_hazard_ptr;
+ NestedThreadsList* get_nested_threads_hazard_ptr() {
+ return _nested_threads_hazard_ptr;
+ }
+ void set_nested_threads_hazard_ptr(NestedThreadsList* value) {
+ assert(Threads_lock->owned_by_self(),
+ "must own Threads_lock for _nested_threads_hazard_ptr to be valid.");
+ _nested_threads_hazard_ptr = value;
+ }
+ // This field is enabled via -XX:+EnableThreadSMRStatistics:
+ uint _nested_threads_hazard_ptr_cnt;
+ void dec_nested_threads_hazard_ptr_cnt() {
+ assert(_nested_threads_hazard_ptr_cnt != 0, "mismatched {dec,inc}_nested_threads_hazard_ptr_cnt()");
+ _nested_threads_hazard_ptr_cnt--;
+ }
+ void inc_nested_threads_hazard_ptr_cnt() {
+ _nested_threads_hazard_ptr_cnt++;
+ }
+ uint nested_threads_hazard_ptr_cnt() {
+ return _nested_threads_hazard_ptr_cnt;
+ }
+
public:
void* operator new(size_t size) throw() { return allocate(size, true); }
void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() {
return allocate(size, false); }
void operator delete(void* p);
*** 354,363 ****
--- 398,410 ----
// Returns the current thread, or NULL if not attached, and is
// safe for use from signal-handlers
static inline Thread* current_or_null_safe();
// Common thread operations
+ #ifdef ASSERT
+ static void check_for_dangling_thread_pointer(Thread *thread);
+ #endif
static void set_priority(Thread* thread, ThreadPriority priority);
static ThreadPriority get_priority(const Thread* const thread);
static void start(Thread* thread);
static void interrupt(Thread* thr);
static bool is_interrupted(Thread* thr, bool clear_interrupted);
*** 569,578 ****
--- 616,626 ----
int lgrp_id() const { return _lgrp_id; }
void set_lgrp_id(int value) { _lgrp_id = value; }
// Printing
virtual void print_on(outputStream* st) const;
+ virtual void print_nested_threads_hazard_ptrs_on(outputStream* st) const;
void print() const { print_on(tty); }
virtual void print_on_error(outputStream* st, char* buf, int buflen) const;
void print_value_on(outputStream* st) const;
// Debug-only code
*** 789,798 ****
--- 837,847 ----
friend class VMStructs;
friend class JVMCIVMStructs;
friend class WhiteBox;
private:
JavaThread* _next; // The next thread in the Threads list
+ bool _on_thread_list; // Is set when this JavaThread is added to the Threads list
oop _threadObj; // The Java level thread object
#ifdef ASSERT
private:
int _java_call_counter;
*** 1116,1134 ****
#endif
ThreadSafepointState *safepoint_state() const { return _safepoint_state; }
void set_safepoint_state(ThreadSafepointState *state) { _safepoint_state = state; }
bool is_at_poll_safepoint() { return _safepoint_state->is_at_poll_safepoint(); }
// thread has called JavaThread::exit() or is terminated
! bool is_exiting() { return _terminated == _thread_exiting || is_terminated(); }
// thread is terminated (no longer on the threads list); we compare
// against the two non-terminated values so that a freed JavaThread
// will also be considered terminated.
! bool is_terminated() { return _terminated != _not_terminated && _terminated != _thread_exiting; }
! void set_terminated(TerminatedTypes t) { _terminated = t; }
// special for Threads::remove() which is static:
! void set_terminated_value() { _terminated = _thread_terminated; }
void block_if_vm_exited();
bool doing_unsafe_access() { return _doing_unsafe_access; }
void set_doing_unsafe_access(bool val) { _doing_unsafe_access = val; }
--- 1165,1191 ----
#endif
ThreadSafepointState *safepoint_state() const { return _safepoint_state; }
void set_safepoint_state(ThreadSafepointState *state) { _safepoint_state = state; }
bool is_at_poll_safepoint() { return _safepoint_state->is_at_poll_safepoint(); }
+ // JavaThread termination and lifecycle support:
+ void smr_delete();
+ bool on_thread_list() { return _on_thread_list; }
+ void set_on_thread_list() { _on_thread_list = true; }
+
// thread has called JavaThread::exit() or is terminated
! bool is_exiting() const;
// thread is terminated (no longer on the threads list); we compare
// against the two non-terminated values so that a freed JavaThread
// will also be considered terminated.
! bool check_is_terminated(TerminatedTypes l_terminated) const {
! return l_terminated != _not_terminated && l_terminated != _thread_exiting;
! }
! bool is_terminated();
! void set_terminated(TerminatedTypes t);
// special for Threads::remove() which is static:
! void set_terminated_value();
void block_if_vm_exited();
bool doing_unsafe_access() { return _doing_unsafe_access; }
void set_doing_unsafe_access(bool val) { _doing_unsafe_access = val; }
*** 1184,1193 ****
--- 1241,1253 ----
// calls to wait_for_ext_suspend_completion() can be done by passing
// other values in the code. Experiments with all calls can be done
// via the appropriate -XX options.
bool wait_for_ext_suspend_completion(int count, int delay, uint32_t *bits);
+ // test for suspend - most (all?) of these should go away
+ bool is_thread_fully_suspended(bool wait_for_suspend, uint32_t *bits);
+
inline void set_external_suspend();
inline void clear_external_suspend();
inline void set_deopt_suspend();
inline void clear_deopt_suspend();
*** 2030,2039 ****
--- 2090,2123 ----
// The active thread queue. It also keeps track of the current used
// thread priorities.
class Threads: AllStatic {
friend class VMStructs;
private:
+ // Safe Memory Reclamation (SMR) support:
+ static Monitor* _smr_delete_lock;
+ // The '_cnt', '_max' and '_times" fields are enabled via
+ // -XX:+EnableThreadSMRStatistics:
+ static uint _smr_delete_lock_wait_cnt;
+ static uint _smr_delete_lock_wait_max;
+ static volatile jint _smr_delete_notify;
+ static volatile jint _smr_deleted_thread_cnt;
+ static volatile jint _smr_deleted_thread_time_max;
+ static volatile jint _smr_deleted_thread_times;
+ static ThreadsList* volatile _smr_java_thread_list;
+ static ThreadsList* get_smr_java_thread_list();
+ static ThreadsList* xchg_smr_java_thread_list(ThreadsList* new_list);
+ static long _smr_java_thread_list_alloc_cnt;
+ static long _smr_java_thread_list_free_cnt;
+ static uint _smr_java_thread_list_max;
+ static uint _smr_nested_thread_list_max;
+ static volatile jint _smr_tlh_cnt;
+ static volatile jint _smr_tlh_time_max;
+ static volatile jint _smr_tlh_times;
+ static ThreadsList* _smr_to_delete_list;
+ static uint _smr_to_delete_list_cnt;
+ static uint _smr_to_delete_list_max;
+
static JavaThread* _thread_list;
static int _number_of_threads;
static int _number_of_non_daemon_threads;
static int _return_code;
static int _thread_claim_parity;
*** 2041,2061 ****
static bool _vm_complete;
#endif
static void initialize_java_lang_classes(JavaThread* main_thread, TRAPS);
static void initialize_jsr292_core_classes(TRAPS);
public:
// Thread management
// force_daemon is a concession to JNI, where we may need to add a
// thread to the thread list before allocating its thread object
static void add(JavaThread* p, bool force_daemon = false);
static void remove(JavaThread* p);
- static bool includes(JavaThread* p);
- static JavaThread* first() { return _thread_list; }
static void threads_do(ThreadClosure* tc);
static void possibly_parallel_threads_do(bool is_par, ThreadClosure* tc);
// Initializes the vm and creates the vm thread
static jint create_vm(JavaVMInitArgs* args, bool* canTryAgain);
static void convert_vm_init_libraries_to_agents();
static void create_vm_init_libraries();
static void create_vm_init_agents();
--- 2125,2178 ----
static bool _vm_complete;
#endif
static void initialize_java_lang_classes(JavaThread* main_thread, TRAPS);
static void initialize_jsr292_core_classes(TRAPS);
+
+ static void smr_free_list(ThreadsList* threads);
+
public:
// Thread management
// force_daemon is a concession to JNI, where we may need to add a
// thread to the thread list before allocating its thread object
static void add(JavaThread* p, bool force_daemon = false);
static void remove(JavaThread* p);
static void threads_do(ThreadClosure* tc);
static void possibly_parallel_threads_do(bool is_par, ThreadClosure* tc);
+ // SMR support:
+ template <class T>
+ static void threads_do_smr(T *tc, Thread *self);
+ static ThreadsList *acquire_stable_list(Thread *self, bool is_ThreadsListSetter);
+ static ThreadsList *acquire_stable_list_fast_path(Thread *self);
+ static ThreadsList *acquire_stable_list_nested_path(Thread *self);
+ static void release_stable_list(Thread *self);
+ 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 bool is_a_protected_JavaThread(JavaThread *thread);
+ static bool is_a_protected_JavaThread_with_lock(JavaThread *thread) {
+ MutexLockerEx ml(Threads_lock->owned_by_self() ? NULL : Threads_lock);
+ return is_a_protected_JavaThread(thread);
+ }
+ static void smr_delete(JavaThread *thread);
+ // The coordination between Threads::release_stable_list() and
+ // Threads::smr_delete() uses the smr_delete_lock in order to
+ // reduce the traffic on the Threads_lock.
+ static Monitor* smr_delete_lock() { return _smr_delete_lock; }
+ // The smr_delete_notify flag is used for proper double-check
+ // locking in order to reduce the traffic on the smr_delete_lock.
+ static bool smr_delete_notify();
+ static void set_smr_delete_notify();
+ static void clear_smr_delete_notify();
+ static void inc_smr_deleted_thread_cnt();
+ static void update_smr_deleted_thread_time_max(jint new_value);
+ static void add_smr_deleted_thread_times(jint add_value);
+ static void inc_smr_tlh_cnt();
+ static void update_smr_tlh_time_max(jint new_value);
+ static void add_smr_tlh_times(jint add_value);
+
// Initializes the vm and creates the vm thread
static jint create_vm(JavaVMInitArgs* args, bool* canTryAgain);
static void convert_vm_init_libraries_to_agents();
static void create_vm_init_libraries();
static void create_vm_init_agents();
*** 2112,2153 ****
static bool is_vm_complete() { return _vm_complete; }
#endif
// Verification
static void verify();
static void print_on(outputStream* st, bool print_stacks, bool internal_format, bool print_concurrent_locks);
static void print(bool print_stacks, bool internal_format) {
// this function is only used by debug.cpp
print_on(tty, print_stacks, internal_format, false /* no concurrent lock printed */);
}
static void print_on_error(outputStream* st, Thread* current, char* buf, int buflen);
static void print_on_error(Thread* this_thread, outputStream* st, Thread* current, char* buf,
int buflen, bool* found_current);
static void print_threads_compiling(outputStream* st, char* buf, int buflen);
! // Get Java threads that are waiting to enter a monitor. If doLock
! // is true, then Threads_lock is grabbed as needed. Otherwise, the
! // VM needs to be at a safepoint.
! static GrowableArray<JavaThread*>* get_pending_threads(int count,
! address monitor, bool doLock);
! // Get owning Java thread from the monitor's owner field. If doLock
! // is true, then Threads_lock is grabbed as needed. Otherwise, the
! // VM needs to be at a safepoint.
! static JavaThread *owning_thread_from_monitor_owner(address owner,
! bool doLock);
// Number of threads on the active threads list
static int number_of_threads() { return _number_of_threads; }
// Number of non-daemon threads on the active threads list
static int number_of_non_daemon_threads() { return _number_of_non_daemon_threads; }
// Deoptimizes all frames tied to marked nmethods
static void deoptimized_wrt_marked_nmethods();
-
- static JavaThread* find_java_thread_from_java_tid(jlong java_tid);
-
};
// Thread iterator
class ThreadClosure: public StackObj {
--- 2229,2266 ----
static bool is_vm_complete() { return _vm_complete; }
#endif
// Verification
static void verify();
+ static void log_smr_statistics();
static void print_on(outputStream* st, bool print_stacks, bool internal_format, bool print_concurrent_locks);
+ static void print_smr_info_on(outputStream* st);
+ static void print_smr_info_elements_on(outputStream* st, ThreadsList* t_list);
static void print(bool print_stacks, bool internal_format) {
// this function is only used by debug.cpp
print_on(tty, print_stacks, internal_format, false /* no concurrent lock printed */);
}
static void print_on_error(outputStream* st, Thread* current, char* buf, int buflen);
static void print_on_error(Thread* this_thread, outputStream* st, Thread* current, char* buf,
int buflen, bool* found_current);
static void print_threads_compiling(outputStream* st, char* buf, int buflen);
! // Get Java threads that are waiting to enter a monitor.
! static GrowableArray<JavaThread*>* get_pending_threads(ThreadsList * t_list,
! int count, address monitor);
! // Get owning Java thread from the monitor's owner field.
! static JavaThread *owning_thread_from_monitor_owner(ThreadsList * t_list,
! address owner);
// Number of threads on the active threads list
static int number_of_threads() { return _number_of_threads; }
// Number of non-daemon threads on the active threads list
static int number_of_non_daemon_threads() { return _number_of_non_daemon_threads; }
// Deoptimizes all frames tied to marked nmethods
static void deoptimized_wrt_marked_nmethods();
};
// Thread iterator
class ThreadClosure: public StackObj {
< prev index next >