src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp
changeset 55498 e64383344f14
parent 54970 76d3d96a8bc2
child 55752 8ae33203d600
equal deleted inserted replaced
55497:d3a33953b936 55498:e64383344f14
    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),
    88 {
    95 {
    89   _all_active = true;
    96   _all_active = true;
    90 }
    97 }
    91 
    98 
    92 G1DirtyCardQueueSet::~G1DirtyCardQueueSet() {
    99 G1DirtyCardQueueSet::~G1DirtyCardQueueSet() {
       
   100   abandon_completed_buffers();
    93   delete _free_ids;
   101   delete _free_ids;
    94 }
   102 }
    95 
   103 
    96 // Determines how many mutator threads can process the buffers in parallel.
   104 // Determines how many mutator threads can process the buffers in parallel.
    97 uint G1DirtyCardQueueSet::num_par_ids() {
   105 uint G1DirtyCardQueueSet::num_par_ids() {
    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,