8037112: gc/g1/TestHumongousAllocInitialMark.java caused SIGSEGV

Fri, 11 Apr 2014 11:00:12 +0200

author
pliden
date
Fri, 11 Apr 2014 11:00:12 +0200
changeset 6690
1772223a25a2
parent 6689
997fd9660dd5
child 6691
e4d318eea75a

8037112: gc/g1/TestHumongousAllocInitialMark.java caused SIGSEGV
Reviewed-by: brutisso, mgerdin

src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1StringDedup.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1StringDedup.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1StringDedupQueue.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1StringDedupQueue.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1StringDedupThread.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_interface/collectedHeap.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/java.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Thu May 22 09:12:29 2014 +0200
     1.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Fri Apr 11 11:00:12 2014 +0200
     1.3 @@ -89,6 +89,10 @@
     1.4    while (!_should_terminate) {
     1.5      // wait until started is set.
     1.6      sleepBeforeNextCycle();
     1.7 +    if (_should_terminate) {
     1.8 +      break;
     1.9 +    }
    1.10 +
    1.11      {
    1.12        ResourceMark rm;
    1.13        HandleMark   hm;
    1.14 @@ -303,11 +307,21 @@
    1.15  }
    1.16  
    1.17  void ConcurrentMarkThread::stop() {
    1.18 -  // it is ok to take late safepoints here, if needed
    1.19 -  MutexLockerEx mu(Terminator_lock);
    1.20 -  _should_terminate = true;
    1.21 -  while (!_has_terminated) {
    1.22 -    Terminator_lock->wait();
    1.23 +  {
    1.24 +    MutexLockerEx ml(Terminator_lock);
    1.25 +    _should_terminate = true;
    1.26 +  }
    1.27 +
    1.28 +  {
    1.29 +    MutexLockerEx ml(CGC_lock, Mutex::_no_safepoint_check_flag);
    1.30 +    CGC_lock->notify_all();
    1.31 +  }
    1.32 +
    1.33 +  {
    1.34 +    MutexLockerEx ml(Terminator_lock);
    1.35 +    while (!_has_terminated) {
    1.36 +      Terminator_lock->wait();
    1.37 +    }
    1.38    }
    1.39  }
    1.40  
    1.41 @@ -327,11 +341,14 @@
    1.42    assert(!in_progress(), "should have been cleared");
    1.43  
    1.44    MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
    1.45 -  while (!started()) {
    1.46 +  while (!started() && !_should_terminate) {
    1.47      CGC_lock->wait(Mutex::_no_safepoint_check_flag);
    1.48    }
    1.49 -  set_in_progress();
    1.50 -  clear_started();
    1.51 +
    1.52 +  if (started()) {
    1.53 +    set_in_progress();
    1.54 +    clear_started();
    1.55 +  }
    1.56  }
    1.57  
    1.58  // Note: As is the case with CMS - this method, although exported
     2.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu May 22 09:12:29 2014 +0200
     2.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Apr 11 11:00:12 2014 +0200
     2.3 @@ -435,6 +435,9 @@
     2.4  void G1CollectedHeap::stop_conc_gc_threads() {
     2.5    _cg1r->stop();
     2.6    _cmThread->stop();
     2.7 +  if (G1StringDedup::is_enabled()) {
     2.8 +    G1StringDedup::stop();
     2.9 +  }
    2.10  }
    2.11  
    2.12  #ifdef ASSERT
    2.13 @@ -2182,6 +2185,16 @@
    2.14    return JNI_OK;
    2.15  }
    2.16  
    2.17 +void G1CollectedHeap::stop() {
    2.18 +  // Abort any ongoing concurrent root region scanning and stop all
    2.19 +  // concurrent threads. We do this to make sure these threads do
    2.20 +  // not continue to execute and access resources (e.g. gclog_or_tty)
    2.21 +  // that are destroyed during shutdown.
    2.22 +  _cm->root_regions()->abort();
    2.23 +  _cm->root_regions()->wait_until_scan_finished();
    2.24 +  stop_conc_gc_threads();
    2.25 +}
    2.26 +
    2.27  size_t G1CollectedHeap::conservative_max_heap_alignment() {
    2.28    return HeapRegion::max_region_size();
    2.29  }
     3.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu May 22 09:12:29 2014 +0200
     3.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Fri Apr 11 11:00:12 2014 +0200
     3.3 @@ -1082,6 +1082,8 @@
     3.4    // specified by the policy object.
     3.5    jint initialize();
     3.6  
     3.7 +  virtual void stop();
     3.8 +
     3.9    // Return the (conservative) maximum heap alignment for any G1 heap
    3.10    static size_t conservative_max_heap_alignment();
    3.11  
     4.1 --- a/src/share/vm/gc_implementation/g1/g1StringDedup.cpp	Thu May 22 09:12:29 2014 +0200
     4.2 +++ b/src/share/vm/gc_implementation/g1/g1StringDedup.cpp	Fri Apr 11 11:00:12 2014 +0200
     4.3 @@ -44,6 +44,11 @@
     4.4    }
     4.5  }
     4.6  
     4.7 +void G1StringDedup::stop() {
     4.8 +  assert(is_enabled(), "String deduplication not enabled");
     4.9 +  G1StringDedupThread::stop();
    4.10 +}
    4.11 +
    4.12  bool G1StringDedup::is_candidate_from_mark(oop obj) {
    4.13    if (java_lang_String::is_instance(obj)) {
    4.14      bool from_young = G1CollectedHeap::heap()->heap_region_containing_raw(obj)->is_young();
     5.1 --- a/src/share/vm/gc_implementation/g1/g1StringDedup.hpp	Thu May 22 09:12:29 2014 +0200
     5.2 +++ b/src/share/vm/gc_implementation/g1/g1StringDedup.hpp	Fri Apr 11 11:00:12 2014 +0200
     5.3 @@ -110,8 +110,12 @@
     5.4      return _enabled;
     5.5    }
     5.6  
     5.7 +  // Initialize string deduplication.
     5.8    static void initialize();
     5.9  
    5.10 +  // Stop the deduplication thread.
    5.11 +  static void stop();
    5.12 +
    5.13    // Immediately deduplicates the given String object, bypassing the
    5.14    // the deduplication queue.
    5.15    static void deduplicate(oop java_string);
     6.1 --- a/src/share/vm/gc_implementation/g1/g1StringDedupQueue.cpp	Thu May 22 09:12:29 2014 +0200
     6.2 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupQueue.cpp	Fri Apr 11 11:00:12 2014 +0200
     6.3 @@ -35,6 +35,7 @@
     6.4  
     6.5  G1StringDedupQueue::G1StringDedupQueue() :
     6.6    _cursor(0),
     6.7 +  _cancel(false),
     6.8    _empty(true),
     6.9    _dropped(0) {
    6.10    _nqueues = MAX2(ParallelGCThreads, (size_t)1);
    6.11 @@ -55,11 +56,17 @@
    6.12  
    6.13  void G1StringDedupQueue::wait() {
    6.14    MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
    6.15 -  while (_queue->_empty) {
    6.16 +  while (_queue->_empty && !_queue->_cancel) {
    6.17      ml.wait(Mutex::_no_safepoint_check_flag);
    6.18    }
    6.19  }
    6.20  
    6.21 +void G1StringDedupQueue::cancel_wait() {
    6.22 +  MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
    6.23 +  _queue->_cancel = true;
    6.24 +  ml.notify();
    6.25 +}
    6.26 +
    6.27  void G1StringDedupQueue::push(uint worker_id, oop java_string) {
    6.28    assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint");
    6.29    assert(worker_id < _queue->_nqueues, "Invalid queue");
     7.1 --- a/src/share/vm/gc_implementation/g1/g1StringDedupQueue.hpp	Thu May 22 09:12:29 2014 +0200
     7.2 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupQueue.hpp	Fri Apr 11 11:00:12 2014 +0200
     7.3 @@ -65,6 +65,7 @@
     7.4    G1StringDedupWorkerQueue*  _queues;
     7.5    size_t                     _nqueues;
     7.6    size_t                     _cursor;
     7.7 +  bool                       _cancel;
     7.8    volatile bool              _empty;
     7.9  
    7.10    // Statistics counter, only used for logging.
    7.11 @@ -81,6 +82,9 @@
    7.12    // Blocks and waits for the queue to become non-empty.
    7.13    static void wait();
    7.14  
    7.15 +  // Wakes up any thread blocked waiting for the queue to become non-empty.
    7.16 +  static void cancel_wait();
    7.17 +
    7.18    // Pushes a deduplication candidate onto a specific GC worker queue.
    7.19    static void push(uint worker_id, oop java_string);
    7.20  
     8.1 --- a/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp	Thu May 22 09:12:29 2014 +0200
     8.2 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp	Fri Apr 11 11:00:12 2014 +0200
     8.3 @@ -73,6 +73,9 @@
     8.4  
     8.5      // Wait for the queue to become non-empty
     8.6      G1StringDedupQueue::wait();
     8.7 +    if (_should_terminate) {
     8.8 +      break;
     8.9 +    }
    8.10  
    8.11      // Include this thread in safepoints
    8.12      stsJoin();
    8.13 @@ -108,7 +111,23 @@
    8.14      stsLeave();
    8.15    }
    8.16  
    8.17 -  ShouldNotReachHere();
    8.18 +  terminate();
    8.19 +}
    8.20 +
    8.21 +void G1StringDedupThread::stop() {
    8.22 +  {
    8.23 +    MonitorLockerEx ml(Terminator_lock);
    8.24 +    _thread->_should_terminate = true;
    8.25 +  }
    8.26 +
    8.27 +  G1StringDedupQueue::cancel_wait();
    8.28 +
    8.29 +  {
    8.30 +    MonitorLockerEx ml(Terminator_lock);
    8.31 +    while (!_thread->_has_terminated) {
    8.32 +      ml.wait();
    8.33 +    }
    8.34 +  }
    8.35  }
    8.36  
    8.37  void G1StringDedupThread::print(outputStream* st, const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
     9.1 --- a/src/share/vm/gc_implementation/g1/g1StringDedupThread.hpp	Thu May 22 09:12:29 2014 +0200
     9.2 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupThread.hpp	Fri Apr 11 11:00:12 2014 +0200
     9.3 @@ -47,6 +47,8 @@
     9.4  
     9.5  public:
     9.6    static void create();
     9.7 +  static void stop();
     9.8 +
     9.9    static G1StringDedupThread* thread();
    9.10  
    9.11    virtual void run();
    10.1 --- a/src/share/vm/gc_interface/collectedHeap.hpp	Thu May 22 09:12:29 2014 +0200
    10.2 +++ b/src/share/vm/gc_interface/collectedHeap.hpp	Fri Apr 11 11:00:12 2014 +0200
    10.3 @@ -208,6 +208,9 @@
    10.4    // This is the correct place to place such initialization methods.
    10.5    virtual void post_initialize() = 0;
    10.6  
    10.7 +  // Stop any onging concurrent work and prepare for exit.
    10.8 +  virtual void stop() {}
    10.9 +
   10.10    MemRegion reserved_region() const { return _reserved; }
   10.11    address base() const { return (address)reserved_region().start(); }
   10.12  
    11.1 --- a/src/share/vm/runtime/java.cpp	Thu May 22 09:12:29 2014 +0200
    11.2 +++ b/src/share/vm/runtime/java.cpp	Fri Apr 11 11:00:12 2014 +0200
    11.3 @@ -497,6 +497,9 @@
    11.4      os::infinite_sleep();
    11.5    }
    11.6  
    11.7 +  // Stop any ongoing concurrent GC work
    11.8 +  Universe::heap()->stop();
    11.9 +
   11.10    // Terminate watcher thread - must before disenrolling any periodic task
   11.11    if (PeriodicTask::num_tasks() > 0)
   11.12      WatcherThread::stop();

mercurial