提交 71dfbe38 编写于 作者: Y ysr

6987703: iCMS: Intermittent hang with gc/gctests/CallGC/CallGC01 and +ExplicitGCInvokesConcurrent

Summary: Count enable_icms() and disable_icms() events so as to prevent inteference between concurrent calls, which can cause the iCMS thread to be left stranded in icms_wait() with an unserviced request and no young allocations to unwedge it.
Reviewed-by: jcoomes, poonam
上级 f734707b
/* /*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1689,6 +1689,8 @@ void CMSCollector::request_full_gc(unsigned int full_gc_count) { ...@@ -1689,6 +1689,8 @@ void CMSCollector::request_full_gc(unsigned int full_gc_count) {
MutexLockerEx y(CGC_lock, Mutex::_no_safepoint_check_flag); MutexLockerEx y(CGC_lock, Mutex::_no_safepoint_check_flag);
_full_gc_requested = true; _full_gc_requested = true;
CGC_lock->notify(); // nudge CMS thread CGC_lock->notify(); // nudge CMS thread
} else {
assert(gc_count > full_gc_count, "Error: causal loop");
} }
} }
......
/* /*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -51,7 +51,7 @@ int ConcurrentMarkSweepThread::_CMS_flag = CMS_nil; ...@@ -51,7 +51,7 @@ int ConcurrentMarkSweepThread::_CMS_flag = CMS_nil;
volatile jint ConcurrentMarkSweepThread::_pending_yields = 0; volatile jint ConcurrentMarkSweepThread::_pending_yields = 0;
volatile jint ConcurrentMarkSweepThread::_pending_decrements = 0; volatile jint ConcurrentMarkSweepThread::_pending_decrements = 0;
volatile bool ConcurrentMarkSweepThread::_icms_enabled = false; volatile jint ConcurrentMarkSweepThread::_icms_disabled = 0;
volatile bool ConcurrentMarkSweepThread::_should_run = false; volatile bool ConcurrentMarkSweepThread::_should_run = false;
// When icms is enabled, the icms thread is stopped until explicitly // When icms is enabled, the icms thread is stopped until explicitly
// started. // started.
...@@ -84,7 +84,7 @@ ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector) ...@@ -84,7 +84,7 @@ ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector)
} }
} }
_sltMonitor = SLT_lock; _sltMonitor = SLT_lock;
set_icms_enabled(CMSIncrementalMode); assert(!CMSIncrementalMode || icms_is_enabled(), "Error");
} }
void ConcurrentMarkSweepThread::run() { void ConcurrentMarkSweepThread::run() {
...@@ -341,11 +341,11 @@ void ConcurrentMarkSweepThread::stop_icms() { ...@@ -341,11 +341,11 @@ void ConcurrentMarkSweepThread::stop_icms() {
void ConcurrentMarkSweepThread::icms_wait() { void ConcurrentMarkSweepThread::icms_wait() {
assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking"); assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking");
if (_should_stop && icms_enabled()) { if (_should_stop && icms_is_enabled()) {
MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag); MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag);
trace_state("pause_icms"); trace_state("pause_icms");
_collector->stats().stop_cms_timer(); _collector->stats().stop_cms_timer();
while(!_should_run && icms_enabled()) { while(!_should_run && icms_is_enabled()) {
iCMS_lock->wait(Mutex::_no_safepoint_check_flag); iCMS_lock->wait(Mutex::_no_safepoint_check_flag);
} }
_collector->stats().start_cms_timer(); _collector->stats().start_cms_timer();
......
/* /*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
class ConcurrentMarkSweepGeneration; class ConcurrentMarkSweepGeneration;
class CMSCollector; class CMSCollector;
// The Concurrent Mark Sweep GC Thread (could be several in the future). // The Concurrent Mark Sweep GC Thread
class ConcurrentMarkSweepThread: public ConcurrentGCThread { class ConcurrentMarkSweepThread: public ConcurrentGCThread {
friend class VMStructs; friend class VMStructs;
friend class ConcurrentMarkSweepGeneration; // XXX should remove friendship friend class ConcurrentMarkSweepGeneration; // XXX should remove friendship
...@@ -55,8 +55,6 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread { ...@@ -55,8 +55,6 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread {
static SurrogateLockerThread::SLT_msg_type _sltBuffer; static SurrogateLockerThread::SLT_msg_type _sltBuffer;
static Monitor* _sltMonitor; static Monitor* _sltMonitor;
ConcurrentMarkSweepThread* _next;
static bool _should_terminate; static bool _should_terminate;
enum CMS_flag_type { enum CMS_flag_type {
...@@ -84,7 +82,7 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread { ...@@ -84,7 +82,7 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread {
// Tracing messages, enabled by CMSTraceThreadState. // Tracing messages, enabled by CMSTraceThreadState.
static inline void trace_state(const char* desc); static inline void trace_state(const char* desc);
static volatile bool _icms_enabled; // iCMS enabled? static volatile int _icms_disabled; // a counter to track #iCMS disable & enable
static volatile bool _should_run; // iCMS may run static volatile bool _should_run; // iCMS may run
static volatile bool _should_stop; // iCMS should stop static volatile bool _should_stop; // iCMS should stop
...@@ -214,10 +212,25 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread { ...@@ -214,10 +212,25 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread {
// Incremental mode is enabled globally by the flag CMSIncrementalMode. It // Incremental mode is enabled globally by the flag CMSIncrementalMode. It
// must also be enabled/disabled dynamically to allow foreground collections. // must also be enabled/disabled dynamically to allow foreground collections.
static inline void enable_icms() { _icms_enabled = true; } #define ICMS_ENABLING_ASSERT \
static inline void disable_icms() { _icms_enabled = false; } assert((CMSIncrementalMode && _icms_disabled >= 0) || \
static inline void set_icms_enabled(bool val) { _icms_enabled = val; } (!CMSIncrementalMode && _icms_disabled <= 0), "Error")
static inline bool icms_enabled() { return _icms_enabled; }
static inline void enable_icms() {
ICMS_ENABLING_ASSERT;
Atomic::dec(&_icms_disabled);
}
static inline void disable_icms() {
ICMS_ENABLING_ASSERT;
Atomic::inc(&_icms_disabled);
}
static inline bool icms_is_disabled() {
ICMS_ENABLING_ASSERT;
return _icms_disabled > 0;
}
static inline bool icms_is_enabled() {
return !icms_is_disabled();
}
}; };
inline void ConcurrentMarkSweepThread::trace_state(const char* desc) { inline void ConcurrentMarkSweepThread::trace_state(const char* desc) {
......
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -192,14 +192,18 @@ void VM_GenCollectFullConcurrent::doit() { ...@@ -192,14 +192,18 @@ void VM_GenCollectFullConcurrent::doit() {
"total_collections() should be monotonically increasing"); "total_collections() should be monotonically increasing");
MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag); MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
assert(_full_gc_count_before <= gch->total_full_collections(), "Error");
if (gch->total_full_collections() == _full_gc_count_before) { if (gch->total_full_collections() == _full_gc_count_before) {
// Disable iCMS until the full collection is done. // Disable iCMS until the full collection is done, and
// remember that we did so.
CMSCollector::disable_icms(); CMSCollector::disable_icms();
_disabled_icms = true;
// In case CMS thread was in icms_wait(), wake it up. // In case CMS thread was in icms_wait(), wake it up.
CMSCollector::start_icms(); CMSCollector::start_icms();
// Nudge the CMS thread to start a concurrent collection. // Nudge the CMS thread to start a concurrent collection.
CMSCollector::request_full_gc(_full_gc_count_before); CMSCollector::request_full_gc(_full_gc_count_before);
} else { } else {
assert(_full_gc_count_before < gch->total_full_collections(), "Error");
FullGCCount_lock->notify_all(); // Inform the Java thread its work is done FullGCCount_lock->notify_all(); // Inform the Java thread its work is done
} }
} }
...@@ -259,6 +263,8 @@ void VM_GenCollectFullConcurrent::doit_epilogue() { ...@@ -259,6 +263,8 @@ void VM_GenCollectFullConcurrent::doit_epilogue() {
FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag); FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);
} }
} }
// Enable iCMS back. // Enable iCMS back if we disabled it earlier.
CMSCollector::enable_icms(); if (_disabled_icms) {
CMSCollector::enable_icms();
}
} }
...@@ -128,11 +128,14 @@ class VM_CMS_Final_Remark: public VM_CMS_Operation { ...@@ -128,11 +128,14 @@ class VM_CMS_Final_Remark: public VM_CMS_Operation {
// VM operation to invoke a concurrent collection of the heap as a // VM operation to invoke a concurrent collection of the heap as a
// GenCollectedHeap heap. // GenCollectedHeap heap.
class VM_GenCollectFullConcurrent: public VM_GC_Operation { class VM_GenCollectFullConcurrent: public VM_GC_Operation {
bool _disabled_icms;
public: public:
VM_GenCollectFullConcurrent(unsigned int gc_count_before, VM_GenCollectFullConcurrent(unsigned int gc_count_before,
unsigned int full_gc_count_before, unsigned int full_gc_count_before,
GCCause::Cause gc_cause) GCCause::Cause gc_cause)
: VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */) { : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */),
_disabled_icms(false)
{
assert(FullGCCount_lock != NULL, "Error"); assert(FullGCCount_lock != NULL, "Error");
assert(UseAsyncConcMarkSweepGC, "Else will hang caller"); assert(UseAsyncConcMarkSweepGC, "Else will hang caller");
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册