1 /*
   2  * Copyright (c) 2013, 2018, 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 #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHCONCURRENTTHREAD_HPP
  25 #define SHARE_VM_GC_SHENANDOAH_SHENANDOAHCONCURRENTTHREAD_HPP
  26 
  27 #include "gc_interface/gcCause.hpp"
  28 #include "gc_implementation/shared/concurrentGCThread.hpp"
  29 #include "gc_implementation/shenandoah/shenandoahHeap.hpp"
  30 #include "gc_implementation/shenandoah/shenandoahPadding.hpp"
  31 #include "gc_implementation/shenandoah/shenandoahSharedVariables.hpp"
  32 #include "runtime/task.hpp"
  33 #include "utilities/ostream.hpp"
  34 
  35 class ShenandoahControlThread;
  36 
  37 // Periodic task is useful for doing asynchronous things that do not require (heap) locks,
  38 // or synchronization with other parts of collector. These could run even when ShenandoahConcurrentThread
  39 // is busy driving the GC cycle.
  40 class ShenandoahPeriodicTask : public PeriodicTask {
  41 private:
  42   ShenandoahControlThread* _thread;
  43 public:
  44   ShenandoahPeriodicTask(ShenandoahControlThread* thread) :
  45           PeriodicTask(100), _thread(thread) {}
  46   virtual void task();
  47 };
  48 
  49 // Periodic task to flush SATB buffers periodically.
  50 class ShenandoahPeriodicSATBFlushTask : public PeriodicTask {
  51 public:
  52   ShenandoahPeriodicSATBFlushTask() : PeriodicTask(ShenandoahSATBBufferFlushInterval) {}
  53   virtual void task();
  54 };
  55 
  56 // Periodic task to notify blocked paced waiters.
  57 class ShenandoahPeriodicPacerNotify : public PeriodicTask {
  58 public:
  59   ShenandoahPeriodicPacerNotify() : PeriodicTask(PeriodicTask::min_interval) {}
  60   virtual void task();
  61 };
  62 
  63 class ShenandoahControlThread: public ConcurrentGCThread {
  64   friend class VMStructs;
  65 
  66 private:
  67   typedef enum {
  68     none,
  69     concurrent_normal,
  70     stw_degenerated,
  71     stw_full
  72   } GCMode;
  73 
  74   // While we could have a single lock for these, it may risk unblocking
  75   // GC waiters when alloc failure GC cycle finishes. We want instead
  76   // to make complete explicit cycle for for demanding customers.
  77   Monitor _alloc_failure_waiters_lock;
  78   Monitor _gc_waiters_lock;
  79   ShenandoahPeriodicTask _periodic_task;
  80   ShenandoahPeriodicSATBFlushTask _periodic_satb_flush_task;
  81   ShenandoahPeriodicPacerNotify _periodic_pacer_notify_task;
  82 
  83  private:
  84   static SurrogateLockerThread* _slt;
  85 
  86 public:
  87   void run();
  88   void stop();
  89 
  90 private:
  91   ShenandoahSharedFlag _gc_requested;
  92   ShenandoahSharedFlag _alloc_failure_gc;
  93   ShenandoahSharedFlag _graceful_shutdown;
  94   ShenandoahSharedFlag _heap_changed;
  95   ShenandoahSharedFlag _do_counters_update;
  96   ShenandoahSharedFlag _force_counters_update;
  97   GCCause::Cause       _requested_gc_cause;
  98   ShenandoahHeap::ShenandoahDegenPoint _degen_point;
  99 
 100   shenandoah_padding(0);
 101   volatile intptr_t _allocs_seen;
 102   shenandoah_padding(1);
 103   volatile intptr_t _gc_id;
 104   shenandoah_padding(2);
 105 
 106   bool check_cancellation_or_degen(ShenandoahHeap::ShenandoahDegenPoint point);
 107   void service_concurrent_normal_cycle(GCCause::Cause cause);
 108   void service_stw_full_cycle(GCCause::Cause cause);
 109   void service_stw_degenerated_cycle(GCCause::Cause cause, ShenandoahHeap::ShenandoahDegenPoint point);
 110   void service_uncommit(double shrink_before, size_t shrink_until);
 111 
 112   bool try_set_alloc_failure_gc();
 113   void notify_alloc_failure_waiters();
 114   bool is_alloc_failure_gc();
 115 
 116   void reset_gc_id();
 117   void update_gc_id();
 118   size_t get_gc_id();
 119 
 120   void notify_gc_waiters();
 121 
 122   // Handle GC request.
 123   // Blocks until GC is over.
 124   void handle_requested_gc(GCCause::Cause cause);
 125 
 126   bool is_explicit_gc(GCCause::Cause cause) const;
 127 
 128   bool check_soft_max_changed() const;
 129 
 130 public:
 131   // Constructor
 132   ShenandoahControlThread();
 133   ~ShenandoahControlThread();
 134 
 135   static void makeSurrogateLockerThread(TRAPS);
 136   static SurrogateLockerThread* slt() { return _slt; }
 137 
 138   // Handle allocation failure from normal allocation.
 139   // Blocks until memory is available.
 140   void handle_alloc_failure(ShenandoahAllocRequest& req);
 141 
 142   // Handle allocation failure from evacuation path.
 143   // Optionally blocks while collector is handling the failure.
 144   void handle_alloc_failure_evac(size_t words);
 145 
 146   void request_gc(GCCause::Cause cause);
 147 
 148   void handle_counters_update();
 149   void handle_force_counters_update();
 150   void set_forced_counters_update(bool value);
 151 
 152   void notify_heap_changed();
 153 
 154   void pacing_notify_alloc(size_t words);
 155 
 156   void start();
 157   void prepare_for_graceful_shutdown();
 158   bool in_graceful_shutdown();
 159 
 160   char* name() const { return (char*)"ShenandoahConcurrentThread";}
 161 
 162   // Printing
 163   void print_on(outputStream* st) const;
 164   void print() const;
 165 
 166 };
 167 
 168 #endif // SHARE_VM_GC_SHENANDOAH_SHENANDOAHCONCURRENTTHREAD_HPP