diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 5fe3a1c36d4..15f8d7b8a06 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -363,7 +363,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map constexpr int kInitialValue = 0; -constexpr int kNewValue = 0; - -#if defined(IS_LEGACY) -// Globals were reinitialized. -constexpr int kResultValue = kInitialValue; -#else -// Globals were kept. -constexpr int kResultValue = kNewValue; -#endif +constexpr int kNewValue = 1; +constexpr int kErrorValue = 2; int main() { std::thread main1([]() { - assert(testlib_symbols()->kotlin.root.readFromA() == kInitialValue); + assert(testlib_symbols()->kotlin.root.tryReadFromA(kErrorValue) == kInitialValue); testlib_symbols()->kotlin.root.writeToA(kNewValue); - assert(testlib_symbols()->kotlin.root.readFromA() == kNewValue); + assert(testlib_symbols()->kotlin.root.tryReadFromA(kErrorValue) == kNewValue); }); main1.join(); - std::thread main2([]() { assert(testlib_symbols()->kotlin.root.readFromA() == kResultValue); }); + std::thread main2([]() { +#if defined(IS_LEGACY) + // Globals were reinitialized. + assert(testlib_symbols()->kotlin.root.tryReadFromA(kErrorValue) == kInitialValue); +#else + // Globals are not accessible. + assert(testlib_symbols()->kotlin.root.tryReadFromA(kErrorValue) == kErrorValue); +#endif + }); main2.join(); return 0; diff --git a/runtime/src/legacymm/cpp/Memory.cpp b/runtime/src/legacymm/cpp/Memory.cpp index cc630e2b8ef..76a90f57d64 100644 --- a/runtime/src/legacymm/cpp/Memory.cpp +++ b/runtime/src/legacymm/cpp/Memory.cpp @@ -2019,12 +2019,6 @@ MemoryState* initMemory(bool firstRuntime) { #endif // USE_CYCLIC_GC memoryState->isMainThread = true; } - if (!firstRuntime && firstMemoryState) { - memoryState->isMainThread = true; - // This thread is now the main thread. And there was a previous main thread, because this is not the first runtime. - // Make sure this thread sees all the updates to Kotlin globals from the previous main thread. - synchronize(); - } return memoryState; } @@ -2032,18 +2026,13 @@ void deinitMemory(MemoryState* memoryState, bool destroyRuntime) { static int pendingDeinit = 0; atomicAdd(&pendingDeinit, 1); #if USE_GC + bool lastRuntime = atomicAdd(&aliveMemoryStatesCount, -1) == 0; switch (Kotlin_getDestroyRuntimeMode()) { case DESTROY_RUNTIME_LEGACY: - destroyRuntime = atomicAdd(&aliveMemoryStatesCount, -1) == 0; + destroyRuntime = lastRuntime; break; case DESTROY_RUNTIME_ON_SHUTDOWN: - if (!destroyRuntime && memoryState->isMainThread) { - // If we are not destroying the runtime but we were the main thread, publish all changes to Kotlin globals. - // This `synchronize` should be before `aliveMemoryStatesCount` decrement to synchronize with - // `initMemory` which does this in the reverse order. - synchronize(); - } - atomicAdd(&aliveMemoryStatesCount, -1); + // Nothing to do break; } bool checkLeaks = Kotlin_memoryLeakCheckerEnabled() && destroyRuntime; diff --git a/runtime/src/main/cpp/Runtime.cpp b/runtime/src/main/cpp/Runtime.cpp index 461de5f385e..9c81ded50df 100644 --- a/runtime/src/main/cpp/Runtime.cpp +++ b/runtime/src/main/cpp/Runtime.cpp @@ -31,6 +31,7 @@ struct InitNode { InitNode* next; }; +// This global is overriden by the compiler. RUNTIME_WEAK DestroyRuntimeMode Kotlin_destroyRuntimeMode = DESTROY_RUNTIME_ON_SHUTDOWN; DestroyRuntimeMode Kotlin_getDestroyRuntimeMode() {