@@ -116,6 +116,13 @@ boolean isInProgress() {
116116 return safepointState == AT_SAFEPOINT ;
117117 }
118118
119+ @ Uninterruptible (reason = CALLED_FROM_UNINTERRUPTIBLE_CODE , mayBeInlined = true )
120+ public boolean isPendingOrInProgress () {
121+ /* Only read the state once. */
122+ int state = safepointState ;
123+ return state == SYNCHRONIZING || state == AT_SAFEPOINT ;
124+ }
125+
119126 @ Uninterruptible (reason = CALLED_FROM_UNINTERRUPTIBLE_CODE , mayBeInlined = true )
120127 public UnsignedWord getSafepointId () {
121128 return safepointId ;
@@ -126,11 +133,6 @@ public boolean isMasterThread() {
126133 return requestingThread == CurrentIsolate .getCurrentThread ();
127134 }
128135
129- @ Uninterruptible (reason = CALLED_FROM_UNINTERRUPTIBLE_CODE , mayBeInlined = true )
130- public boolean isPendingOrInProgress () {
131- return requestingThread .isNonNull ();
132- }
133-
134136 /**
135137 * Initiates a safepoint.
136138 *
@@ -150,12 +152,13 @@ boolean startSafepoint(String reason) {
150152 THREAD_MUTEX .lock ();
151153 }
152154
155+ assert requestingThread .isNull ();
153156 requestingThread = CurrentIsolate .getCurrentThread ();
154157 ImageSingletons .lookup (Heap .class ).prepareForSafepoint ();
158+
155159 safepointState = SYNCHRONIZING ;
160+ int numJavaThreads = requestThreadsEnterSafepoint (reason );
156161
157- int numJavaThreads = requestThreadsEnterSafepoint ();
158- waitUntilThreadsEnterSafepoint (reason );
159162 safepointState = AT_SAFEPOINT ;
160163 safepointId = safepointId .add (1 );
161164 SafepointBeginEvent .emit (getSafepointId (), numJavaThreads , startTicks );
@@ -167,46 +170,34 @@ boolean startSafepoint(String reason) {
167170 void endSafepoint (boolean unlock ) {
168171 assert VMOperationControl .mayExecuteVmOperations ();
169172 long startTicks = JfrTicks .elapsedTicks ();
173+
170174 safepointState = NOT_AT_SAFEPOINT ;
171175 releaseThreadsFromSafepoint ();
172176 /* Some Java threads can continue execution now. */
173177
174- SafepointEndEvent .emit (getSafepointId (), startTicks );
175- ImageSingletons .lookup (Heap .class ).endSafepoint ();
176-
177- requestingThread = Word .nullPointer ();
178178 if (unlock ) {
179179 THREAD_MUTEX .unlock ();
180180 }
181181
182- /* This can take a moment, so we do it after letting all other threads proceed. */
183- VMThreads .singleton ().cleanupExitedOsThreads ();
184- }
185-
186- /**
187- * Ask all other threads to come to a safepoint. There is no guarantee that the threads will
188- * comply with the request.
189- */
190- private static int requestThreadsEnterSafepoint () {
191- assert THREAD_MUTEX .isOwner () : "must hold mutex while requesting a safepoint" ;
192- int numJavaThreads = 0 ;
182+ /*
183+ * Now that the safepoint was released, we can treat this thread like a normal VM thread and
184+ * don't need the special handling in the safepoint slowpath anymore. Other threads also
185+ * can't start a new safepoint yet (this code is still executed in the VM operation thread
186+ * and only the VM operation thread may start a safepoint).
187+ */
188+ requestingThread = Word .nullPointer ();
193189
194- for (IsolateThread thread = VMThreads .firstThread (); thread .isNonNull (); thread = VMThreads .nextThread (thread )) {
195- numJavaThreads ++;
196- if (thread == CurrentIsolate .getCurrentThread ()) {
197- continue ;
198- }
199- if (SafepointBehavior .ignoresSafepoints (thread )) {
200- /* If safepoints are disabled, do not ask it to stop at safepoints. */
201- continue ;
202- }
203- requestEnterSafepoint (thread );
204- }
205- return numJavaThreads ;
190+ /*
191+ * Everything down here can take a moment, so we do it after letting all other threads
192+ * proceed.
193+ */
194+ ImageSingletons .lookup (Heap .class ).endSafepoint ();
195+ SafepointEndEvent .emit (getSafepointId (), startTicks );
196+ VMThreads .singleton ().cleanupExitedOsThreads ();
206197 }
207198
208- /** Wait until all other threads reach a safepoint. Re-requests safepoints if necessary . */
209- private static void waitUntilThreadsEnterSafepoint (String reason ) {
199+ /** Blocks until all other threads entered the safepoint. */
200+ private static int requestThreadsEnterSafepoint (String reason ) {
210201 assert THREAD_MUTEX .isOwner () : "must hold mutex while waiting for safepoints" ;
211202
212203 long startNanos = System .nanoTime ();
@@ -216,12 +207,13 @@ private static void waitUntilThreadsEnterSafepoint(String reason) {
216207 long failureNanos = -1 ;
217208
218209 for (int loopCount = 1 ; /* return */ ; loopCount ++) {
210+ int numThreads = 0 ;
219211 int atSafepoint = 0 ;
220212 int ignoreSafepoints = 0 ;
221213 int notAtSafepoint = 0 ;
222- int lostUpdates = 0 ;
223214
224215 for (IsolateThread thread = VMThreads .firstThread (); thread .isNonNull (); thread = VMThreads .nextThread (thread )) {
216+ numThreads ++;
225217 if (thread == CurrentIsolate .getCurrentThread ()) {
226218 continue ;
227219 }
@@ -245,10 +237,9 @@ private static void waitUntilThreadsEnterSafepoint(String reason) {
245237 switch (status ) {
246238 case StatusSupport .STATUS_IN_JAVA :
247239 case StatusSupport .STATUS_IN_VM : {
248- /* Re-request the safepoint in case of a lost update. */
240+ /* Request the safepoint (or re-request in case of a lost update) . */
249241 if (SafepointCheckCounter .getVolatile (thread ) > 0 ) {
250242 requestEnterSafepoint (thread );
251- lostUpdates ++;
252243 }
253244 notAtSafepoint ++;
254245 break ;
@@ -274,8 +265,8 @@ private static void waitUntilThreadsEnterSafepoint(String reason) {
274265 }
275266
276267 if (notAtSafepoint == 0 ) {
277- /* All threads entered the safepoint. */
278- return ;
268+ /* All relevant threads entered the safepoint. */
269+ return numThreads ;
279270 }
280271
281272 if (warningNanos == -1 || failureNanos == -1 ) {
@@ -297,7 +288,6 @@ private static void waitUntilThreadsEnterSafepoint(String reason) {
297288 .string (" atSafepoint: " ).signed (atSafepoint )
298289 .string (" ignoreSafepoints: " ).signed (ignoreSafepoints )
299290 .string (" notAtSafepoint: " ).signed (notAtSafepoint )
300- .string (" lostUpdates: " ).signed (lostUpdates )
301291 .string ("]" )
302292 .newline ();
303293
@@ -333,6 +323,7 @@ private static void releaseThreadsFromSafepoint() {
333323 continue ;
334324 }
335325
326+ assert StatusSupport .getStatusVolatile (thread ) == StatusSupport .STATUS_IN_SAFEPOINT ;
336327 restoreCounter (thread );
337328
338329 /* Skip suspended threads so that they remain in STATUS_IN_SAFEPOINT. */
0 commit comments