< prev index next >

src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp

Print this page
*** 28,34 ***
  #include "gc/shenandoah/shenandoahConcurrentGC.hpp"
  #include "gc/shenandoah/shenandoahControlThread.hpp"
  #include "gc/shenandoah/shenandoahDegeneratedGC.hpp"
  #include "gc/shenandoah/shenandoahFreeSet.hpp"
  #include "gc/shenandoah/shenandoahFullGC.hpp"
  #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  #include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
  #include "gc/shenandoah/shenandoahPacer.inline.hpp"
  #include "gc/shenandoah/shenandoahUtils.hpp"
  #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
  #include "memory/metaspaceUtils.hpp"
  #include "memory/metaspaceStats.hpp"
- #include "memory/resourceArea.hpp"
- #include "runtime/atomic.hpp"
  
  ShenandoahControlThread::ShenandoahControlThread() :
!   ConcurrentGCThread(),
-   _alloc_failure_waiters_lock(Mutex::safepoint-2, "ShenandoahAllocFailureGC_lock", true),
-   _gc_waiters_lock(Mutex::safepoint-2, "ShenandoahRequestedGC_lock", true),
    _requested_gc_cause(GCCause::_no_cause_specified),
!   _degen_point(ShenandoahGC::_degenerated_outside_cycle),
-   _allocs_seen(0) {
    set_name("Shenandoah Control Thread");
-   reset_gc_id();
    create_and_start();
  }
  
  void ShenandoahControlThread::run_service() {
!   ShenandoahHeap* heap = ShenandoahHeap::heap();
  
    const GCMode default_mode = concurrent_normal;
    const GCCause::Cause default_cause = GCCause::_shenandoah_concurrent_gc;
    int sleep = ShenandoahControlIntervalMin;
  
--- 28,31 ---
  #include "gc/shenandoah/shenandoahConcurrentGC.hpp"
  #include "gc/shenandoah/shenandoahControlThread.hpp"
  #include "gc/shenandoah/shenandoahDegeneratedGC.hpp"
  #include "gc/shenandoah/shenandoahFreeSet.hpp"
  #include "gc/shenandoah/shenandoahFullGC.hpp"
+ #include "gc/shenandoah/shenandoahGeneration.hpp"
  #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  #include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
  #include "gc/shenandoah/shenandoahPacer.inline.hpp"
  #include "gc/shenandoah/shenandoahUtils.hpp"
  #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
+ #include "gc/shenandoah/mode/shenandoahMode.hpp"
+ #include "logging/log.hpp"
  #include "memory/metaspaceUtils.hpp"
  #include "memory/metaspaceStats.hpp"
  
  ShenandoahControlThread::ShenandoahControlThread() :
!   ShenandoahController(),
    _requested_gc_cause(GCCause::_no_cause_specified),
!   _degen_point(ShenandoahGC::_degenerated_outside_cycle) {
    set_name("Shenandoah Control Thread");
    create_and_start();
  }
  
  void ShenandoahControlThread::run_service() {
!   ShenandoahHeap* const heap = ShenandoahHeap::heap();
  
    const GCMode default_mode = concurrent_normal;
    const GCCause::Cause default_cause = GCCause::_shenandoah_concurrent_gc;
    int sleep = ShenandoahControlIntervalMin;
  

*** 75,11 ***
      const bool alloc_failure_pending = _alloc_failure_gc.is_set();
      const bool is_gc_requested = _gc_requested.is_set();
      const GCCause::Cause requested_gc_cause = _requested_gc_cause;
  
      // This control loop iteration has seen this much allocation.
!     const size_t allocs_seen = Atomic::xchg(&_allocs_seen, (size_t)0, memory_order_relaxed);
  
      // Check if we have seen a new target for soft max heap size.
      const bool soft_max_changed = heap->check_soft_max_changed();
  
      // Choose which GC mode to run in. The block below should select a single mode.
--- 72,11 ---
      const bool alloc_failure_pending = _alloc_failure_gc.is_set();
      const bool is_gc_requested = _gc_requested.is_set();
      const GCCause::Cause requested_gc_cause = _requested_gc_cause;
  
      // This control loop iteration has seen this much allocation.
!     const size_t allocs_seen = reset_allocs_seen();
  
      // Check if we have seen a new target for soft max heap size.
      const bool soft_max_changed = heap->check_soft_max_changed();
  
      // Choose which GC mode to run in. The block below should select a single mode.

*** 104,11 ***
        } else {
          heuristics->record_allocation_failure_gc();
          policy->record_alloc_failure_to_full();
          mode = stw_full;
        }
- 
      } else if (is_gc_requested) {
        cause = requested_gc_cause;
        log_info(gc)("Trigger: GC request (%s)", GCCause::to_string(cause));
        heuristics->record_requested_gc();
  
--- 101,10 ---

*** 237,11 ***
        // GC is over, we are at idle now
        if (ShenandoahPacing) {
          heap->pacer()->setup_for_idle();
        }
      } else {
!       // Allow allocators to know we have seen this much regions
        if (ShenandoahPacing && (allocs_seen > 0)) {
          heap->pacer()->report_alloc(allocs_seen);
        }
      }
  
