[K/N] Add CallsCheckerIgnoreGuard
This commit is contained in:
committed by
Space Team
parent
39e97e5766
commit
43a7711fcc
@@ -8,6 +8,7 @@
|
||||
#include <cinttypes>
|
||||
#include <optional>
|
||||
|
||||
#include "CallsChecker.hpp"
|
||||
#include "CompilerConstants.hpp"
|
||||
#include "GlobalData.hpp"
|
||||
#include "GCImpl.hpp"
|
||||
@@ -90,7 +91,9 @@ void gc::ConcurrentMarkAndSweep::ThreadData::OnOOM(size_t size) noexcept {
|
||||
ScheduleAndWaitFullGC();
|
||||
}
|
||||
|
||||
NO_EXTERNAL_CALLS_CHECK void gc::ConcurrentMarkAndSweep::ThreadData::OnSuspendForGC() noexcept {
|
||||
void gc::ConcurrentMarkAndSweep::ThreadData::OnSuspendForGC() noexcept {
|
||||
CallsCheckerIgnoreGuard guard;
|
||||
|
||||
std::unique_lock lock(markingMutex);
|
||||
if (!markingRequested.load()) return;
|
||||
AutoReset scopedAssignMarking(&marking_, true);
|
||||
@@ -259,7 +262,7 @@ void gc::ConcurrentMarkAndSweep::WaitForThreadsReadyToMark() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
NO_EXTERNAL_CALLS_CHECK void gc::ConcurrentMarkAndSweep::CollectRootSetAndStartMarking(GCHandle gcHandle) noexcept {
|
||||
void gc::ConcurrentMarkAndSweep::CollectRootSetAndStartMarking(GCHandle gcHandle) noexcept {
|
||||
std::unique_lock lock(markingMutex);
|
||||
markingRequested = false;
|
||||
gc::collectRootSet<internal::MarkTraits>(
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace kotlin {
|
||||
|
||||
// Ignore thread state checker for the scope.
|
||||
//
|
||||
// Can be used to ignore specific call sites that are known to be safe.
|
||||
class CallsCheckerIgnoreGuard : private Pinned {
|
||||
public:
|
||||
ALWAYS_INLINE CallsCheckerIgnoreGuard() noexcept;
|
||||
ALWAYS_INLINE ~CallsCheckerIgnoreGuard();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <array>
|
||||
#include <cinttypes>
|
||||
|
||||
#include "CallsChecker.hpp"
|
||||
#include "Format.h"
|
||||
#include "KAssert.h"
|
||||
#include "Porting.h"
|
||||
@@ -104,7 +105,7 @@ private:
|
||||
|
||||
class StderrLogger : public logging::internal::Logger {
|
||||
public:
|
||||
NO_EXTERNAL_CALLS_CHECK void Log(logging::Level level, std_support::span<const char* const> tags, std::string_view message) const noexcept override {
|
||||
void Log(logging::Level level, std_support::span<const char* const> tags, std::string_view message) const noexcept override {
|
||||
konan::consoleErrorUtf8(message.data(), message.size());
|
||||
}
|
||||
};
|
||||
@@ -204,6 +205,8 @@ void logging::Log(Level level, std::initializer_list<const char*> tags, const ch
|
||||
}
|
||||
|
||||
void logging::VLog(Level level, std::initializer_list<const char*> tags, const char* format, std::va_list args) noexcept {
|
||||
CallsCheckerIgnoreGuard guard;
|
||||
|
||||
[[clang::no_destroy]] static DefaultLogContext ctx(compiler::runtimeLogs());
|
||||
RuntimeAssert(tags.size() > 0, "Cannot Log without tags");
|
||||
std_support::span<const char* const> tagsSpan(std::data(tags), std::size(tags));
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "CallsChecker.hpp"
|
||||
|
||||
#ifndef KONAN_NO_EXTERNAL_CALLS_CHECKER
|
||||
#include <string_view>
|
||||
#include <cstring>
|
||||
@@ -10,6 +12,7 @@
|
||||
#include "KAssert.h"
|
||||
#include "Memory.h"
|
||||
#include "Porting.h"
|
||||
#include "StackTrace.hpp"
|
||||
#include "ThreadData.hpp"
|
||||
#include "ThreadRegistry.hpp"
|
||||
#include "ExecFormat.h"
|
||||
@@ -321,6 +324,8 @@ private:
|
||||
constexpr int MSG_SEND_TO_NULL = -1;
|
||||
constexpr int CALLED_LLVM_BUILTIN = -2;
|
||||
|
||||
thread_local size_t ignoreGuardsCount = 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -335,15 +340,10 @@ constexpr int CALLED_LLVM_BUILTIN = -2;
|
||||
*/
|
||||
extern "C" RUNTIME_NOTHROW RUNTIME_NODEBUG void Kotlin_mm_checkStateAtExternalFunctionCall(const char* caller, const char *callee, const void *calleePtr) noexcept {
|
||||
if (reinterpret_cast<int64_t>(calleePtr) == MSG_SEND_TO_NULL) return; // objc_sendMsg called on nil, it does nothing, so it's ok
|
||||
if (ignoreGuardsCount != 0) return;
|
||||
if (konan::isOnThreadExitNotSetOrAlreadyStarted()) return;
|
||||
static thread_local bool recursiveCallGuard = false;
|
||||
if (recursiveCallGuard) return;
|
||||
if (!mm::ThreadRegistry::Instance().IsCurrentThreadRegistered()) return;
|
||||
struct unlockGuard {
|
||||
unlockGuard() { recursiveCallGuard = true; }
|
||||
~unlockGuard() { recursiveCallGuard = false; }
|
||||
} guard;
|
||||
|
||||
CallsCheckerIgnoreGuard recursiveGuard;
|
||||
|
||||
auto actualState = GetThreadState();
|
||||
if (actualState == ThreadState::kNative) {
|
||||
@@ -367,7 +367,14 @@ extern "C" RUNTIME_NOTHROW RUNTIME_NODEBUG void Kotlin_mm_checkStateAtExternalFu
|
||||
return;
|
||||
}
|
||||
|
||||
PrintStackTraceStderr();
|
||||
RuntimeFail("Expected kNative thread state at call of function %s by function %s", callee, caller);
|
||||
}
|
||||
|
||||
CallsCheckerIgnoreGuard::CallsCheckerIgnoreGuard() noexcept { ++ignoreGuardsCount; }
|
||||
CallsCheckerIgnoreGuard::~CallsCheckerIgnoreGuard() { --ignoreGuardsCount; }
|
||||
|
||||
#else
|
||||
kotlin::CallsCheckerIgnoreGuard::CallsCheckerIgnoreGuard() noexcept {}
|
||||
kotlin::CallsCheckerIgnoreGuard::~CallsCheckerIgnoreGuard() {}
|
||||
#endif // KONAN_NO_EXTERNAL_CALLS_CHECKER
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#include "CallsChecker.hpp"
|
||||
#include "Logging.hpp"
|
||||
#include "StackTrace.hpp"
|
||||
|
||||
@@ -50,7 +51,9 @@ THREAD_LOCAL_VARIABLE bool gSuspensionRequestedByCurrentThread = false;
|
||||
|
||||
std::atomic<bool> kotlin::mm::internal::gSuspensionRequested = false;
|
||||
|
||||
NO_EXTERNAL_CALLS_CHECK void kotlin::mm::ThreadSuspensionData::suspendIfRequestedSlowPath() noexcept {
|
||||
void kotlin::mm::ThreadSuspensionData::suspendIfRequestedSlowPath() noexcept {
|
||||
CallsCheckerIgnoreGuard guard;
|
||||
|
||||
if (IsThreadSuspensionRequested()) {
|
||||
threadData_.gc().OnSuspendForGC();
|
||||
std::unique_lock lock(gSuspensionMutex);
|
||||
@@ -65,7 +68,9 @@ NO_EXTERNAL_CALLS_CHECK void kotlin::mm::ThreadSuspensionData::suspendIfRequeste
|
||||
}
|
||||
}
|
||||
|
||||
NO_EXTERNAL_CALLS_CHECK bool kotlin::mm::RequestThreadsSuspension() noexcept {
|
||||
bool kotlin::mm::RequestThreadsSuspension() noexcept {
|
||||
CallsCheckerIgnoreGuard guard;
|
||||
|
||||
RuntimeAssert(gSuspensionRequestedByCurrentThread == false, "Current thread already suspended threads.");
|
||||
{
|
||||
std::unique_lock lock(gSuspensionMutex);
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
bool suspended() noexcept { return suspended_; }
|
||||
|
||||
NO_EXTERNAL_CALLS_CHECK void suspendIfRequested() noexcept {
|
||||
void suspendIfRequested() noexcept {
|
||||
if (IsThreadSuspensionRequested()) {
|
||||
suspendIfRequestedSlowPath();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user