Make SingleThreadMarkAndSweep support multiple threads

This commit is contained in:
Alexander Shabalin
2021-05-21 13:59:22 +03:00
committed by Space
parent 10ae9c511b
commit 9ebba93dd9
15 changed files with 556 additions and 127 deletions
+45 -80
View File
@@ -708,7 +708,7 @@ task runtime_basic_simd(type: KonanLocalTest) {
task runtime_worker_random(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Uses workers.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
!(isExperimentalMM && project.testTarget == 'mingw_x64') // TODO: Fix Experimental MM performance on Windows.
source = "runtime/basic/worker_random.kt"
}
@@ -826,170 +826,150 @@ task empty_substring(type: KonanLocalTest) {
}
standaloneTest("cleaner_basic") {
enabled = (project.testTarget != 'wasm32') && // Cleaners need workers
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Cleaners need workers
source = "runtime/basic/cleaner_basic.kt"
flags = ['-tr', '-Xopt-in=kotlin.native.internal.InternalForKotlinNative']
}
standaloneTest("cleaner_workers") {
enabled = (project.testTarget != 'wasm32') && // Cleaners need workers
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Cleaners need workers
source = "runtime/basic/cleaner_workers.kt"
flags = ['-tr', '-Xopt-in=kotlin.native.internal.InternalForKotlinNative']
}
standaloneTest("cleaner_in_main_with_checker") {
enabled = (project.testTarget != 'wasm32') && // Cleaners need workers
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Cleaners need workers
source = "runtime/basic/cleaner_in_main_with_checker.kt"
goldValue = "42\n"
}
standaloneTest("cleaner_in_main_without_checker") {
enabled = (project.testTarget != 'wasm32') && // Cleaners need workers
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Cleaners need workers
source = "runtime/basic/cleaner_in_main_without_checker.kt"
goldValue = ""
}
standaloneTest("cleaner_leak_without_checker") {
enabled = (project.testTarget != 'wasm32') && // Cleaners need workers
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Cleaners need workers
source = "runtime/basic/cleaner_leak_without_checker.kt"
goldValue = ""
}
standaloneTest("cleaner_leak_with_checker") {
enabled = (project.testTarget != 'wasm32') && // Cleaners need workers
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Cleaners need workers
source = "runtime/basic/cleaner_leak_with_checker.kt"
expectedExitStatusChecker = { it != 0 }
outputChecker = { s -> (s =~ /Cleaner (0x)?[0-9a-fA-F]+ was disposed during program exit/).find() }
}
standaloneTest("cleaner_in_tls_main_without_checker") {
enabled = (project.testTarget != 'wasm32') && // Cleaners need workers
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Cleaners need workers
source = "runtime/basic/cleaner_in_tls_main_without_checker.kt"
}
standaloneTest("cleaner_in_tls_main_with_checker") {
enabled = (project.testTarget != 'wasm32') && // Cleaners need workers
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Cleaners need workers
source = "runtime/basic/cleaner_in_tls_main_with_checker.kt"
expectedExitStatusChecker = { it != 0 }
outputChecker = { s -> (s =~ /Cleaner (0x)?[0-9a-fA-F]+ was disposed during program exit/).find() }
}
standaloneTest("cleaner_in_tls_worker") {
enabled = (project.testTarget != 'wasm32') && // Cleaners need workers
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Cleaners need workers
source = "runtime/basic/cleaner_in_tls_worker.kt"
flags = ['-Xopt-in=kotlin.native.internal.InternalForKotlinNative']
}
standaloneTest("worker_bound_reference0") {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
!(isExperimentalMM && project.testTarget == 'mingw_x64') // TODO: Fix Experimental MM performance on Windows.
source = "runtime/concurrent/worker_bound_reference0.kt"
flags = ['-tr']
}
task worker0(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Workers need pthreads.
goldValue = "Got Input processed\nOK\n"
source = "runtime/workers/worker0.kt"
}
task worker1(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
!(isExperimentalMM && project.testTarget == 'mingw_x64') // TODO: Fix Experimental MM performance on Windows.
goldValue = "OK\n"
source = "runtime/workers/worker1.kt"
}
task worker2(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
!(isExperimentalMM && project.testTarget == 'mingw_x64') // TODO: Fix Experimental MM performance on Windows.
goldValue = "OK\n"
source = "runtime/workers/worker2.kt"
}
task worker3(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Workers need pthreads.
goldValue = "OK\n"
source = "runtime/workers/worker3.kt"
}
task worker4(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Workers need pthreads.
goldValue = "Got 42\nOK\n"
source = "runtime/workers/worker4.kt"
}
// This tests changes main thread worker queue state, so better be executed alone.
standaloneTest("worker5") {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Workers need pthreads.
goldValue = "Got 3\nOK\n"
source = "runtime/workers/worker5.kt"
}
task worker6(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Workers need pthreads.
goldValue = "Got 42\nOK\n"
source = "runtime/workers/worker6.kt"
}
task worker7(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Workers need pthreads.
goldValue = "Input\nGot kotlin.Unit\nOK\n"
source = "runtime/workers/worker7.kt"
}
task worker8(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Workers need pthreads.
goldValue = "SharedData(string=Hello, int=10, member=SharedDataMember(double=0.1))\nGot kotlin.Unit\nOK\n"
source = "runtime/workers/worker8.kt"
}
task worker9(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Workers need pthreads.
goldValue = "zzz\n42\nOK\nfirst 2\nsecond 3\nfrozen OK\n"
source = "runtime/workers/worker9.kt"
}
task worker10(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Workers need pthreads.
goldValue = "OK\ntrue\ntrue\n"
source = "runtime/workers/worker10.kt"
}
task worker11(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
!(isExperimentalMM && project.testTarget == 'mingw_x64') // TODO: Fix Experimental MM performance on Windows.
goldValue = "OK\n"
source = "runtime/workers/worker11.kt"
}
standaloneTest("worker_threadlocal_no_leak") {
disabled = (project.testTarget == 'wasm32') || // Needs pthreads.
isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
disabled = (project.testTarget == 'wasm32') // Needs pthreads.
source = "runtime/workers/worker_threadlocal_no_leak.kt"
}
task freeze0(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // No workers on WASM.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // No workers on WASM.
goldValue = "frozen bit is true\n" +
"Worker: SharedData(string=Hello, int=10, member=SharedDataMember(double=0.1))\n" +
"Main: SharedData(string=Hello, int=10, member=SharedDataMember(double=0.1))\n" +
@@ -1010,8 +990,7 @@ task freeze_stress(type: KonanLocalTest) {
}
task freeze2(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // No exceptions on WASM.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // No exceptions on WASM.
goldValue =
"Worker 1: Hello world\n" + "Worker2: 42\n" +
"Worker3: 239.0\n" + "Worker4: a\n" + "OK\n"
@@ -1019,8 +998,7 @@ task freeze2(type: KonanLocalTest) {
}
task freeze3(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // No exceptions on WASM.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // No exceptions on WASM.
goldValue = "OK\n"
source = "runtime/workers/freeze3.kt"
}
@@ -1044,7 +1022,7 @@ task freeze6(type: KonanLocalTest) {
task atomic0(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
!(isExperimentalMM && project.testTarget == 'mingw_x64') // TODO: Fix Experimental MM performance on Windows.
goldValue = "35\n" + "20\n" + "OK\n"
source = "runtime/workers/atomic0.kt"
}
@@ -1056,8 +1034,7 @@ standaloneTest("atomic1") {
}
task lazy0(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Workers need pthreads.
goldValue = "OK\n"
source = "runtime/workers/lazy0.kt"
}
@@ -1078,29 +1055,25 @@ standaloneTest("lazy3") {
}
task mutableData1(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads. Need exceptions
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Workers need pthreads. Need exceptions
source = "runtime/workers/mutableData1.kt"
}
task enumIdentity(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
enabled = (project.testTarget != 'wasm32') // Workers need pthreads.
goldValue = "true\n"
source = "runtime/workers/enum_identity.kt"
}
standaloneTest("leakWorker") {
disabled = (project.testTarget == 'wasm32') || // Needs pthreads.
isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
disabled = (project.testTarget == 'wasm32') // Needs pthreads.
source = "runtime/workers/leak_worker.kt"
expectedExitStatusChecker = { it != 0 }
outputChecker = { s -> s.contains("Unfinished workers detected, 1 workers leaked!") }
}
standaloneTest("leakMemoryWithWorkerTermination") {
disabled = (project.testTarget == 'wasm32') || // Needs pthreads.
isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
disabled = (project.testTarget == 'wasm32') // Needs pthreads.
source = "runtime/workers/leak_memory_with_worker_termination.kt"
if (!isExperimentalMM) { // Experimental MM will not report memory leaks.
@@ -2841,7 +2814,7 @@ task initializers5(type: KonanLocalTest) {
task initializers6(type: KonanLocalTest) {
disabled = (project.testTarget == 'wasm32') || // Needs workers.
isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
(isExperimentalMM && project.testTarget == 'mingw_x64') // TODO: Fix Experimental MM performance on Windows.
source = "runtime/basic/initializers6.kt"
}
@@ -2939,8 +2912,7 @@ standaloneTest("memory_only_gc") {
}
task memory_stable_ref_cross_thread_check(type: KonanLocalTest) {
disabled = (project.testTarget == 'wasm32') || // Needs workers.
isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
disabled = (project.testTarget == 'wasm32') // Needs workers.
source = "runtime/memory/stable_ref_cross_thread_check.kt"
}
@@ -4224,15 +4196,13 @@ dynamicTest("interop_kt43502") {
}
interopTest("interop_leakMemoryWithRunningThreadUnchecked") {
disabled = (project.testTarget == 'wasm32') || // No interop for wasm yet.
isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
interop = 'leakMemoryWithRunningThread'
source = "interop/leakMemoryWithRunningThread/unchecked.kt"
}
interopTest("interop_leakMemoryWithRunningThreadChecked") {
disabled = (project.testTarget == 'wasm32') || // No interop for wasm yet.
isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
interop = 'leakMemoryWithRunningThread'
source = "interop/leakMemoryWithRunningThread/checked.kt"
expectedExitStatusChecker = { it != 0 }
@@ -4452,7 +4422,7 @@ if (PlatformInfo.isAppleTarget(project)) {
}
interopTest("interop_objc_illegal_sharing_with_weak") {
enabled = !isExperimentalMM // Experimental MM doesn't support multiple mutators and thread state switching for ObjC interop yet.
enabled = !isExperimentalMM // Experimental MM doesn't support thread state switching for ObjC interop yet.
source = "interop/objc/illegal_sharing_with_weak/main.kt"
interop = 'objc_illegal_sharing_with_weak'
@@ -4465,7 +4435,7 @@ if (PlatformInfo.isAppleTarget(project)) {
}
interopTest("interop_objc_kt42172") {
enabled = !isExperimentalMM // Experimental MM doesn't support multiple mutators and thread state switching for ObjC interop yet.
enabled = !isExperimentalMM // Experimental MM doesn't support thread state switching for ObjC interop yet.
source = "interop/objc/kt42172/main.kt"
interop = "objc_kt42172"
flags = ['-Xopt-in=kotlin.native.internal.InternalForKotlinNative']
@@ -4516,7 +4486,7 @@ standaloneTest("interop_zlib") {
standaloneTest("interop_objc_illegal_sharing") {
disabled = !isAppleTarget(project) ||
isExperimentalMM // Experimental MM doesn't support multiple mutators and thread state switching for ObjC interop yet.
isExperimentalMM // Experimental MM doesn't support thread state switching for ObjC interop yet.
source = "interop/objc/illegal_sharing.kt"
UtilsKt.dependsOnPlatformLibs(it)
if (isExperimentalMM) {
@@ -4601,8 +4571,7 @@ dynamicTest("interop_kt42397") {
}
dynamicTest("interop_cleaners_main_thread") {
disabled = (project.target.name != project.hostName) ||
isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
disabled = (project.target.name != project.hostName)
source = "interop/cleaners/cleaners.kt"
cSource = "$projectDir/interop/cleaners/main_thread.cpp"
clangTool = "clang++"
@@ -4611,8 +4580,7 @@ dynamicTest("interop_cleaners_main_thread") {
}
dynamicTest("interop_cleaners_second_thread") {
disabled = (project.target.name != project.hostName) ||
isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
disabled = (project.target.name != project.hostName)
source = "interop/cleaners/cleaners.kt"
cSource = "$projectDir/interop/cleaners/second_thread.cpp"
clangTool = "clang++"
@@ -4621,8 +4589,7 @@ dynamicTest("interop_cleaners_second_thread") {
}
dynamicTest("interop_cleaners_leak") {
disabled = (project.target.name != project.hostName) ||
isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
disabled = (project.target.name != project.hostName)
source = "interop/cleaners/cleaners.kt"
cSource = "$projectDir/interop/cleaners/leak.cpp"
clangTool = "clang++"
@@ -4641,8 +4608,7 @@ dynamicTest("interop_migrating_main_thread_legacy") {
}
dynamicTest("interop_migrating_main_thread") {
disabled = (project.target.name != project.hostName) ||
isExperimentalMM // Experimental MM doesn't support multiple mutators yet.
disabled = (project.target.name != project.hostName)
source = "interop/migrating_main_thread/lib.kt"
flags = ['-Xdestroy-runtime-mode=on-shutdown']
if (isExperimentalMM) {
@@ -5218,8 +5184,7 @@ private void configureStdlibTest(KonanGTest task, boolean inWorker) {
task.useFilter = false
task.testLogger = KonanTest.Logger.GTEST
task.finalizedBy("resultsTask")
task.enabled = (project.testTarget != 'wasm32') && // Uses exceptions
(!inWorker || !ext.isExperimentalMM) // Experimental MM doesn't support multiple mutators yet.
task.enabled = (project.testTarget != 'wasm32') // Uses exceptions
}
/**
@@ -1073,6 +1073,11 @@ class TestSharedRefs {
}
}
// This will free `object1` and release+dealloc its associated `Deinit` which nils `Deinit.object2`
ValuesKt.gc()
// This will free `object2`.
ValuesKt.gc()
try assertTrue(Deinit.weakVar2 === nil)
}
@@ -1403,10 +1408,7 @@ class ValuesTests : SimpleTestProvider {
test("TestInvalidIdentifiers", testInvalidIdentifiers)
test("TestDeprecation", testDeprecation)
test("TestWeakRefs", testWeakRefs)
if !ValuesKt.isExperimentalMM {
// Experimental MM doesn't support multiple mutators yet.
test("TestSharedRefs", TestSharedRefs().test)
}
test("TestSharedRefs", TestSharedRefs().test)
test("TestClassTypeCheck", testClassTypeCheck)
test("TestInterfaceTypeCheck", testInterfaceTypeCheck)
test("TestGH3503_1", testGH3503_1)
@@ -1419,9 +1421,6 @@ class ValuesTests : SimpleTestProvider {
test("TestFakeOverrideInInterface", testFakeOverrideInInterface)
// Stress test, must remain the last one:
if !ValuesKt.isExperimentalMM {
// Experimental MM doesn't support multiple mutators yet.
test("TestGH2931", testGH2931)
}
test("TestGH2931", testGH2931)
}
}
@@ -25,6 +25,7 @@ fun main() {
worker.requestTermination().result
waitWorkerTermination(worker)
GC.collect()
waitCleanerWorker()
assertEquals(42, value.value)
@@ -59,27 +59,36 @@ data class Data(var int: Int)
assertFailsWith<InvalidMutabilityException> { a8[1] = 2.0 }
// Ensure that String and integral boxes are frozen by default, by passing local to the worker.
val hasToBeFrozen = Platform.memoryModel == MemoryModel.STRICT
val worker = Worker.start()
var data: Any = "Hello" + " " + "world"
assert(data.isFrozen)
if (hasToBeFrozen) {
assertTrue(data.isFrozen)
}
worker.execute(TransferMode.SAFE, { data } ) {
input -> println("Worker 1: $input")
}.result
data = 42
assert(data.isFrozen)
if (hasToBeFrozen) {
assertTrue(data.isFrozen)
}
worker.execute(TransferMode.SAFE, { data } ) {
input -> println("Worker2: $input")
}.result
data = 239.0
assert(data.isFrozen)
if (hasToBeFrozen) {
assertTrue(data.isFrozen)
}
worker.execute(TransferMode.SAFE, { data } ) {
input -> println("Worker3: $input")
}.result
data = 'a'
assert(data.isFrozen)
if (hasToBeFrozen) {
assertTrue(data.isFrozen)
}
worker.execute(TransferMode.SAFE, { data } ) {
input -> println("Worker4: $input")
}.result
@@ -87,4 +96,4 @@ data class Data(var int: Int)
worker.requestTermination().result
println("OK")
}
}