--- 233,11 ---
        // GC is over, we are at idle now
        if (ShenandoahPacing) {
          heap->pacer()->setup_for_idle();
        }
      } else {
!       // Report to pacer that we have seen this many words allocated
        if (ShenandoahPacing && (allocs_seen > 0)) {
          heap->pacer()->report_alloc(allocs_seen);
        }
      }
  

*** 321,22 ***
    //
    ShenandoahHeap* heap = ShenandoahHeap::heap();
    if (check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle)) return;
  
    GCIdMark gc_id_mark;
!   ShenandoahGCSession session(cause);
  
    TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
  
!   ShenandoahConcurrentGC gc;
    if (gc.collect(cause)) {
      // Cycle is complete
!     heap->heuristics()->record_success_concurrent();
!     heap->shenandoah_policy()->record_success_concurrent(gc.abbreviated());
    } else {
      assert(heap->cancelled_gc(), "Must have been cancelled");
      check_cancellation_or_degen(gc.degen_point());
    }
  }
  
  bool ShenandoahControlThread::check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point) {
    ShenandoahHeap* heap = ShenandoahHeap::heap();
--- 317,24 ---
    //
    ShenandoahHeap* heap = ShenandoahHeap::heap();
    if (check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle)) return;
  
    GCIdMark gc_id_mark;
!   ShenandoahGCSession session(cause, heap->global_generation());
  
    TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
  
