< prev index next >

src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp

Print this page
rev 55389 : [mq]: satb_lock_free


  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) {


< prev index next >