src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp

Sat, 06 Oct 2012 01:17:44 -0700

author
johnc
date
Sat, 06 Oct 2012 01:17:44 -0700
changeset 4173
8a5ea0a9ccc4
parent 3156
f08d439fab8c
child 4299
f34d701e952e
permissions
-rw-r--r--

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 }

mercurial