diff --git a/kotlin-native/runtime/src/main/cpp/Porting.cpp b/kotlin-native/runtime/src/main/cpp/Porting.cpp index 710f76fb0d6..4253d1c46a7 100644 --- a/kotlin-native/runtime/src/main/cpp/Porting.cpp +++ b/kotlin-native/runtime/src/main/cpp/Porting.cpp @@ -192,13 +192,17 @@ struct DestructorRecord { static void onThreadExitCallback(void* value) { DestructorRecord* record = reinterpret_cast(value); + pthread_setspecific(terminationKey, nullptr); while (record != nullptr) { record->destructor(record->destructorParameter); auto next = record->next; free(record); record = next; } - pthread_setspecific(terminationKey, nullptr); +} + +bool isOnThreadExitNotSetOrAlreadyStarted() { + return terminationKey != 0 && pthread_getspecific(terminationKey) == nullptr; } #if KONAN_LINUX diff --git a/kotlin-native/runtime/src/main/cpp/Porting.h b/kotlin-native/runtime/src/main/cpp/Porting.h index 7fda6ad949c..78ebeb9c4e5 100644 --- a/kotlin-native/runtime/src/main/cpp/Porting.h +++ b/kotlin-native/runtime/src/main/cpp/Porting.h @@ -41,6 +41,7 @@ RUNTIME_NORETURN void exit(int32_t status); // Thread control. void onThreadExit(void (*destructor)(void*), void* destructorParameter); +bool isOnThreadExitNotSetOrAlreadyStarted(); // String/byte operations. // memcpy/memmove/memcmp are not here intentionally, as frequently implemented/optimized diff --git a/kotlin-native/runtime/src/mm/cpp/ThreadRegistry.cpp b/kotlin-native/runtime/src/mm/cpp/ThreadRegistry.cpp index 2f4b44cadd1..55ed241d16f 100644 --- a/kotlin-native/runtime/src/mm/cpp/ThreadRegistry.cpp +++ b/kotlin-native/runtime/src/mm/cpp/ThreadRegistry.cpp @@ -20,7 +20,7 @@ mm::ThreadRegistry::Node* mm::ThreadRegistry::RegisterCurrentThread() noexcept { auto* threadDataNode = list_.Emplace(pthread_self()); AssertThreadState(threadDataNode->Get(), ThreadState::kNative); Node*& currentDataNode = currentThreadDataNode_; - RuntimeAssert(currentDataNode == nullptr, "This thread already had some data assigned to it."); + RuntimeAssert(!IsCurrentThreadRegistered(), "This thread already had some data assigned to it."); currentDataNode = threadDataNode; return threadDataNode; } diff --git a/kotlin-native/runtime/src/mm/cpp/ThreadRegistry.hpp b/kotlin-native/runtime/src/mm/cpp/ThreadRegistry.hpp index 7eac82a73c5..f32c799e8b6 100644 --- a/kotlin-native/runtime/src/mm/cpp/ThreadRegistry.hpp +++ b/kotlin-native/runtime/src/mm/cpp/ThreadRegistry.hpp @@ -41,6 +41,8 @@ public: ALWAYS_INLINE ThreadData* CurrentThreadData() const noexcept; Node* CurrentThreadDataNode() const noexcept { return currentThreadDataNode_; } + bool IsCurrentThreadRegistered() const noexcept { return currentThreadDataNode_ != nullptr; } + class TestSupport { public: static void ClearCurrentThreadData() { currentThreadDataNode_ = nullptr; }