< 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();

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();

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 >