< prev index next >

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

Print this page

        

@@ -30,10 +30,76 @@
 #include "runtime/atomic.inline.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/thread.inline.hpp"
 
+// Represents a set of free small integer ids.
+class FreeIdSet : public CHeapObj<mtGC> {
+  enum {
+    end_of_list = UINT_MAX,
+    claimed = UINT_MAX - 1
+  };
+
+  uint _size;
+  Monitor* _mon;
+
+  uint* _ids;
+  uint _hd;
+  uint _waiters;
+  uint _claimed;
+
+public:
+  FreeIdSet(uint size, Monitor* mon);
+  ~FreeIdSet();
+
+  // Returns an unclaimed parallel id (waiting for one to be released if
+  // necessary).
+  uint claim_par_id();
+
+  void release_par_id(uint id);
+};
+
+FreeIdSet::FreeIdSet(uint size, Monitor* mon) :
+  _size(size), _mon(mon), _hd(0), _waiters(0), _claimed(0)
+{
+  guarantee(size != 0, "must be");
+  _ids = NEW_C_HEAP_ARRAY(uint, size, mtGC);
+  for (uint i = 0; i < size - 1; i++) {
+    _ids[i] = i+1;
+  }
+  _ids[size-1] = end_of_list; // end of list.
+}
+
+FreeIdSet::~FreeIdSet() {
+  FREE_C_HEAP_ARRAY(uint, _ids);
+}
+
+uint FreeIdSet::claim_par_id() {
+  MutexLockerEx x(_mon, Mutex::_no_safepoint_check_flag);
+  while (_hd == end_of_list) {
+    _waiters++;
+    _mon->wait(Mutex::_no_safepoint_check_flag);
+    _waiters--;
+  }
+  uint res = _hd;
+  _hd = _ids[res];
+  _ids[res] = claimed;  // For debugging.
+  _claimed++;
+  return res;
+}
+
+void FreeIdSet::release_par_id(uint id) {
+  MutexLockerEx x(_mon, Mutex::_no_safepoint_check_flag);
+  assert(_ids[id] == claimed, "Precondition.");
+  _ids[id] = _hd;
+  _hd = id;
+  _claimed--;
+  if (_waiters > 0) {
+    _mon->notify_all();
+  }
+}
+
 DirtyCardQueue::DirtyCardQueue(DirtyCardQueueSet* qset, bool permanent) :
   // Dirty card queues are always active, so we create them with their
   // active field set to true.
   PtrQueue(qset, permanent, true /* active */)
 { }

@@ -101,28 +167,31 @@
                                    Monitor* cbl_mon,
                                    Mutex* fl_lock,
                                    int process_completed_threshold,
                                    int max_completed_queue,
                                    Mutex* lock,
-                                   DirtyCardQueueSet* fl_owner) {
+                                   DirtyCardQueueSet* fl_owner,
+                                   bool init_free_ids) {
   _mut_process_closure = cl;
   PtrQueueSet::initialize(cbl_mon,
                           fl_lock,
                           process_completed_threshold,
                           max_completed_queue,
                           fl_owner);
   set_buffer_size(G1UpdateBufferSize);
   _shared_dirty_card_queue.set_lock(lock);
+  if (init_free_ids) {
   _free_ids = new FreeIdSet(num_par_ids(), _cbl_mon);
+  }
 }
 
 void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) {
   t->dirty_card_queue().handle_zero_index();
 }
 
 bool DirtyCardQueueSet::mut_process_buffer(void** buf) {
-
+  guarantee(_free_ids != NULL, "must be");
   // Used to determine if we had already claimed a par_id
   // before entering this method.
   bool already_claimed = false;
 
   // We grab the current JavaThread.
< prev index next >