[K/N] Add CallsCheckerIgnoreGuard

This commit is contained in:
Alexander Shabalin
2023-06-14 14:06:14 +02:00
committed by Space Team
parent 39e97e5766
commit 43a7711fcc
6 changed files with 51 additions and 13 deletions
@@ -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();
}