23 */ |
23 */ |
24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "gc/g1/g1ConcurrentRefine.hpp" |
26 #include "gc/g1/g1ConcurrentRefine.hpp" |
27 #include "gc/g1/g1ConcurrentRefineThread.hpp" |
27 #include "gc/g1/g1ConcurrentRefineThread.hpp" |
28 #include "gc/g1/g1CollectedHeap.inline.hpp" |
|
29 #include "gc/g1/g1RemSet.hpp" |
|
30 #include "gc/shared/suspendibleThreadSet.hpp" |
28 #include "gc/shared/suspendibleThreadSet.hpp" |
31 #include "logging/log.hpp" |
29 #include "logging/log.hpp" |
32 #include "memory/resourceArea.hpp" |
30 #include "memory/resourceArea.hpp" |
33 #include "runtime/handles.inline.hpp" |
31 #include "runtime/handles.inline.hpp" |
34 #include "runtime/mutexLocker.hpp" |
32 #include "runtime/mutexLocker.hpp" |
35 |
33 |
36 G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr, |
34 G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr, uint worker_id) : |
37 G1ConcurrentRefineThread *next, |
|
38 uint worker_id_offset, |
|
39 uint worker_id, |
|
40 size_t activate, |
|
41 size_t deactivate) : |
|
42 ConcurrentGCThread(), |
35 ConcurrentGCThread(), |
43 _worker_id_offset(worker_id_offset), |
|
44 _worker_id(worker_id), |
36 _worker_id(worker_id), |
45 _active(false), |
37 _active(false), |
46 _next(next), |
|
47 _monitor(NULL), |
38 _monitor(NULL), |
48 _cr(cr), |
39 _cr(cr), |
49 _vtime_accum(0.0), |
40 _vtime_accum(0.0) |
50 _activation_threshold(activate), |
|
51 _deactivation_threshold(deactivate) |
|
52 { |
41 { |
53 |
|
54 // Each thread has its own monitor. The i-th thread is responsible for signaling |
42 // Each thread has its own monitor. The i-th thread is responsible for signaling |
55 // to thread i+1 if the number of buffers in the queue exceeds a threshold for this |
43 // to thread i+1 if the number of buffers in the queue exceeds a threshold for this |
56 // thread. Monitors are also used to wake up the threads during termination. |
44 // thread. Monitors are also used to wake up the threads during termination. |
57 // The 0th (primary) worker is notified by mutator threads and has a special monitor. |
45 // The 0th (primary) worker is notified by mutator threads and has a special monitor. |
58 if (!is_primary()) { |
46 if (!is_primary()) { |
63 } |
51 } |
64 |
52 |
65 // set name |
53 // set name |
66 set_name("G1 Refine#%d", worker_id); |
54 set_name("G1 Refine#%d", worker_id); |
67 create_and_start(); |
55 create_and_start(); |
68 } |
|
69 |
|
70 void G1ConcurrentRefineThread::update_thresholds(size_t activate, |
|
71 size_t deactivate) { |
|
72 assert(deactivate < activate, "precondition"); |
|
73 _activation_threshold = activate; |
|
74 _deactivation_threshold = deactivate; |
|
75 } |
56 } |
76 |
57 |
77 void G1ConcurrentRefineThread::wait_for_completed_buffers() { |
58 void G1ConcurrentRefineThread::wait_for_completed_buffers() { |
78 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); |
59 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); |
79 while (!should_terminate() && !is_active()) { |
60 while (!should_terminate() && !is_active()) { |
116 if (should_terminate()) { |
97 if (should_terminate()) { |
117 break; |
98 break; |
118 } |
99 } |
119 |
100 |
120 size_t buffers_processed = 0; |
101 size_t buffers_processed = 0; |
121 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); |
102 log_debug(gc, refine)("Activated worker %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, |
122 log_debug(gc, refine)("Activated %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, |
103 _worker_id, _cr->activation_threshold(_worker_id), |
123 _worker_id, _activation_threshold, dcqs.completed_buffers_num()); |
104 JavaThread::dirty_card_queue_set().completed_buffers_num()); |
124 |
105 |
125 { |
106 { |
126 SuspendibleThreadSetJoiner sts_join; |
107 SuspendibleThreadSetJoiner sts_join; |
127 |
108 |
128 while (!should_terminate()) { |
109 while (!should_terminate()) { |
129 if (sts_join.should_yield()) { |
110 if (sts_join.should_yield()) { |
130 sts_join.yield(); |
111 sts_join.yield(); |
131 continue; // Re-check for termination after yield delay. |
112 continue; // Re-check for termination after yield delay. |
132 } |
113 } |
133 |
114 |
134 size_t curr_buffer_num = dcqs.completed_buffers_num(); |
115 if (!_cr->do_refinement_step(_worker_id)) { |
135 // If the number of the buffers falls down into the yellow zone, |
116 break; |
136 // that means that the transition period after the evacuation pause has ended. |
|
137 if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cr()->yellow_zone()) { |
|
138 dcqs.set_completed_queue_padding(0); |
|
139 } |
|
140 |
|
141 // Check if we need to activate the next thread. |
|
142 if ((_next != NULL) && |
|
143 !_next->is_active() && |
|
144 (curr_buffer_num > _next->_activation_threshold)) { |
|
145 _next->activate(); |
|
146 } |
|
147 |
|
148 // Process the next buffer, if there are enough left. |
|
149 if (!dcqs.refine_completed_buffer_concurrently(_worker_id + _worker_id_offset, _deactivation_threshold)) { |
|
150 break; // Deactivate, number of buffers fell below threshold. |
|
151 } |
117 } |
152 ++buffers_processed; |
118 ++buffers_processed; |
153 } |
119 } |
154 } |
120 } |
155 |
121 |
156 deactivate(); |
122 deactivate(); |
157 log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT |
123 log_debug(gc, refine)("Deactivated worker %d, off threshold: " SIZE_FORMAT |
158 ", current: " SIZE_FORMAT ", processed: " SIZE_FORMAT, |
124 ", current: " SIZE_FORMAT ", processed: " SIZE_FORMAT, |
159 _worker_id, _deactivation_threshold, |
125 _worker_id, _cr->deactivation_threshold(_worker_id), |
160 dcqs.completed_buffers_num(), |
126 JavaThread::dirty_card_queue_set().completed_buffers_num(), |
161 buffers_processed); |
127 buffers_processed); |
162 |
128 |
163 if (os::supports_vtime()) { |
129 if (os::supports_vtime()) { |
164 _vtime_accum = (os::elapsedVTime() - _vtime_start); |
130 _vtime_accum = (os::elapsedVTime() - _vtime_start); |
165 } else { |
131 } else { |