!   ShenandoahConcurrentGC gc(heap->global_generation(), false);
    if (gc.collect(cause)) {
      // Cycle is complete
!     heap->global_generation()->heuristics()->record_success_concurrent(gc.abbreviated());
!     heap->shenandoah_policy()->record_success_concurrent(false, gc.abbreviated());
+     heap->log_heap_status("At end of GC");
    } else {
      assert(heap->cancelled_gc(), "Must have been cancelled");
      check_cancellation_or_degen(gc.degen_point());
+     heap->log_heap_status("At end of cancelled GC");
    }
  }
  
  bool ShenandoahControlThread::check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point) {
    ShenandoahHeap* heap = ShenandoahHeap::heap();

*** 355,24 ***
  void ShenandoahControlThread::stop_service() {
    // Nothing to do here.
  }
  
  void ShenandoahControlThread::service_stw_full_cycle(GCCause::Cause cause) {
    GCIdMark gc_id_mark;
!   ShenandoahGCSession session(cause);
  
    ShenandoahFullGC gc;
    gc.collect(cause);
  }
  
  void ShenandoahControlThread::service_stw_degenerated_cycle(GCCause::Cause cause, ShenandoahGC::ShenandoahDegenPoint point) {
    assert (point != ShenandoahGC::_degenerated_unset, "Degenerated point should be set");
! 
    GCIdMark gc_id_mark;
!   ShenandoahGCSession session(cause);
  
!   ShenandoahDegenGC gc(point);
    gc.collect(cause);
  }
  
  void ShenandoahControlThread::request_gc(GCCause::Cause cause) {
    if (ShenandoahCollectorPolicy::should_handle_requested_gc(cause)) {
--- 353,25 ---
  void ShenandoahControlThread::stop_service() {
    // Nothing to do here.
  }
  
  void ShenandoahControlThread::service_stw_full_cycle(GCCause::Cause cause) {
+   ShenandoahHeap* const heap = ShenandoahHeap::heap();
    GCIdMark gc_id_mark;
!   ShenandoahGCSession session(cause, heap->global_generation());
  
    ShenandoahFullGC gc;
    gc.collect(cause);
  }
  
  void ShenandoahControlThread::service_stw_degenerated_cycle(GCCause::Cause cause, ShenandoahGC::ShenandoahDegenPoint point) {
    assert (point != ShenandoahGC::_degenerated_unset, "Degenerated point should be set");
!   ShenandoahHeap* const heap = ShenandoahHeap::heap();
    GCIdMark gc_id_mark;
!   ShenandoahGCSession session(cause, heap->global_generation());
  
!   ShenandoahDegenGC gc(point, heap->global_generation());
    gc.collect(cause);
  }
  
  void ShenandoahControlThread::request_gc(GCCause::Cause cause) {
    if (ShenandoahCollectorPolicy::should_handle_requested_gc(cause)) {

*** 405,90 ***
      }
      current_gc_id = get_gc_id();
    }
  }
  
- void ShenandoahControlThread::handle_alloc_failure(ShenandoahAllocRequest& req, bool block) {
-   ShenandoahHeap* heap = ShenandoahHeap::heap();
- 
-   assert(current()->is_Java_thread(), "expect Java thread here");
- 
-   if (try_set_alloc_failure_gc()) {
-     // Only report the first allocation failure
-     log_info(gc)("Failed to allocate %s, " SIZE_FORMAT "%s",
-                  req.type_string(),
-                  byte_size_in_proper_unit(req.size() * HeapWordSize), proper_unit_for_byte_size(req.size() * HeapWordSize));
- 
-     // Now that alloc failure GC is scheduled, we can abort everything else
-     heap->cancel_gc(GCCause::_allocation_failure);
-   }
- 
- 
-   if (block) {
-     MonitorLocker ml(&_alloc_failure_waiters_lock);
-     while (is_alloc_failure_gc()) {
-       ml.wait();
-     }
-   }
- }
- 
- void ShenandoahControlThread::handle_alloc_failure_evac(size_t words) {
-   ShenandoahHeap* heap = ShenandoahHeap::heap();
- 
-   if (try_set_alloc_failure_gc()) {
-     // Only report the first allocation failure
-     log_info(gc)("Failed to allocate " SIZE_FORMAT "%s for evacuation",
-                  byte_size_in_proper_unit(words * HeapWordSize), proper_unit_for_byte_size(words * HeapWordSize));
-   }
- 
-   // Forcefully report allocation failure
-   heap->cancel_gc(GCCause::_shenandoah_allocation_failure_evac);
- }
- 
- void ShenandoahControlThread::notify_alloc_failure_waiters() {
-   _alloc_failure_gc.unset();
-   MonitorLocker ml(&_alloc_failure_waiters_lock);
-   ml.notify_all();
- }
- 
- bool ShenandoahControlThread::try_set_alloc_failure_gc() {
-   return _alloc_failure_gc.try_set();
- }
- 
- bool ShenandoahControlThread::is_alloc_failure_gc() {
-   return _alloc_failure_gc.is_set();
- }
- 
  void ShenandoahControlThread::notify_gc_waiters() {
    _gc_requested.unset();
    MonitorLocker ml(&_gc_waiters_lock);
    ml.notify_all();
  }
- 
- void ShenandoahControlThread::pacing_notify_alloc(size_t words) {
-   assert(ShenandoahPacing, "should only call when pacing is enabled");
-   Atomic::add(&_allocs_seen, words, memory_order_relaxed);
- }
- 
- void ShenandoahControlThread::reset_gc_id() {
-   Atomic::store(&_gc_id, (size_t)0);
- }
- 
- void ShenandoahControlThread::update_gc_id() {
-   Atomic::inc(&_gc_id);
- }
- 
- size_t ShenandoahControlThread::get_gc_id() {
-   return Atomic::load(&_gc_id);
- }
- 
- void ShenandoahControlThread::start() {
-   create_and_start();
- }
- 
- void ShenandoahControlThread::prepare_for_graceful_shutdown() {
-   _graceful_shutdown.set();
- }
- 
- bool ShenandoahControlThread::in_graceful_shutdown() {
-   return _graceful_shutdown.is_set();
- }
--- 404,10 ---
< prev index next >