68 // Impl note: Atomically added to over VM lifetime so use unsigned for more |
68 // Impl note: Atomically added to over VM lifetime so use unsigned for more |
69 // range. Unsigned 64-bit would be more future proof, but 64-bit atomic inc |
69 // range. Unsigned 64-bit would be more future proof, but 64-bit atomic inc |
70 // isn't available everywhere (or is it?). |
70 // isn't available everywhere (or is it?). |
71 volatile uint ThreadsSMRSupport::_deleted_thread_times = 0; |
71 volatile uint ThreadsSMRSupport::_deleted_thread_times = 0; |
72 |
72 |
73 ThreadsList* volatile ThreadsSMRSupport::_java_thread_list = new ThreadsList(0); |
73 // The bootstrap list is empty and cannot be freed. |
|
74 ThreadsList ThreadsSMRSupport::_bootstrap_list = ThreadsList(0); |
|
75 |
|
76 // This is the VM's current "threads list" and it contains all of |
|
77 // the JavaThreads the VM considers to be alive at this moment in |
|
78 // time. The other ThreadsList objects in the VM contain past |
|
79 // snapshots of the "threads list". _java_thread_list is initially |
|
80 // set to _bootstrap_list so that we can detect when we have a very |
|
81 // early use of a ThreadsListHandle. |
|
82 ThreadsList* volatile ThreadsSMRSupport::_java_thread_list = &_bootstrap_list; |
74 |
83 |
75 // # of ThreadsLists allocated over VM lifetime. |
84 // # of ThreadsLists allocated over VM lifetime. |
76 // Impl note: We allocate a new ThreadsList for every thread create and |
85 // Impl note: We allocate a new ThreadsList for every thread create and |
77 // every thread delete so we need a bigger type than the |
86 // every thread delete so we need a bigger type than the |
78 // _deleted_thread_cnt field. |
87 // _deleted_thread_cnt field. |
131 Atomic::inc(&_deleted_thread_cnt); |
140 Atomic::inc(&_deleted_thread_cnt); |
132 } |
141 } |
133 |
142 |
134 inline void ThreadsSMRSupport::inc_java_thread_list_alloc_cnt() { |
143 inline void ThreadsSMRSupport::inc_java_thread_list_alloc_cnt() { |
135 _java_thread_list_alloc_cnt++; |
144 _java_thread_list_alloc_cnt++; |
|
145 } |
|
146 |
|
147 inline bool ThreadsSMRSupport::is_bootstrap_list(ThreadsList* list) { |
|
148 return list == &_bootstrap_list; |
136 } |
149 } |
137 |
150 |
138 inline void ThreadsSMRSupport::update_deleted_thread_time_max(uint new_value) { |
151 inline void ThreadsSMRSupport::update_deleted_thread_time_max(uint new_value) { |
139 while (true) { |
152 while (true) { |
140 uint cur_value = _deleted_thread_time_max; |
153 uint cur_value = _deleted_thread_time_max; |
156 } |
169 } |
157 |
170 |
158 inline ThreadsList* ThreadsSMRSupport::xchg_java_thread_list(ThreadsList* new_list) { |
171 inline ThreadsList* ThreadsSMRSupport::xchg_java_thread_list(ThreadsList* new_list) { |
159 return (ThreadsList*)Atomic::xchg(new_list, &_java_thread_list); |
172 return (ThreadsList*)Atomic::xchg(new_list, &_java_thread_list); |
160 } |
173 } |
161 |
|
162 |
174 |
163 // Hash table of pointers found by a scan. Used for collecting hazard |
175 // Hash table of pointers found by a scan. Used for collecting hazard |
164 // pointers (ThreadsList references). Also used for collecting JavaThreads |
176 // pointers (ThreadsList references). Also used for collecting JavaThreads |
165 // that are indirectly referenced by hazard ptrs. An instance of this |
177 // that are indirectly referenced by hazard ptrs. An instance of this |
166 // class only contains one type of pointer. |
178 // class only contains one type of pointer. |
507 // alive is scanned by threads_do() which is a key piece of honoring |
519 // alive is scanned by threads_do() which is a key piece of honoring |
508 // the Thread-SMR protocol. |
520 // the Thread-SMR protocol. |
509 void SafeThreadsListPtr::verify_hazard_ptr_scanned() { |
521 void SafeThreadsListPtr::verify_hazard_ptr_scanned() { |
510 #ifdef ASSERT |
522 #ifdef ASSERT |
511 assert(_list != NULL, "_list must not be NULL"); |
523 assert(_list != NULL, "_list must not be NULL"); |
|
524 |
|
525 if (ThreadsSMRSupport::is_bootstrap_list(_list)) { |
|
526 // We are early in VM bootstrapping so nothing to do here. |
|
527 return; |
|
528 } |
512 |
529 |
513 // The closure will attempt to verify that the calling thread can |
530 // The closure will attempt to verify that the calling thread can |
514 // be found by threads_do() on the specified ThreadsList. If it |
531 // be found by threads_do() on the specified ThreadsList. If it |
515 // is successful, then the specified ThreadsList was acquired as |
532 // is successful, then the specified ThreadsList was acquired as |
516 // a stable hazard ptr by the calling thread in a way that honored |
533 // a stable hazard ptr by the calling thread in a way that honored |
759 // The specified ThreadsList may not get deleted during this call if it |
776 // The specified ThreadsList may not get deleted during this call if it |
760 // is still in-use (referenced by a hazard ptr). Other ThreadsLists |
777 // is still in-use (referenced by a hazard ptr). Other ThreadsLists |
761 // in the chain may get deleted by this call if they are no longer in-use. |
778 // in the chain may get deleted by this call if they are no longer in-use. |
762 void ThreadsSMRSupport::free_list(ThreadsList* threads) { |
779 void ThreadsSMRSupport::free_list(ThreadsList* threads) { |
763 assert_locked_or_safepoint(Threads_lock); |
780 assert_locked_or_safepoint(Threads_lock); |
|
781 |
|
782 if (is_bootstrap_list(threads)) { |
|
783 // The bootstrap list cannot be freed and is empty so |
|
784 // it does not need to be scanned. Nothing to do here. |
|
785 log_debug(thread, smr)("tid=" UINTX_FORMAT ": ThreadsSMRSupport::free_list: bootstrap ThreadsList=" INTPTR_FORMAT " is no longer in use.", os::current_thread_id(), p2i(threads)); |
|
786 return; |
|
787 } |
764 |
788 |
765 threads->set_next_list(_to_delete_list); |
789 threads->set_next_list(_to_delete_list); |
766 _to_delete_list = threads; |
790 _to_delete_list = threads; |
767 if (EnableThreadSMRStatistics) { |
791 if (EnableThreadSMRStatistics) { |
768 _to_delete_list_cnt++; |
792 _to_delete_list_cnt++; |