61 // active field set to true.
62 PtrQueue(qset, true /* active */)
63 { }
64
65 G1DirtyCardQueue::~G1DirtyCardQueue() {
66 flush();
67 }
68
69 void G1DirtyCardQueue::handle_completed_buffer() {
70 assert(_buf != NULL, "precondition");
71 BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
72 G1DirtyCardQueueSet* dcqs = dirty_card_qset();
73 if (dcqs->process_or_enqueue_completed_buffer(node)) {
74 reset(); // Buffer fully processed, reset index.
75 } else {
76 allocate_buffer(); // Buffer enqueued, get a new one.
77 }
78 }
79
80 G1DirtyCardQueueSet::G1DirtyCardQueueSet(bool notify_when_complete) :
81 PtrQueueSet(notify_when_complete),
82 _max_completed_buffers(MaxCompletedBuffersUnlimited),
83 _completed_buffers_padding(0),
84 _free_ids(NULL),
85 _processed_buffers_mut(0),
86 _processed_buffers_rs_thread(0),
87 _cur_par_buffer_node(NULL)
88 {
89 _all_active = true;
90 }
91
92 G1DirtyCardQueueSet::~G1DirtyCardQueueSet() {
93 delete _free_ids;
94 }
95
96 // Determines how many mutator threads can process the buffers in parallel.
97 uint G1DirtyCardQueueSet::num_par_ids() {
98 return (uint)os::initial_active_processor_count();
99 }
100
101 void G1DirtyCardQueueSet::initialize(Monitor* cbl_mon,
102 BufferNode::Allocator* allocator,
103 bool init_free_ids) {
104 PtrQueueSet::initialize(cbl_mon, allocator);
105 if (init_free_ids) {
106 _free_ids = new G1FreeIdSet(0, num_par_ids());
107 }
108 }
109
110 void G1DirtyCardQueueSet::handle_zero_index_for_thread(Thread* t) {
111 G1ThreadLocalData::dirty_card_queue(t).handle_zero_index();
112 }
113
114 bool G1DirtyCardQueueSet::apply_closure_to_buffer(G1CardTableEntryClosure* cl,
115 BufferNode* node,
116 bool consume,
117 uint worker_i) {
118 if (cl == NULL) return true;
119 bool result = true;
120 void** buf = BufferNode::make_buffer_from_node(node);
121 size_t i = node->index();
122 size_t limit = buffer_size();
123 for ( ; i < limit; ++i) {
124 CardTable::CardValue* card_ptr = static_cast<CardTable::CardValue*>(buf[i]);
125 assert(card_ptr != NULL, "invariant");
126 if (!cl->do_card_ptr(card_ptr, worker_i)) {
127 result = false; // Incomplete processing.
128 break;
129 }
130 }
131 if (consume) {
|
61 // active field set to true.
62 PtrQueue(qset, true /* active */)
63 { }
64
65 G1DirtyCardQueue::~G1DirtyCardQueue() {
66 flush();
67 }
68
69 void G1DirtyCardQueue::handle_completed_buffer() {
70 assert(_buf != NULL, "precondition");
71 BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
72 G1DirtyCardQueueSet* dcqs = dirty_card_qset();
73 if (dcqs->process_or_enqueue_completed_buffer(node)) {
74 reset(); // Buffer fully processed, reset index.
75 } else {
76 allocate_buffer(); // Buffer enqueued, get a new one.
77 }
78 }
79
80 G1DirtyCardQueueSet::G1DirtyCardQueueSet(bool 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),
89 _max_completed_buffers(MaxCompletedBuffersUnlimited),
90 _completed_buffers_padding(0),
91 _free_ids(NULL),
92 _processed_buffers_mut(0),
93 _processed_buffers_rs_thread(0),
94 _cur_par_buffer_node(NULL)
95 {
96 _all_active = true;
97 }
98
99 G1DirtyCardQueueSet::~G1DirtyCardQueueSet() {
100 abandon_completed_buffers();
101 delete _free_ids;
102 }
103
104 // Determines how many mutator threads can process the buffers in parallel.
105 uint G1DirtyCardQueueSet::num_par_ids() {
106 return (uint)os::initial_active_processor_count();
107 }
108
109 void G1DirtyCardQueueSet::initialize(Monitor* cbl_mon,
110 BufferNode::Allocator* allocator,
111 bool init_free_ids) {
112 PtrQueueSet::initialize(allocator);
113 assert(_cbl_mon == NULL, "Init order issue?");
114 _cbl_mon = cbl_mon;
115 if (init_free_ids) {
116 _free_ids = new G1FreeIdSet(0, num_par_ids());
117 }
118 }
119
120 void G1DirtyCardQueueSet::handle_zero_index_for_thread(Thread* t) {
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();
239 }
240
241 bool G1DirtyCardQueueSet::apply_closure_to_buffer(G1CardTableEntryClosure* cl,
242 BufferNode* node,
243 bool consume,
244 uint worker_i) {
245 if (cl == NULL) return true;
246 bool result = true;
247 void** buf = BufferNode::make_buffer_from_node(node);
248 size_t i = node->index();
249 size_t limit = buffer_size();
250 for ( ; i < limit; ++i) {
251 CardTable::CardValue* card_ptr = static_cast<CardTable::CardValue*>(buf[i]);
252 assert(card_ptr != NULL, "invariant");
253 if (!cl->do_card_ptr(card_ptr, worker_i)) {
254 result = false; // Incomplete processing.
255 break;
256 }
257 }
258 if (consume) {
|