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
|