1 /*
   2  * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  *
  22  */
  23 
  24 #include "precompiled.hpp"
  25 
  26 #include "gc_implementation/shenandoah/shenandoahSynchronizerIterator.hpp"
  27 #include "runtime/atomic.hpp"
  28 #include "runtime/thread.hpp"
  29 #include "runtime/objectMonitor.hpp"
  30 #include "runtime/objectMonitor.inline.hpp"
  31 #include "runtime/synchronizer.hpp"
  32 #include "runtime/safepoint.hpp"
  33 
  34 #define CHAINMARKER (cast_to_oop<intptr_t>(-1))
  35 
  36 // ParallelObjectSynchronizerIterator implementation
  37 ShenandoahSynchronizerIterator::ShenandoahSynchronizerIterator()
  38   : _cur(ObjectSynchronizer::gBlockList) {
  39   assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint");
  40 }
  41 
  42 // Get the next block in the block list.
  43 static inline ObjectMonitor* next(ObjectMonitor* block) {
  44   assert(block->object() == CHAINMARKER, "must be a block header");
  45   block = block->FreeNext ;
  46   assert(block == NULL || block->object() == CHAINMARKER, "must be a block header");
  47   return block;
  48 }
  49 
  50 ObjectMonitor* ShenandoahSynchronizerIterator::claim() {
  51   ObjectMonitor* my_cur = _cur;
  52 
  53   while (true) {
  54     if (my_cur == NULL) return NULL;
  55     ObjectMonitor* next_block = next(my_cur);
  56     ObjectMonitor* cas_result = (ObjectMonitor*) Atomic::cmpxchg_ptr(next_block, &_cur, my_cur);
  57     if (my_cur == cas_result) {
  58       // We succeeded.
  59       return my_cur;
  60     } else {
  61       // We failed. Retry with offending CAS result.
  62       my_cur = cas_result;
  63     }
  64   }
  65 }
  66 
  67 bool ShenandoahSynchronizerIterator::parallel_oops_do(OopClosure* f) {
  68   ObjectMonitor* block = claim();
  69   if (block != NULL) {
  70     for (int i = 1; i < ObjectSynchronizer::_BLOCKSIZE; i++) {
  71       ObjectMonitor* mid = &block[i];
  72       if (mid->object() != NULL) {
  73         f->do_oop((oop*) mid->object_addr());
  74       }
  75     }
  76     return true;
  77   }
  78   return false;
  79 }