Skip to content

Commit 28f0d71

Browse files
committed
Fix lincheck (it doesn't support thread locals)
1 parent 55235d8 commit 28f0d71

File tree

4 files changed

+25
-10
lines changed

4 files changed

+25
-10
lines changed

atomicfu/src/concurrentMain/kotlin/kotlinx/atomicfu/locks/Mutex.kt

+5-7
Original file line numberDiff line numberDiff line change
@@ -153,27 +153,25 @@ internal class NativeMutex {
153153
when (parker.value) {
154154
Empty -> if (parker.compareAndSet(Empty, KThread.currentThread())) Parker.park()
155155
is KThread -> Parker.park()
156-
Woken -> return
156+
Awoken -> return
157157
}
158158
}
159159
}
160160

161161
fun nodeWake() {
162162
while (true) {
163163
when (val currentState = parker.value) {
164-
Empty -> if (parker.compareAndSet(Empty, Woken)) return
165-
is KThread -> if (parker.compareAndSet(currentState, Woken)) {
164+
Empty -> if (parker.compareAndSet(Empty, Awoken)) return
165+
is KThread -> if (parker.compareAndSet(currentState, Awoken)) {
166166
Parker.unpark(currentState)
167167
return
168168
}
169-
Woken -> throw IllegalStateException("Node is already woken")
169+
Awoken -> throw IllegalStateException("Node is already woken")
170170
}
171171
}
172172
}
173173
}
174174

175175
private object Empty
176-
private object Woken
177-
178-
176+
private object Awoken
179177
}

atomicfu/src/jvmMain/kotlin/kotlinx/atomicfu/parking/KThread.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package kotlinx.atomicfu.parking
22

33
actual class KThread internal actual constructor() {
4-
internal val parker = ThreadParker(this)
4+
internal var parker = ThreadParker(this)
55
actual companion object {
66
actual fun currentThread(): KThread = localKThread.get()
77
}

atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/locks/NativeMutexLincheckReentrantTest.kt

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
import kotlinx.atomicfu.locks.Mutex
12
import kotlinx.atomicfu.locks.NativeMutex
3+
import kotlinx.atomicfu.parking.KThread
4+
import kotlinx.atomicfu.parking.ThreadParker
25
import org.jetbrains.kotlinx.lincheck.annotations.Operation
36
import org.jetbrains.kotlinx.lincheck.check
47
import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.ModelCheckingOptions
58
import org.jetbrains.kotlinx.lincheck.util.LoggingLevel
9+
import java.util.concurrent.ConcurrentHashMap
610
import kotlin.test.Test
711

812
class NativeMutexLincheckReentrantTest {
@@ -13,8 +17,9 @@ class NativeMutexLincheckReentrantTest {
1317
fun inc(): Int = ++value
1418
fun get() = value
1519
}
16-
private val lock = NativeMutex()
1720
private val counter = Counter()
21+
private val lock = NativeMutex()
22+
private val resetThreadParkers = ConcurrentHashMap.newKeySet<Long>()
1823

1924
@Test
2025
fun modelCheckingTest(): Unit = ModelCheckingOptions()
@@ -30,6 +35,8 @@ class NativeMutexLincheckReentrantTest {
3035

3136
@Operation
3237
fun inc(): Int {
38+
if (resetThreadParkers.add(Thread.currentThread().id))
39+
KThread.currentThread().parker = ThreadParker(KThread.currentThread())
3340
lock.lock()
3441
if (!lock.tryLock()) throw IllegalStateException("couldnt reent with trylock")
3542
if (!lock.tryLock()) throw IllegalStateException("couldnt reent with trylock")
@@ -42,6 +49,8 @@ class NativeMutexLincheckReentrantTest {
4249

4350
@Operation
4451
fun get(): Int {
52+
if (resetThreadParkers.add(Thread.currentThread().id))
53+
KThread.currentThread().parker = ThreadParker(KThread.currentThread())
4554
lock.lock()
4655
if (!lock.tryLock()) throw IllegalStateException("couldnt reent with trylock")
4756
if (!lock.tryLock()) throw IllegalStateException("couldnt reent with trylock")

atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/locks/NativeMutexLincheckTest.kt

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import kotlinx.atomicfu.locks.NativeMutex
2+
import kotlinx.atomicfu.parking.KThread
3+
import kotlinx.atomicfu.parking.ThreadParker
24
import org.jetbrains.kotlinx.lincheck.annotations.Operation
35
import org.jetbrains.kotlinx.lincheck.check
46
import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.ModelCheckingOptions
57
import org.jetbrains.kotlinx.lincheck.util.LoggingLevel
8+
import java.util.concurrent.ConcurrentHashMap
69
import kotlin.test.Test
710

811
class NativeMutexLincheckTest {
@@ -13,8 +16,9 @@ class NativeMutexLincheckTest {
1316
fun inc(): Int = ++value
1417
fun get() = value
1518
}
16-
private val lock = NativeMutex()
1719
private val counter = Counter()
20+
private val lock = NativeMutex()
21+
private val resetThreadParkers = ConcurrentHashMap.newKeySet<Long>()
1822

1923
@Test
2024
fun modelCheckingTest(): Unit = ModelCheckingOptions()
@@ -30,13 +34,17 @@ class NativeMutexLincheckTest {
3034

3135
@Operation
3236
fun inc() {
37+
if (resetThreadParkers.add(Thread.currentThread().id))
38+
KThread.currentThread().parker = ThreadParker(KThread.currentThread())
3339
lock.lock()
3440
counter.inc()
3541
lock.unlock()
3642
}
3743

3844
@Operation
3945
fun get() {
46+
if (resetThreadParkers.add(Thread.currentThread().id))
47+
KThread.currentThread().parker = ThreadParker(KThread.currentThread())
4048
lock.lock()
4149
counter.get()
4250
lock.unlock()

0 commit comments

Comments
 (0)