< prev index next >

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

Print this page

 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  *
 24  */
 25 
 26 #include "precompiled.hpp"
 27 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
 28 #include "gc/shenandoah/shenandoahConcurrentGC.hpp"
 29 #include "gc/shenandoah/shenandoahControlThread.hpp"
 30 #include "gc/shenandoah/shenandoahDegeneratedGC.hpp"
 31 #include "gc/shenandoah/shenandoahFreeSet.hpp"
 32 #include "gc/shenandoah/shenandoahFullGC.hpp"

 33 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
 34 #include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
 35 #include "gc/shenandoah/shenandoahPacer.inline.hpp"
 36 #include "gc/shenandoah/shenandoahUtils.hpp"
 37 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
 38 #include "gc/shenandoah/mode/shenandoahMode.hpp"
 39 #include "logging/log.hpp"
 40 #include "memory/metaspaceUtils.hpp"
 41 #include "memory/metaspaceStats.hpp"
 42 
 43 ShenandoahControlThread::ShenandoahControlThread() :
 44   ShenandoahController(),
 45   _requested_gc_cause(GCCause::_no_cause_specified),
 46   _degen_point(ShenandoahGC::_degenerated_outside_cycle) {
 47   set_name("Shenandoah Control Thread");
 48   create_and_start();
 49 }
 50 
 51 void ShenandoahControlThread::run_service() {
 52   ShenandoahHeap* const heap = ShenandoahHeap::heap();

 68   ShenandoahHeuristics* const heuristics = heap->heuristics();
 69   while (!in_graceful_shutdown() && !should_terminate()) {
 70     // Figure out if we have pending requests.
 71     const bool alloc_failure_pending = _alloc_failure_gc.is_set();
 72     const bool is_gc_requested = _gc_requested.is_set();
 73     const GCCause::Cause requested_gc_cause = _requested_gc_cause;
 74 
 75     // This control loop iteration has seen this much allocation.
 76     const size_t allocs_seen = reset_allocs_seen();
 77 
 78     // Check if we have seen a new target for soft max heap size.
 79     const bool soft_max_changed = heap->check_soft_max_changed();
 80 
 81     // Choose which GC mode to run in. The block below should select a single mode.
 82     GCMode mode = none;
 83     GCCause::Cause cause = GCCause::_last_gc_cause;
 84     ShenandoahGC::ShenandoahDegenPoint degen_point = ShenandoahGC::_degenerated_unset;
 85 
 86     if (alloc_failure_pending) {
 87       // Allocation failure takes precedence: we have to deal with it first thing
 88       log_info(gc)("Trigger: Handle Allocation Failure");
 89 
 90       cause = GCCause::_allocation_failure;
 91 
 92       // Consume the degen point, and seed it with default value
 93       degen_point = _degen_point;
 94       _degen_point = ShenandoahGC::_degenerated_outside_cycle;
 95 
 96       if (ShenandoahDegeneratedGC && heuristics->should_degenerate_cycle()) {
 97         heuristics->record_allocation_failure_gc();
 98         policy->record_alloc_failure_to_degenerated(degen_point);
 99         mode = stw_degenerated;
100       } else {
101         heuristics->record_allocation_failure_gc();
102         policy->record_alloc_failure_to_full();
103         mode = stw_full;
104       }
105     } else if (is_gc_requested) {
106       cause = requested_gc_cause;
107       log_info(gc)("Trigger: GC request (%s)", GCCause::to_string(cause));
108       heuristics->record_requested_gc();
109 
110       if (ShenandoahCollectorPolicy::should_run_full_gc(cause)) {
111         mode = stw_full;
112       } else {
113         mode = default_mode;
114         // Unload and clean up everything
115         heap->set_unload_classes(heuristics->can_unload_classes());
116       }
117     } else {
118       // Potential normal cycle: ask heuristics if it wants to act
119       if (heuristics->should_start_gc()) {
120         mode = default_mode;
121         cause = default_cause;
122       }
123 
124       // Ask policy if this cycle wants to process references or unload classes
125       heap->set_unload_classes(heuristics->should_unload_classes());
126     }
127 

298   //                   | (af)               | (af)            | (af)         |
299   // ..................|....................|.................|..............|.......................
300   //                   |                    |                 |              |
301   //                   |                    |                 |              |      Degenerated GC
302   //                   v                    v                 v              |
303   //               STW Mark ----------> STW Evac ----> STW Update-Refs ----->o
304   //                   |                    |                 |              ^
305   //                   | (af)               | (af)            | (af)         |
306   // ..................|....................|.................|..............|.......................
307   //                   |                    |                 |              |
308   //                   |                    v                 |              |      Full GC
309   //                   \------------------->o<----------------/              |
310   //                                        |                                |
311   //                                        v                                |
312   //                                      Full GC  --------------------------/
313   //
314   ShenandoahHeap* heap = ShenandoahHeap::heap();
315   if (check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle)) return;
316 
317   GCIdMark gc_id_mark;
318   ShenandoahGCSession session(cause);
319 
320   TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
321 
322   ShenandoahConcurrentGC gc;
323   if (gc.collect(cause)) {
324     // Cycle is complete.  There were no failed allocation requests and no degeneration, so count this as good progress.
325     heap->notify_gc_progress();
326     heap->heuristics()->record_success_concurrent();
327     heap->shenandoah_policy()->record_success_concurrent(gc.abbreviated());

328   } else {
329     assert(heap->cancelled_gc(), "Must have been cancelled");
330     check_cancellation_or_degen(gc.degen_point());

331   }
332 }
333 
334 bool ShenandoahControlThread::check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point) {
335   ShenandoahHeap* heap = ShenandoahHeap::heap();
336   if (heap->cancelled_gc()) {
337     assert (is_alloc_failure_gc() || in_graceful_shutdown(), "Cancel GC either for alloc failure GC, or gracefully exiting");
338     if (!in_graceful_shutdown()) {
339       assert (_degen_point == ShenandoahGC::_degenerated_outside_cycle,
340               "Should not be set yet: %s", ShenandoahGC::degen_point_to_string(_degen_point));
341       _degen_point = point;
342     }
343     return true;
344   }
345   return false;
346 }
347 
348 void ShenandoahControlThread::stop_service() {
349   // Nothing to do here.
350 }
351 
352 void ShenandoahControlThread::service_stw_full_cycle(GCCause::Cause cause) {

353   GCIdMark gc_id_mark;
354   ShenandoahGCSession session(cause);
355 
356   ShenandoahFullGC gc;
357   gc.collect(cause);
358 }
359 
360 void ShenandoahControlThread::service_stw_degenerated_cycle(GCCause::Cause cause, ShenandoahGC::ShenandoahDegenPoint point) {
361   assert (point != ShenandoahGC::_degenerated_unset, "Degenerated point should be set");
362 
363   GCIdMark gc_id_mark;
364   ShenandoahGCSession session(cause);
365 
366   ShenandoahDegenGC gc(point);
367   gc.collect(cause);
368 }
369 
370 void ShenandoahControlThread::request_gc(GCCause::Cause cause) {
371   if (ShenandoahCollectorPolicy::should_handle_requested_gc(cause)) {
372     handle_requested_gc(cause);
373   }
374 }
375 
376 void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
377   // For normal requested GCs (System.gc) we want to block the caller. However,
378   // for whitebox requested GC, we want to initiate the GC and return immediately.
379   // The whitebox caller thread will arrange for itself to wait until the GC notifies
380   // it that has reached the requested breakpoint (phase in the GC).
381   if (cause == GCCause::_wb_breakpoint) {
382     _requested_gc_cause = cause;
383     _gc_requested.set();
384     return;
385   }
386 

 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  *
 24  */
 25 
 26 #include "precompiled.hpp"
 27 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
 28 #include "gc/shenandoah/shenandoahConcurrentGC.hpp"
 29 #include "gc/shenandoah/shenandoahControlThread.hpp"
 30 #include "gc/shenandoah/shenandoahDegeneratedGC.hpp"
 31 #include "gc/shenandoah/shenandoahFreeSet.hpp"
 32 #include "gc/shenandoah/shenandoahFullGC.hpp"
 33 #include "gc/shenandoah/shenandoahGeneration.hpp"
 34 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
 35 #include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
 36 #include "gc/shenandoah/shenandoahPacer.inline.hpp"
 37 #include "gc/shenandoah/shenandoahUtils.hpp"
 38 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
 39 #include "gc/shenandoah/mode/shenandoahMode.hpp"
 40 #include "logging/log.hpp"
 41 #include "memory/metaspaceUtils.hpp"
 42 #include "memory/metaspaceStats.hpp"
 43 
 44 ShenandoahControlThread::ShenandoahControlThread() :
 45   ShenandoahController(),
 46   _requested_gc_cause(GCCause::_no_cause_specified),
 47   _degen_point(ShenandoahGC::_degenerated_outside_cycle) {
 48   set_name("Shenandoah Control Thread");
 49   create_and_start();
 50 }
 51 
 52 void ShenandoahControlThread::run_service() {
 53   ShenandoahHeap* const heap = ShenandoahHeap::heap();

 69   ShenandoahHeuristics* const heuristics = heap->heuristics();
 70   while (!in_graceful_shutdown() && !should_terminate()) {
 71     // Figure out if we have pending requests.
 72     const bool alloc_failure_pending = _alloc_failure_gc.is_set();
 73     const bool is_gc_requested = _gc_requested.is_set();
 74     const GCCause::Cause requested_gc_cause = _requested_gc_cause;
 75 
 76     // This control loop iteration has seen this much allocation.
 77     const size_t allocs_seen = reset_allocs_seen();
 78 
 79     // Check if we have seen a new target for soft max heap size.
 80     const bool soft_max_changed = heap->check_soft_max_changed();
 81 
 82     // Choose which GC mode to run in. The block below should select a single mode.
 83     GCMode mode = none;
 84     GCCause::Cause cause = GCCause::_last_gc_cause;
 85     ShenandoahGC::ShenandoahDegenPoint degen_point = ShenandoahGC::_degenerated_unset;
 86 
 87     if (alloc_failure_pending) {
 88       // Allocation failure takes precedence: we have to deal with it first thing
 89       heuristics->log_trigger("Handle Allocation Failure");
 90 
 91       cause = GCCause::_allocation_failure;
 92 
 93       // Consume the degen point, and seed it with default value
 94       degen_point = _degen_point;
 95       _degen_point = ShenandoahGC::_degenerated_outside_cycle;
 96 
 97       if (ShenandoahDegeneratedGC && heuristics->should_degenerate_cycle()) {
 98         heuristics->record_allocation_failure_gc();
 99         policy->record_alloc_failure_to_degenerated(degen_point);
100         mode = stw_degenerated;
101       } else {
102         heuristics->record_allocation_failure_gc();
103         policy->record_alloc_failure_to_full();
104         mode = stw_full;
105       }
106     } else if (is_gc_requested) {
107       cause = requested_gc_cause;
108       heuristics->log_trigger("GC request (%s)", GCCause::to_string(cause));
109       heuristics->record_requested_gc();
110 
111       if (ShenandoahCollectorPolicy::should_run_full_gc(cause)) {
112         mode = stw_full;
113       } else {
114         mode = default_mode;
115         // Unload and clean up everything
116         heap->set_unload_classes(heuristics->can_unload_classes());
117       }
118     } else {
119       // Potential normal cycle: ask heuristics if it wants to act
120       if (heuristics->should_start_gc()) {
121         mode = default_mode;
122         cause = default_cause;
123       }
124 
125       // Ask policy if this cycle wants to process references or unload classes
126       heap->set_unload_classes(heuristics->should_unload_classes());
127     }
128 

299   //                   | (af)               | (af)            | (af)         |
300   // ..................|....................|.................|..............|.......................
301   //                   |                    |                 |              |
302   //                   |                    |                 |              |      Degenerated GC
303   //                   v                    v                 v              |
304   //               STW Mark ----------> STW Evac ----> STW Update-Refs ----->o
305   //                   |                    |                 |              ^
306   //                   | (af)               | (af)            | (af)         |
307   // ..................|....................|.................|..............|.......................
308   //                   |                    |                 |              |
309   //                   |                    v                 |              |      Full GC
310   //                   \------------------->o<----------------/              |
311   //                                        |                                |
312   //                                        v                                |
313   //                                      Full GC  --------------------------/
314   //
315   ShenandoahHeap* heap = ShenandoahHeap::heap();
316   if (check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle)) return;
317 
318   GCIdMark gc_id_mark;
319   ShenandoahGCSession session(cause, heap->global_generation());
320 
321   TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
322 
323   ShenandoahConcurrentGC gc(heap->global_generation(), false);
324   if (gc.collect(cause)) {
325     // Cycle is complete.  There were no failed allocation requests and no degeneration, so count this as good progress.
326     heap->notify_gc_progress();
327     heap->global_generation()->heuristics()->record_success_concurrent();
328     heap->shenandoah_policy()->record_success_concurrent(false, gc.abbreviated());
329     heap->log_heap_status("At end of GC");
330   } else {
331     assert(heap->cancelled_gc(), "Must have been cancelled");
332     check_cancellation_or_degen(gc.degen_point());
333     heap->log_heap_status("At end of cancelled GC");
334   }
335 }
336 
337 bool ShenandoahControlThread::check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point) {
338   ShenandoahHeap* heap = ShenandoahHeap::heap();
339   if (heap->cancelled_gc()) {
340     assert (is_alloc_failure_gc() || in_graceful_shutdown(), "Cancel GC either for alloc failure GC, or gracefully exiting");
341     if (!in_graceful_shutdown()) {
342       assert (_degen_point == ShenandoahGC::_degenerated_outside_cycle,
343               "Should not be set yet: %s", ShenandoahGC::degen_point_to_string(_degen_point));
344       _degen_point = point;
345     }
346     return true;
347   }
348   return false;
349 }
350 
351 void ShenandoahControlThread::stop_service() {
352   // Nothing to do here.
353 }
354 
355 void ShenandoahControlThread::service_stw_full_cycle(GCCause::Cause cause) {
356   ShenandoahHeap* const heap = ShenandoahHeap::heap();
357   GCIdMark gc_id_mark;
358   ShenandoahGCSession session(cause, heap->global_generation());
359 
360   ShenandoahFullGC gc;
361   gc.collect(cause);
362 }
363 
364 void ShenandoahControlThread::service_stw_degenerated_cycle(GCCause::Cause cause, ShenandoahGC::ShenandoahDegenPoint point) {
365   assert (point != ShenandoahGC::_degenerated_unset, "Degenerated point should be set");
366   ShenandoahHeap* const heap = ShenandoahHeap::heap();
367   GCIdMark gc_id_mark;
368   ShenandoahGCSession session(cause, heap->global_generation());
369 
370   ShenandoahDegenGC gc(point, heap->global_generation());
371   gc.collect(cause);
372 }
373 
374 void ShenandoahControlThread::request_gc(GCCause::Cause cause) {
375   if (ShenandoahCollectorPolicy::should_handle_requested_gc(cause)) {
376     handle_requested_gc(cause);
377   }
378 }
379 
380 void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
381   // For normal requested GCs (System.gc) we want to block the caller. However,
382   // for whitebox requested GC, we want to initiate the GC and return immediately.
383   // The whitebox caller thread will arrange for itself to wait until the GC notifies
384   // it that has reached the requested breakpoint (phase in the GC).
385   if (cause == GCCause::_wb_breakpoint) {
386     _requested_gc_cause = cause;
387     _gc_requested.set();
388     return;
389   }
390 
< prev index next >