From addff4b4b7265166c608642a74d21d8fe9a7c1b4 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 13 Nov 2020 03:11:47 -0800 Subject: [PATCH] Prevent potential re-park when the unparking thread is too slow (#2381) --- .../jvm/src/scheduling/CoroutineScheduler.kt | 14 +++++++++++++- ...ngCoroutineDispatcherMixedStealingStressTest.kt | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt index 62cf80f7f8..ad61224b52 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt @@ -721,7 +721,19 @@ internal class CoroutineScheduler( } assert { localQueue.size == 0 } workerCtl.value = PARKED // Update value once - while (inStack()) { // Prevent spurious wakeups + /* + * inStack() prevents spurious wakeups, while workerCtl.value == PARKED + * prevents the following race: + * + * - T2 scans the queue, adds itself to the stack, goes to rescan + * - T2 suspends in 'workerCtl.value = PARKED' line + * - T1 pops T2 from the stack, claims workerCtl, suspends + * - T2 fails 'while (inStack())' check, goes to full rescan + * - T2 adds itself to the stack, parks + * - T1 unparks T2, bails out with success + * - T2 unparks and loops in 'while (inStack())' + */ + while (inStack() && workerCtl.value == PARKED) { // Prevent spurious wakeups if (isTerminated || state == WorkerState.TERMINATED) break tryReleaseCpu(WorkerState.PARKING) interrupted() // Cleanup interruptions diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherMixedStealingStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherMixedStealingStressTest.kt index 1fe0d8386d..3a55f8c4f2 100644 --- a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherMixedStealingStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherMixedStealingStressTest.kt @@ -77,4 +77,4 @@ class BlockingCoroutineDispatcherMixedStealingStressTest : SchedulerTestBase() { cpuBlocker.await() } } -} \ No newline at end of file +}