Sat, 06 Oct 2012 01:17:44 -0700
7127708: G1: change task num types from int to uint in concurrent mark
Summary: Change the type of various task num fields, parameters etc to unsigned and rename them to be more consistent with the other collectors. Code changes were also reviewed by Vitaly Davidovich.
Reviewed-by: johnc
Contributed-by: Kaushik Srenevasan <kaushik@twitter.com>
1 /*
2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
25 #include "precompiled.hpp"
26 #include "gc_implementation/g1/dirtyCardQueue.hpp"
27 #include "gc_implementation/g1/heapRegionRemSet.hpp"
28 #include "runtime/atomic.hpp"
29 #include "runtime/mutexLocker.hpp"
30 #include "runtime/safepoint.hpp"
31 #include "runtime/thread.hpp"
32 #include "utilities/workgroup.hpp"
33 #ifdef TARGET_OS_FAMILY_linux
34 # include "thread_linux.inline.hpp"
35 #endif
36 #ifdef TARGET_OS_FAMILY_solaris
37 # include "thread_solaris.inline.hpp"
38 #endif
39 #ifdef TARGET_OS_FAMILY_windows
40 # include "thread_windows.inline.hpp"
41 #endif
42 #ifdef TARGET_OS_FAMILY_bsd
43 # include "thread_bsd.inline.hpp"
44 #endif
46 bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl,
47 bool consume,
48 size_t worker_i) {
49 bool res = true;
50 if (_buf != NULL) {
51 res = apply_closure_to_buffer(cl, _buf, _index, _sz,
52 consume,
53 (int) worker_i);
54 if (res && consume) _index = _sz;
55 }
56 return res;
57 }
59 bool DirtyCardQueue::apply_closure_to_buffer(CardTableEntryClosure* cl,
60 void** buf,
61 size_t index, size_t sz,
62 bool consume,
63 int worker_i) {
64 if (cl == NULL) return true;
65 for (size_t i = index; i < sz; i += oopSize) {
66 int ind = byte_index_to_index((int)i);
67 jbyte* card_ptr = (jbyte*)buf[ind];
68 if (card_ptr != NULL) {
69 // Set the entry to null, so we don't do it again (via the test
70 // above) if we reconsider this buffer.
71 if (consume) buf[ind] = NULL;
72 if (!cl->do_card_ptr(card_ptr, worker_i)) return false;
73 }
74 }
75 return true;
76 }
78 #ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away
79 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list
80 #endif // _MSC_VER
82 DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) :
83 PtrQueueSet(notify_when_complete),
84 _closure(NULL),
85 _shared_dirty_card_queue(this, true /*perm*/),
86 _free_ids(NULL),
87 _processed_buffers_mut(0), _processed_buffers_rs_thread(0)
88 {
89 _all_active = true;
90 }
92 // Determines how many mutator threads can process the buffers in parallel.
93 size_t DirtyCardQueueSet::num_par_ids() {
94 return os::processor_count();
95 }
97 void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock,
98 int process_completed_threshold,
99 int max_completed_queue,
100 Mutex* lock, PtrQueueSet* fl_owner) {
101 PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold,
102 max_completed_queue, fl_owner);
103 set_buffer_size(G1UpdateBufferSize);
104 _shared_dirty_card_queue.set_lock(lock);
105 _free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon);
106 }
108 void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) {
109 t->dirty_card_queue().handle_zero_index();
110 }
112 void DirtyCardQueueSet::set_closure(CardTableEntryClosure* closure) {
113 _closure = closure;
114 }
116 void DirtyCardQueueSet::iterate_closure_all_threads(bool consume,
117 size_t worker_i) {
118 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
119 for(JavaThread* t = Threads::first(); t; t = t->next()) {
120 bool b = t->dirty_card_queue().apply_closure(_closure, consume);
121 guarantee(b, "Should not be interrupted.");
122 }
123 bool b = shared_dirty_card_queue()->apply_closure(_closure,
124 consume,
125 worker_i);
126 guarantee(b, "Should not be interrupted.");
127 }
129 bool DirtyCardQueueSet::mut_process_buffer(void** buf) {
131 // Used to determine if we had already claimed a par_id
132 // before entering this method.
133 bool already_claimed = false;
135 // We grab the current JavaThread.
136 JavaThread* thread = JavaThread::current();
138 // We get the the number of any par_id that this thread
139 // might have already claimed.
140 int worker_i = thread->get_claimed_par_id();
142 // If worker_i is not -1 then the thread has already claimed
143 // a par_id. We make note of it using the already_claimed value
144 if (worker_i != -1) {
145 already_claimed = true;
146 } else {
148 // Otherwise we need to claim a par id
149 worker_i = _free_ids->claim_par_id();
151 // And store the par_id value in the thread
152 thread->set_claimed_par_id(worker_i);
153 }
155 bool b = false;
156 if (worker_i != -1) {
157 b = DirtyCardQueue::apply_closure_to_buffer(_closure, buf, 0,
158 _sz, true, worker_i);
159 if (b) Atomic::inc(&_processed_buffers_mut);
161 // If we had not claimed an id before entering the method
162 // then we must release the id.
163 if (!already_claimed) {
165 // we release the id
166 _free_ids->release_par_id(worker_i);
168 // and set the claimed_id in the thread to -1
169 thread->set_claimed_par_id(-1);
170 }
171 }
172 return b;
173 }
176 BufferNode*
177 DirtyCardQueueSet::get_completed_buffer(int stop_at) {
178 BufferNode* nd = NULL;
179 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
181 if ((int)_n_completed_buffers <= stop_at) {
182 _process_completed = false;
183 return NULL;
184 }
186 if (_completed_buffers_head != NULL) {
187 nd = _completed_buffers_head;
188 _completed_buffers_head = nd->next();
189 if (_completed_buffers_head == NULL)
190 _completed_buffers_tail = NULL;
191 _n_completed_buffers--;
192 assert(_n_completed_buffers >= 0, "Invariant");
193 }
194 debug_only(assert_completed_buffer_list_len_correct_locked());
195 return nd;
196 }
198 bool DirtyCardQueueSet::
199 apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
200 int worker_i,
201 BufferNode* nd) {
202 if (nd != NULL) {
203 void **buf = BufferNode::make_buffer_from_node(nd);
204 size_t index = nd->index();
205 bool b =
206 DirtyCardQueue::apply_closure_to_buffer(cl, buf,
207 index, _sz,
208 true, worker_i);
209 if (b) {
210 deallocate_buffer(buf);
211 return true; // In normal case, go on to next buffer.
212 } else {
213 enqueue_complete_buffer(buf, index);
214 return false;
215 }
216 } else {
217 return false;
218 }
219 }
221 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
222 int worker_i,
223 int stop_at,
224 bool during_pause) {
225 assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause");
226 BufferNode* nd = get_completed_buffer(stop_at);
227 bool res = apply_closure_to_completed_buffer_helper(cl, worker_i, nd);
228 if (res) Atomic::inc(&_processed_buffers_rs_thread);
229 return res;
230 }
232 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i,
233 int stop_at,
234 bool during_pause) {
235 return apply_closure_to_completed_buffer(_closure, worker_i,
236 stop_at, during_pause);
237 }
239 void DirtyCardQueueSet::apply_closure_to_all_completed_buffers() {
240 BufferNode* nd = _completed_buffers_head;
241 while (nd != NULL) {
242 bool b =
243 DirtyCardQueue::apply_closure_to_buffer(_closure,
244 BufferNode::make_buffer_from_node(nd),
245 0, _sz, false);
246 guarantee(b, "Should not stop early.");
247 nd = nd->next();
248 }
249 }
251 // Deallocates any completed log buffers
252 void DirtyCardQueueSet::clear() {
253 BufferNode* buffers_to_delete = NULL;
254 {
255 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
256 while (_completed_buffers_head != NULL) {
257 BufferNode* nd = _completed_buffers_head;
258 _completed_buffers_head = nd->next();
259 nd->set_next(buffers_to_delete);
260 buffers_to_delete = nd;
261 }
262 _n_completed_buffers = 0;
263 _completed_buffers_tail = NULL;
264 debug_only(assert_completed_buffer_list_len_correct_locked());
265 }
266 while (buffers_to_delete != NULL) {
267 BufferNode* nd = buffers_to_delete;
268 buffers_to_delete = nd->next();
269 deallocate_buffer(BufferNode::make_buffer_from_node(nd));
270 }
272 }
274 void DirtyCardQueueSet::abandon_logs() {
275 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
276 clear();
277 // Since abandon is done only at safepoints, we can safely manipulate
278 // these queues.
279 for (JavaThread* t = Threads::first(); t; t = t->next()) {
280 t->dirty_card_queue().reset();
281 }
282 shared_dirty_card_queue()->reset();
283 }
286 void DirtyCardQueueSet::concatenate_logs() {
287 // Iterate over all the threads, if we find a partial log add it to
288 // the global list of logs. Temporarily turn off the limit on the number
289 // of outstanding buffers.
290 int save_max_completed_queue = _max_completed_queue;
291 _max_completed_queue = max_jint;
292 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
293 for (JavaThread* t = Threads::first(); t; t = t->next()) {
294 DirtyCardQueue& dcq = t->dirty_card_queue();
295 if (dcq.size() != 0) {
296 void **buf = t->dirty_card_queue().get_buf();
297 // We must NULL out the unused entries, then enqueue.
298 for (size_t i = 0; i < t->dirty_card_queue().get_index(); i += oopSize) {
299 buf[PtrQueue::byte_index_to_index((int)i)] = NULL;
300 }
301 enqueue_complete_buffer(dcq.get_buf(), dcq.get_index());
302 dcq.reinitialize();
303 }
304 }
305 if (_shared_dirty_card_queue.size() != 0) {
306 enqueue_complete_buffer(_shared_dirty_card_queue.get_buf(),
307 _shared_dirty_card_queue.get_index());
308 _shared_dirty_card_queue.reinitialize();
309 }
310 // Restore the completed buffer queue limit.
311 _max_completed_queue = save_max_completed_queue;
312 }