76 allocate_buffer(); // Buffer enqueued, get a new one. |
76 allocate_buffer(); // Buffer enqueued, get a new one. |
77 } |
77 } |
78 } |
78 } |
79 |
79 |
80 G1DirtyCardQueueSet::G1DirtyCardQueueSet(bool notify_when_complete) : |
80 G1DirtyCardQueueSet::G1DirtyCardQueueSet(bool notify_when_complete) : |
81 PtrQueueSet(notify_when_complete), |
81 PtrQueueSet(), |
|
82 _cbl_mon(NULL), |
|
83 _completed_buffers_head(NULL), |
|
84 _completed_buffers_tail(NULL), |
|
85 _n_completed_buffers(0), |
|
86 _process_completed_buffers_threshold(ProcessCompletedBuffersThresholdNever), |
|
87 _process_completed_buffers(false), |
|
88 _notify_when_complete(notify_when_complete), |
82 _max_completed_buffers(MaxCompletedBuffersUnlimited), |
89 _max_completed_buffers(MaxCompletedBuffersUnlimited), |
83 _completed_buffers_padding(0), |
90 _completed_buffers_padding(0), |
84 _free_ids(NULL), |
91 _free_ids(NULL), |
85 _processed_buffers_mut(0), |
92 _processed_buffers_mut(0), |
86 _processed_buffers_rs_thread(0), |
93 _processed_buffers_rs_thread(0), |
99 } |
107 } |
100 |
108 |
101 void G1DirtyCardQueueSet::initialize(Monitor* cbl_mon, |
109 void G1DirtyCardQueueSet::initialize(Monitor* cbl_mon, |
102 BufferNode::Allocator* allocator, |
110 BufferNode::Allocator* allocator, |
103 bool init_free_ids) { |
111 bool init_free_ids) { |
104 PtrQueueSet::initialize(cbl_mon, allocator); |
112 PtrQueueSet::initialize(allocator); |
|
113 assert(_cbl_mon == NULL, "Init order issue?"); |
|
114 _cbl_mon = cbl_mon; |
105 if (init_free_ids) { |
115 if (init_free_ids) { |
106 _free_ids = new G1FreeIdSet(0, num_par_ids()); |
116 _free_ids = new G1FreeIdSet(0, num_par_ids()); |
107 } |
117 } |
108 } |
118 } |
109 |
119 |
110 void G1DirtyCardQueueSet::handle_zero_index_for_thread(Thread* t) { |
120 void G1DirtyCardQueueSet::handle_zero_index_for_thread(Thread* t) { |
111 G1ThreadLocalData::dirty_card_queue(t).handle_zero_index(); |
121 G1ThreadLocalData::dirty_card_queue(t).handle_zero_index(); |
|
122 } |
|
123 |
|
124 void G1DirtyCardQueueSet::enqueue_completed_buffer(BufferNode* cbn) { |
|
125 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag); |
|
126 cbn->set_next(NULL); |
|
127 if (_completed_buffers_tail == NULL) { |
|
128 assert(_completed_buffers_head == NULL, "Well-formedness"); |
|
129 _completed_buffers_head = cbn; |
|
130 _completed_buffers_tail = cbn; |
|
131 } else { |
|
132 _completed_buffers_tail->set_next(cbn); |
|
133 _completed_buffers_tail = cbn; |
|
134 } |
|
135 _n_completed_buffers++; |
|
136 |
|
137 if (!process_completed_buffers() && |
|
138 (_n_completed_buffers > process_completed_buffers_threshold())) { |
|
139 set_process_completed_buffers(true); |
|
140 if (_notify_when_complete) { |
|
141 _cbl_mon->notify_all(); |
|
142 } |
|
143 } |
|
144 assert_completed_buffers_list_len_correct_locked(); |
|
145 } |
|
146 |
|
147 BufferNode* G1DirtyCardQueueSet::get_completed_buffer(size_t stop_at) { |
|
148 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag); |
|
149 |
|
150 if (_n_completed_buffers <= stop_at) { |
|
151 return NULL; |
|
152 } |
|
153 |
|
154 assert(_n_completed_buffers > 0, "invariant"); |
|
155 assert(_completed_buffers_head != NULL, "invariant"); |
|
156 assert(_completed_buffers_tail != NULL, "invariant"); |
|
157 |
|
158 BufferNode* bn = _completed_buffers_head; |
|
159 _n_completed_buffers--; |
|
160 _completed_buffers_head = bn->next(); |
|
161 if (_completed_buffers_head == NULL) { |
|
162 assert(_n_completed_buffers == 0, "invariant"); |
|
163 _completed_buffers_tail = NULL; |
|
164 set_process_completed_buffers(false); |
|
165 } |
|
166 assert_completed_buffers_list_len_correct_locked(); |
|
167 bn->set_next(NULL); |
|
168 return bn; |
|
169 } |
|
170 |
|
171 void G1DirtyCardQueueSet::abandon_completed_buffers() { |
|
172 BufferNode* buffers_to_delete = NULL; |
|
173 { |
|
174 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag); |
|
175 buffers_to_delete = _completed_buffers_head; |
|
176 _completed_buffers_head = NULL; |
|
177 _completed_buffers_tail = NULL; |
|
178 _n_completed_buffers = 0; |
|
179 set_process_completed_buffers(false); |
|
180 } |
|
181 while (buffers_to_delete != NULL) { |
|
182 BufferNode* bn = buffers_to_delete; |
|
183 buffers_to_delete = bn->next(); |
|
184 bn->set_next(NULL); |
|
185 deallocate_buffer(bn); |
|
186 } |
|
187 } |
|
188 |
|
189 void G1DirtyCardQueueSet::notify_if_necessary() { |
|
190 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag); |
|
191 if (_n_completed_buffers > process_completed_buffers_threshold()) { |
|
192 set_process_completed_buffers(true); |
|
193 if (_notify_when_complete) |
|
194 _cbl_mon->notify(); |
|
195 } |
|
196 } |
|
197 |
|
198 #ifdef ASSERT |
|
199 void G1DirtyCardQueueSet::assert_completed_buffers_list_len_correct_locked() { |
|
200 assert_lock_strong(_cbl_mon); |
|
201 size_t n = 0; |
|
202 for (BufferNode* bn = _completed_buffers_head; bn != NULL; bn = bn->next()) { |
|
203 ++n; |
|
204 } |
|
205 assert(n == _n_completed_buffers, |
|
206 "Completed buffer length is wrong: counted: " SIZE_FORMAT |
|
207 ", expected: " SIZE_FORMAT, n, _n_completed_buffers); |
|
208 } |
|
209 #endif // ASSERT |
|
210 |
|
211 // Merge lists of buffers. Notify the processing threads. |
|
212 // The source queue is emptied as a result. The queues |
|
213 // must share the monitor. |
|
214 void G1DirtyCardQueueSet::merge_bufferlists(G1DirtyCardQueueSet *src) { |
|
215 assert(_cbl_mon == src->_cbl_mon, "Should share the same lock"); |
|
216 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag); |
|
217 if (_completed_buffers_tail == NULL) { |
|
218 assert(_completed_buffers_head == NULL, "Well-formedness"); |
|
219 _completed_buffers_head = src->_completed_buffers_head; |
|
220 _completed_buffers_tail = src->_completed_buffers_tail; |
|
221 } else { |
|
222 assert(_completed_buffers_head != NULL, "Well formedness"); |
|
223 if (src->_completed_buffers_head != NULL) { |
|
224 _completed_buffers_tail->set_next(src->_completed_buffers_head); |
|
225 _completed_buffers_tail = src->_completed_buffers_tail; |
|
226 } |
|
227 } |
|
228 _n_completed_buffers += src->_n_completed_buffers; |
|
229 |
|
230 src->_n_completed_buffers = 0; |
|
231 src->_completed_buffers_head = NULL; |
|
232 src->_completed_buffers_tail = NULL; |
|
233 src->set_process_completed_buffers(false); |
|
234 |
|
235 assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL || |
|
236 _completed_buffers_head != NULL && _completed_buffers_tail != NULL, |
|
237 "Sanity"); |
|
238 assert_completed_buffers_list_len_correct_locked(); |
112 } |
239 } |
113 |
240 |
114 bool G1DirtyCardQueueSet::apply_closure_to_buffer(G1CardTableEntryClosure* cl, |
241 bool G1DirtyCardQueueSet::apply_closure_to_buffer(G1CardTableEntryClosure* cl, |
115 BufferNode* node, |
242 BufferNode* node, |
116 bool consume, |
243 bool consume, |