Thu, 21 Oct 2010 17:29:24 -0700
6992998: CMSWaitDuration=0 causes hangs with +ExplicitGCInvokesConcurrent
Summary: Closed a timing hole during which concurrent full gc requests can be missed. The hole can increase the latency of the response to a full gc request by up to the value of CMSWaitDuration. If CMSWaitDuration=0 is, as currently, interpreted as an unbounded wait, suitable in certain tuning scenarios, the application can potentially hang. Made two obscure tunables, including CMSWaitDuration, manageable.
Reviewed-by: jcoomes, tonyp
1.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Sat Oct 16 17:12:19 2010 -0400 1.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Thu Oct 21 17:29:24 2010 -0700 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -272,12 +272,16 @@ 1.11 } 1.12 } 1.13 1.14 -// Wait until the next synchronous GC or a timeout, whichever is earlier. 1.15 -void ConcurrentMarkSweepThread::wait_on_cms_lock(long t) { 1.16 +// Wait until the next synchronous GC, a concurrent full gc request, 1.17 +// or a timeout, whichever is earlier. 1.18 +void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) { 1.19 MutexLockerEx x(CGC_lock, 1.20 Mutex::_no_safepoint_check_flag); 1.21 + if (_should_terminate || _collector->_full_gc_requested) { 1.22 + return; 1.23 + } 1.24 set_CMS_flag(CMS_cms_wants_token); // to provoke notifies 1.25 - CGC_lock->wait(Mutex::_no_safepoint_check_flag, t); 1.26 + CGC_lock->wait(Mutex::_no_safepoint_check_flag, t_millis); 1.27 clear_CMS_flag(CMS_cms_wants_token); 1.28 assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), 1.29 "Should not be set"); 1.30 @@ -289,7 +293,8 @@ 1.31 icms_wait(); 1.32 return; 1.33 } else { 1.34 - // Wait until the next synchronous GC or a timeout, whichever is earlier 1.35 + // Wait until the next synchronous GC, a concurrent full gc 1.36 + // request or a timeout, whichever is earlier. 1.37 wait_on_cms_lock(CMSWaitDuration); 1.38 } 1.39 // Check if we should start a CMS collection cycle
2.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp Sat Oct 16 17:12:19 2010 -0400 2.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp Thu Oct 21 17:29:24 2010 -0700 2.3 @@ -120,8 +120,10 @@ 2.4 } 2.5 2.6 // Wait on CMS lock until the next synchronous GC 2.7 - // or given timeout, whichever is earlier. 2.8 - void wait_on_cms_lock(long t); // milliseconds 2.9 + // or given timeout, whichever is earlier. A timeout value 2.10 + // of 0 indicates that there is no upper bound on the wait time. 2.11 + // A concurrent full gc request terminates the wait. 2.12 + void wait_on_cms_lock(long t_millis); 2.13 2.14 // The CMS thread will yield during the work portion of its cycle 2.15 // only when requested to. Both synchronous and asychronous requests
3.1 --- a/src/share/vm/runtime/globals.hpp Sat Oct 16 17:12:19 2010 -0400 3.2 +++ b/src/share/vm/runtime/globals.hpp Thu Oct 21 17:29:24 2010 -0700 3.3 @@ -1585,7 +1585,7 @@ 3.4 "(Temporary, subject to experimentation)" \ 3.5 "Nominal minimum work per abortable preclean iteration") \ 3.6 \ 3.7 - product(intx, CMSAbortablePrecleanWaitMillis, 100, \ 3.8 + manageable(intx, CMSAbortablePrecleanWaitMillis, 100, \ 3.9 "(Temporary, subject to experimentation)" \ 3.10 " Time that we sleep between iterations when not given" \ 3.11 " enough work per iteration") \ 3.12 @@ -1677,7 +1677,7 @@ 3.13 product(uintx, CMSWorkQueueDrainThreshold, 10, \ 3.14 "Don't drain below this size per parallel worker/thief") \ 3.15 \ 3.16 - product(intx, CMSWaitDuration, 2000, \ 3.17 + manageable(intx, CMSWaitDuration, 2000, \ 3.18 "Time in milliseconds that CMS thread waits for young GC") \ 3.19 \ 3.20 product(bool, CMSYield, true, \