From c15b1ec001233d346dcd4a85182fd086e2054394 Mon Sep 17 00:00:00 2001 From: Alexander Shabalin Date: Fri, 14 Jan 2022 12:20:30 +0000 Subject: [PATCH] [K/N] Remove certain pthread functions from runnable allow list ^KT-50713 Merge-request: KT-MR-5417 Merged-by: Alexander Shabalin --- .../runtime/src/main/cpp/Runtime.cpp | 3 ++ .../runtime/src/main/cpp/StackTrace.cpp | 3 ++ kotlin-native/runtime/src/main/cpp/Worker.cpp | 31 ++++++++++++++++--- .../runtime/src/mm/cpp/CallsChecker.cpp | 12 +------ 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/kotlin-native/runtime/src/main/cpp/Runtime.cpp b/kotlin-native/runtime/src/main/cpp/Runtime.cpp index bd09085968a..4cb3a31d3a2 100644 --- a/kotlin-native/runtime/src/main/cpp/Runtime.cpp +++ b/kotlin-native/runtime/src/main/cpp/Runtime.cpp @@ -245,6 +245,9 @@ void Kotlin_shutdownRuntime() { if (!needsFullShutdown) { auto lastStatus = compareAndSwap(&globalRuntimeStatus, kGlobalRuntimeRunning, kGlobalRuntimeShutdown); RuntimeAssert(lastStatus == kGlobalRuntimeRunning, "Invalid runtime status for shutdown"); + // The main thread is not doing anything Kotlin anymore, but will stick around to cleanup C++ globals and the like. + // Mark the thread native, and don't make the GC thread wait on it. + kotlin::SwitchThreadState(runtime->memoryState, kotlin::ThreadState::kNative); return; } diff --git a/kotlin-native/runtime/src/main/cpp/StackTrace.cpp b/kotlin-native/runtime/src/main/cpp/StackTrace.cpp index 2d997056375..3547f2aa050 100644 --- a/kotlin-native/runtime/src/main/cpp/StackTrace.cpp +++ b/kotlin-native/runtime/src/main/cpp/StackTrace.cpp @@ -91,6 +91,7 @@ int getSourceInfo(void* symbol, SourceInfo *result, int result_len) { // TODO: this implementation is just a hack, e.g. the result is inexact; // however it is better to have an inexact stacktrace than not to have any. NO_INLINE KStdVector kotlin::internal::GetCurrentStackTrace(size_t skipFrames) noexcept { + NativeOrUnregisteredThreadGuard guard(true); #if KONAN_NO_BACKTRACE return {}; #else @@ -133,6 +134,7 @@ NO_INLINE KStdVector kotlin::internal::GetCurrentStackTrace(size_t skipFr // TODO: this implementation is just a hack, e.g. the result is inexact; // however it is better to have an inexact stacktrace than not to have any. NO_INLINE size_t kotlin::internal::GetCurrentStackTrace(size_t skipFrames, std_support::span buffer) noexcept { + NativeOrUnregisteredThreadGuard guard(true); #if KONAN_NO_BACKTRACE return {}; #else @@ -237,6 +239,7 @@ KNativePtr adjustAddressForSourceInfo(KNativePtr address) { return address; } #endif KStdVector kotlin::GetStackTraceStrings(std_support::span stackTrace) noexcept { + NativeOrUnregisteredThreadGuard guard(true); #if KONAN_NO_BACKTRACE KStdVector strings; strings.push_back(""); diff --git a/kotlin-native/runtime/src/main/cpp/Worker.cpp b/kotlin-native/runtime/src/main/cpp/Worker.cpp index 2f717bb951a..1fff95e2c62 100644 --- a/kotlin-native/runtime/src/main/cpp/Worker.cpp +++ b/kotlin-native/runtime/src/main/cpp/Worker.cpp @@ -144,6 +144,7 @@ class Worker { kind_(kind), exceptionHandling_(exceptionHandling) { name_ = customName != nullptr ? CreateStablePointer(customName) : nullptr; + kotlin::ThreadStateGuard guard(ThreadState::kNative); pthread_mutex_init(&lock_, nullptr); pthread_cond_init(&cond_, nullptr); } @@ -245,9 +246,9 @@ void waitInNativeState(pthread_cond_t* cond, class Locker { public: - explicit Locker(pthread_mutex_t* lock, bool switchThreadState = true) : lock_(lock) { + explicit Locker(pthread_mutex_t* lock, bool switchThreadState = true) : lock_(lock), switchThreadState_(switchThreadState) { if (switchThreadState) { - kotlin::ThreadStateGuard guard(kotlin::ThreadState::kNative); + kotlin::ThreadStateGuard guard(kotlin::ThreadState::kNative, true); pthread_mutex_lock(lock_); } else { // We may need to create a locker when the current thread is already unregistered in the memory subsystem. @@ -255,28 +256,40 @@ public: pthread_mutex_lock(lock_); } } - Locker(pthread_mutex_t* lock, MemoryState* memoryState) : lock_(lock) { - kotlin::ThreadStateGuard guard(memoryState, kotlin::ThreadState::kNative); + Locker(pthread_mutex_t* lock, MemoryState* memoryState) : lock_(lock), memoryState_(memoryState) { + kotlin::ThreadStateGuard guard(memoryState, kotlin::ThreadState::kNative, true); pthread_mutex_lock(lock_); } ~Locker() { + kotlin::ThreadStateGuard guard; + if (switchThreadState_) { + if (memoryState_ != nullptr) { + guard = kotlin::ThreadStateGuard(memoryState_, ThreadState::kNative, true); + } else { + guard = kotlin::ThreadStateGuard(ThreadState::kNative, true); + } + } pthread_mutex_unlock(lock_); } private: pthread_mutex_t* lock_; + bool switchThreadState_ = true; + MemoryState* memoryState_ = nullptr; }; class Future { public: Future(KInt id) : state_(SCHEDULED), id_(id) { + kotlin::ThreadStateGuard guard(ThreadState::kNative); pthread_mutex_init(&lock_, nullptr); pthread_cond_init(&cond_, nullptr); } ~Future() { clear(); + kotlin::ThreadStateGuard guard(ThreadState::kNative); pthread_mutex_destroy(&lock_); pthread_cond_destroy(&cond_); } @@ -326,6 +339,7 @@ class Future { class State { public: State() { + kotlin::ThreadStateGuard guard(ThreadState::kNative); pthread_mutex_init(&lock_, nullptr); pthread_cond_init(&cond_, nullptr); @@ -335,6 +349,7 @@ class State { } ~State() { + kotlin::ThreadStateGuard guard(ThreadState::kNative); // TODO: some sanity check here? pthread_mutex_destroy(&lock_); pthread_cond_destroy(&cond_); @@ -527,6 +542,7 @@ class State { } void signalAnyFuture() { + kotlin::AssertThreadState(ThreadState::kNative); { Locker locker(&lock_); currentVersion_++; @@ -535,6 +551,7 @@ class State { } void signalAnyFuture(MemoryState* memoryState) { + kotlin::AssertThreadState(memoryState, ThreadState::kNative); { Locker locker(&lock_, memoryState); currentVersion_++; @@ -638,6 +655,7 @@ State* theState() { } void Future::storeResultUnlocked(KNativePtr result, bool ok) { + kotlin::ThreadStateGuard guard(ThreadState::kNative); { Locker locker(&lock_); state_ = ok ? COMPUTED : THROWN; @@ -651,6 +669,7 @@ void Future::storeResultUnlocked(KNativePtr result, bool ok) { } void Future::cancelUnlocked(MemoryState* memoryState) { + kotlin::ThreadStateGuard guard(memoryState, ThreadState::kNative); { Locker locker(&lock_, memoryState); state_ = CANCELLED; @@ -896,6 +915,7 @@ Worker::~Worker() { DisposeStablePointerFor(memoryState_, name_); } + kotlin::ThreadStateGuard guard(memoryState_, ThreadState::kNative); pthread_mutex_destroy(&lock_); pthread_cond_destroy(&cond_); } @@ -925,10 +945,12 @@ void* workerRoutine(void* argument) { } // namespace void Worker::startEventLoop() { + kotlin::ThreadStateGuard guard(ThreadState::kNative); pthread_create(&thread_, nullptr, workerRoutine, this); } void Worker::putJob(Job job, bool toFront) { + kotlin::ThreadStateGuard guard(ThreadState::kNative); Locker locker(&lock_); if (toFront) queue_.push_front(job); @@ -938,6 +960,7 @@ void Worker::putJob(Job job, bool toFront) { } void Worker::putDelayedJob(Job job) { + kotlin::ThreadStateGuard guard(ThreadState::kNative); Locker locker(&lock_); delayed_.insert(job); pthread_cond_signal(&cond_); diff --git a/kotlin-native/runtime/src/mm/cpp/CallsChecker.cpp b/kotlin-native/runtime/src/mm/cpp/CallsChecker.cpp index ee22c77fcd0..4efcb8449b8 100644 --- a/kotlin-native/runtime/src/mm/cpp/CallsChecker.cpp +++ b/kotlin-native/runtime/src/mm/cpp/CallsChecker.cpp @@ -144,18 +144,8 @@ extern "C" const char* Kotlin_callsCheckerGoodFunctionNames[] = { "unsetenv", "dispatch_once", - "\x01_pthread_cond_init", - "_pthread_cond_init", - "pthread_cond_broadcast", - "pthread_cond_destroy", - "pthread_cond_signal", - "pthread_cond_init", - "pthread_create", "pthread_equal", "pthread_main_np", - "pthread_mutex_destroy", - "pthread_mutex_init", - "pthread_mutex_unlock", "pthread_self", "+[NSMethodSignature signatureWithObjCTypes:]", @@ -374,4 +364,4 @@ extern "C" RUNTIME_NOTHROW RUNTIME_NODEBUG void Kotlin_mm_checkStateAtExternalFu RuntimeFail("Expected kNative thread state at call of function %s by function %s", callee, caller); } -#endif // KONAN_NO_EXTERNAL_CALLS_CHECKER \ No newline at end of file +#endif // KONAN_NO_EXTERNAL_CALLS_CHECKER