From 570f33e3f57acb9a8b4b7e3c378b836bef774df4 Mon Sep 17 00:00:00 2001
Date: Wed, 17 Jul 2019 11:36:31 +0000
Subject: [PATCH] Backport of JDK-8129626

summary: G1: set_in_progress() and clear_started() needs a barrier on non-TSO platforms
LLT:

Bug url: https://bugs.openjdk.java.net/browse/JDK-8129626
---
 .../gc_implementation/g1/concurrentMarkThread.cpp  |  4 +--
 .../gc_implementation/g1/concurrentMarkThread.hpp  | 29 +++++++++++++---------
 .../vm/gc_implementation/g1/g1CollectedHeap.cpp    |  2 +-
 3 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp
index b56e309234..53fe0837b1 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp
@@ -43,8 +43,7 @@ SurrogateLockerThread*
 ConcurrentMarkThread::ConcurrentMarkThread(ConcurrentMark* cm) :
   ConcurrentGCThread(),
   _cm(cm),
-  _started(false),
-  _in_progress(false),
+  _state(Idle),
   _vtime_accum(0.0),
   _vtime_mark_accum(0.0) {
   create_and_start();
@@ -341,7 +340,6 @@ void ConcurrentMarkThread::sleepBeforeNextCycle() {
 
   if (started()) {
     set_in_progress();
-    clear_started();
   }
 }
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp
index caa7f429c6..5f5f70ac4d 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp
@@ -46,8 +46,14 @@ class ConcurrentMarkThread: public ConcurrentGCThread {
 
  private:
   ConcurrentMark*                  _cm;
-  volatile bool                    _started;
-  volatile bool                    _in_progress;
+
+  enum State {
+    Idle,
+    Started,
+    InProgress
+  };
+
+  volatile State _state;
 
   void sleepBeforeNextCycle();
 
@@ -71,23 +77,22 @@ class ConcurrentMarkThread: public ConcurrentGCThread {
 
   ConcurrentMark* cm()     { return _cm; }
 
-  void set_started()       { assert(!_in_progress, "cycle in progress"); _started = true;  }
-  void clear_started()     { assert(_in_progress, "must be starting a cycle"); _started = false; }
-  bool started()           { return _started;  }
-
-  void set_in_progress()   { assert(_started, "must be starting a cycle"); _in_progress = true;  }
-  void clear_in_progress() { assert(!_started, "must not be starting a new cycle"); _in_progress = false; }
-  bool in_progress()       { return _in_progress;  }
+  void set_idle()          { assert(_state != Started, "must not be starting a new cycle"); _state = Idle; }
+  bool idle()              { return _state == Idle; }
+  void set_started()       { assert(_state == Idle, "cycle in progress"); _state = Started; }
+  bool started()           { return _state == Started; }
+  void set_in_progress()   { assert(_state == Started, "must be starting a cycle"); _state = InProgress; }
+  bool in_progress()       { return _state == InProgress; }
 
-  // This flag returns true from the moment a marking cycle is
+  // Returns true from the moment a marking cycle is
   // initiated (during the initial-mark pause when started() is set)
   // to the moment when the cycle completes (just after the next
   // marking bitmap has been cleared and in_progress() is
-  // cleared). While this flag is true we will not start another cycle
+  // cleared). While during_cycle() is true we will not start another cycle
   // so that cycles do not overlap. We cannot use just in_progress()
   // as the CM thread might take some time to wake up before noticing
   // that started() is set and set in_progress().
-  bool during_cycle()      { return started() || in_progress(); }
+  bool during_cycle()      { return !idle(); }
 
   // shutdown
   void stop();
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
index aa6bbc81a4..a6e91a08ce 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
@@ -2409,7 +2409,7 @@ void G1CollectedHeap::increment_old_marking_cycles_completed(bool concurrent) {
   // is set) so that if a waiter requests another System.gc() it doesn't
   // incorrectly see that a marking cycle is still in progress.
   if (concurrent) {
-    _cmThread->clear_in_progress();
+    _cmThread->set_idle();
   }
 
   // This notify_all() will ensure that a thread that called
-- 
2.12.3

