[K/N][New MM] Support thread state switching

Including

* Support thread state switching in codegen
* Introduce and use GCUnsafeCall annotation
* Switch thread state in C++ runtime code

Also

* Register current thread in Mark&Sweep tests
* Store MemoryState in Worker instance
* Set worker tid in WorkerInit
This commit is contained in:
Ilya Matveev
2021-01-25 19:06:27 +07:00
committed by Space
parent 0b46ed3cde
commit 4d346d3735
86 changed files with 1340 additions and 721 deletions
@@ -3830,6 +3830,11 @@ createInterop("cppSkia") {
it.defFile 'interop/cpp/skia.def'
}
createInterop("threadStates") {
it.defFile "interop/threadStates/threadStates.def"
it.extraOpts "-Xcompile-source", "$projectDir/interop/threadStates/threadStates.cpp"
}
if (PlatformInfo.isAppleTarget(project)) {
createInterop("objcSmoke") {
it.defFile 'interop/objc/objcSmoke.def'
@@ -4117,6 +4122,20 @@ interopTest("interop_callbacksAndVarargs") {
interop = 'ccallbacksAndVarargs'
}
interopTest("interop_threadStates") {
disabled = (project.testTarget == 'wasm32') || // No interop for wasm yet.
!isExperimentalMM // No thread state switching in the legacy MM.
source = "interop/threadStates/threadStates.kt"
interop = "threadStates"
}
interopTest("interop_threadStates_callbacksWithExceptions") {
disabled = (project.testTarget == 'wasm32') || // No interop for wasm yet.
!isExperimentalMM // No thread state switching in the legacy MM.
source = "interop/threadStates/callbacksWithExceptions.kt"
interop = "threadStates"
}
interopTest("interop_withSpaces") {
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
interop ='withSpaces'
@@ -0,0 +1,95 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
import kotlin.native.internal.Debugging
import kotlin.test.*
import kotlinx.cinterop.staticCFunction
import threadStates.*
fun main() {
callbackWithException()
callbackWithFinally()
callbackWithFinallyNoCatch()
nestedCallbackWithException()
nestedCallbackWithFinally()
}
fun assertRunnableThreadState() {
assertTrue(Debugging.isThreadStateRunnable)
}
class CustomException() : Exception()
fun throwException() {
assertRunnableThreadState()
throw CustomException()
}
fun callbackWithException() {
try {
runCallback(staticCFunction(::throwException))
} catch (e: CustomException) {
assertRunnableThreadState()
return
} catch (e: Throwable) {
assertRunnableThreadState()
fail("Wrong exception type: ${e.message}")
}
fail("No exception thrown")
}
fun callbackWithFinally() {
try {
runCallback(staticCFunction(::throwException))
} catch (e: CustomException) {
assertRunnableThreadState()
return
} finally {
assertRunnableThreadState()
}
fail("No exception thrown")
}
fun callbackWithFinallyNoCatch() {
try {
try {
runCallback(staticCFunction(::throwException))
} finally {
assertRunnableThreadState()
}
assertRunnableThreadState()
} catch (_: CustomException) {}
}
fun nestedCallbackWithException() {
try {
runCallback(staticCFunction { ->
assertRunnableThreadState()
runCallback(staticCFunction(::throwException))
})
} catch (e: CustomException) {
assertRunnableThreadState()
return
} catch (e: Throwable) {
assertRunnableThreadState()
fail("Wrong exception type: ${e.message}")
}
fail("No exception thrown")
}
fun nestedCallbackWithFinally() {
try {
runCallback(staticCFunction { ->
assertRunnableThreadState()
runCallback(staticCFunction(::throwException))
})
} catch (e: CustomException) {
assertRunnableThreadState()
return
} finally {
assertRunnableThreadState()
}
fail("No exception thrown")
}
@@ -0,0 +1,20 @@
#include <thread>
#include <stdint.h>
#include <stdlib.h>
// Implemented in the runtime for test purposes.
extern "C" bool Kotlin_Debugging_isThreadStateNative();
extern "C" void assertNativeThreadState() {
if (!Kotlin_Debugging_isThreadStateNative()) {
printf("Incorrect thread state. Expected native thread state.");
abort();
}
}
extern "C" void runInNewThread(void(*callback)(void)) {
std::thread t([callback]() {
callback();
});
t.join();
}
@@ -0,0 +1,20 @@
language = C
---
#include <stdint.h>
void assertNativeThreadState();
void runCallback(void(*callback)(void)) {
assertNativeThreadState();
callback();
assertNativeThreadState();
}
int32_t answer() {
assertNativeThreadState();
return 42;
}
void runInNewThread(void(*callback)(void));
@@ -0,0 +1,59 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
import kotlin.native.internal.Debugging
import kotlin.test.*
import kotlinx.cinterop.*
import threadStates.*
fun main() {
nativeCall()
callback()
nestedCalls()
directStaticCFunctionCall()
// TODO: Support runtime initialization for callbacks
// see: https://youtrack.jetbrains.com/issue/KT-44283
// callbackOnSeparateThread()
}
fun assertRunnableThreadState() {
assertTrue(Debugging.isThreadStateRunnable)
}
fun nativeCall() {
answer()
assertRunnableThreadState()
}
fun callback() {
runCallback(staticCFunction { ->
assertRunnableThreadState()
})
assertRunnableThreadState()
}
fun nestedCalls() {
runCallback(staticCFunction { ->
assertRunnableThreadState()
answer()
Unit
})
assertRunnableThreadState()
}
fun directStaticCFunctionCall() {
val funPtr = staticCFunction { ->
assertRunnableThreadState()
}
assertRunnableThreadState()
funPtr()
assertRunnableThreadState()
}
fun callbackOnSeparateThread() {
runInNewThread(staticCFunction { ->
assertRunnableThreadState()
})
}