[K/N] Spread use of atomic_ref + group concurrent stuff in single dir
diff --git a/kotlin-native/runtime/src/alloc/custom/cpp/AtomicStackTest.cpp b/kotlin-native/runtime/src/alloc/custom/cpp/AtomicStackTest.cpp
index 9e66397..751161c 100644
--- a/kotlin-native/runtime/src/alloc/custom/cpp/AtomicStackTest.cpp
+++ b/kotlin-native/runtime/src/alloc/custom/cpp/AtomicStackTest.cpp
@@ -11,7 +11,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
using namespace kotlin;
diff --git a/kotlin-native/runtime/src/alloc/legacy/cpp/ObjectFactory.hpp b/kotlin-native/runtime/src/alloc/legacy/cpp/ObjectFactory.hpp
index 7ce81c9..2df21b7 100644
--- a/kotlin-native/runtime/src/alloc/legacy/cpp/ObjectFactory.hpp
+++ b/kotlin-native/runtime/src/alloc/legacy/cpp/ObjectFactory.hpp
@@ -15,7 +15,7 @@
#include "Alignment.hpp"
#include "FinalizerHooks.hpp"
#include "Memory.h"
-#include "Mutex.hpp"
+#include "concurrent/Mutex.hpp"
#include "Porting.h"
#include "TypeLayout.hpp"
#include "Types.h"
diff --git a/kotlin-native/runtime/src/alloc/legacy/cpp/ObjectFactoryTest.cpp b/kotlin-native/runtime/src/alloc/legacy/cpp/ObjectFactoryTest.cpp
index 7127420..0c66525 100644
--- a/kotlin-native/runtime/src/alloc/legacy/cpp/ObjectFactoryTest.cpp
+++ b/kotlin-native/runtime/src/alloc/legacy/cpp/ObjectFactoryTest.cpp
@@ -17,7 +17,7 @@
#include "ObjectFactoryAllocator.hpp"
#include "ObjectOps.hpp"
#include "ObjectTestSupport.hpp"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "TestSupport.hpp"
#include "Types.h"
diff --git a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMark.hpp b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMark.hpp
index 61a43e9..995e4fd 100644
--- a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMark.hpp
+++ b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMark.hpp
@@ -11,7 +11,7 @@
#include "GCStatistics.hpp"
#include "ManuallyScoped.hpp"
#include "ObjectData.hpp"
-#include "ParallelProcessor.hpp"
+#include "concurrent/ParallelProcessor.hpp"
#include "SafePoint.hpp"
#include "ThreadRegistry.hpp"
#include "Utils.hpp"
diff --git a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.hpp b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.hpp
index 43422f4..e7865d9 100644
--- a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.hpp
+++ b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.hpp
@@ -20,7 +20,7 @@
#include "MarkAndSweepUtils.hpp"
#include "ObjectData.hpp"
#include "ConcurrentMark.hpp"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "ThreadData.hpp"
#include "Types.h"
#include "Utils.hpp"
diff --git a/kotlin-native/runtime/src/gc/common/cpp/FinalizerProcessor.hpp b/kotlin-native/runtime/src/gc/common/cpp/FinalizerProcessor.hpp
index 252d8dd..23009c8 100644
--- a/kotlin-native/runtime/src/gc/common/cpp/FinalizerProcessor.hpp
+++ b/kotlin-native/runtime/src/gc/common/cpp/FinalizerProcessor.hpp
@@ -14,7 +14,7 @@
#include "KAssert.h"
#include "Memory.h"
#include "Runtime.h"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "Utils.hpp"
#include "Logging.hpp"
diff --git a/kotlin-native/runtime/src/gc/common/cpp/GCStatistics.cpp b/kotlin-native/runtime/src/gc/common/cpp/GCStatistics.cpp
index 1bce3d1..9793962 100644
--- a/kotlin-native/runtime/src/gc/common/cpp/GCStatistics.cpp
+++ b/kotlin-native/runtime/src/gc/common/cpp/GCStatistics.cpp
@@ -11,7 +11,7 @@
#include "Allocator.hpp"
#include "Logging.hpp"
-#include "Mutex.hpp"
+#include "concurrent/Mutex.hpp"
#include "Porting.h"
#include "ThreadData.hpp"
#include "Types.h"
diff --git a/kotlin-native/runtime/src/gc/pmcs/cpp/ParallelMark.hpp b/kotlin-native/runtime/src/gc/pmcs/cpp/ParallelMark.hpp
index 7b6173e..c56b72a 100644
--- a/kotlin-native/runtime/src/gc/pmcs/cpp/ParallelMark.hpp
+++ b/kotlin-native/runtime/src/gc/pmcs/cpp/ParallelMark.hpp
@@ -11,7 +11,7 @@
#include "GCStatistics.hpp"
#include "ManuallyScoped.hpp"
#include "ObjectData.hpp"
-#include "ParallelProcessor.hpp"
+#include "concurrent/ParallelProcessor.hpp"
#include "ThreadRegistry.hpp"
#include "Utils.hpp"
diff --git a/kotlin-native/runtime/src/gc/pmcs/cpp/ParallelMarkConcurrentSweep.hpp b/kotlin-native/runtime/src/gc/pmcs/cpp/ParallelMarkConcurrentSweep.hpp
index 17ec844..4fa8637 100644
--- a/kotlin-native/runtime/src/gc/pmcs/cpp/ParallelMarkConcurrentSweep.hpp
+++ b/kotlin-native/runtime/src/gc/pmcs/cpp/ParallelMarkConcurrentSweep.hpp
@@ -20,7 +20,7 @@
#include "MarkAndSweepUtils.hpp"
#include "ObjectData.hpp"
#include "ParallelMark.hpp"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "ThreadData.hpp"
#include "Types.h"
#include "Utils.hpp"
diff --git a/kotlin-native/runtime/src/gcScheduler/aggressive/cpp/SafePointTracker.hpp b/kotlin-native/runtime/src/gcScheduler/aggressive/cpp/SafePointTracker.hpp
index 72493a7..9b47f8c 100644
--- a/kotlin-native/runtime/src/gcScheduler/aggressive/cpp/SafePointTracker.hpp
+++ b/kotlin-native/runtime/src/gcScheduler/aggressive/cpp/SafePointTracker.hpp
@@ -11,7 +11,7 @@
#include "CallsChecker.hpp"
#include "KAssert.h"
#include "Logging.hpp"
-#include "Mutex.hpp"
+#include "concurrent/Mutex.hpp"
#include "StackTrace.hpp"
namespace kotlin::gcScheduler::internal {
diff --git a/kotlin-native/runtime/src/main/cpp/Atomic.h b/kotlin-native/runtime/src/main/cpp/Atomic.h
deleted file mode 100644
index ce986c2..0000000
--- a/kotlin-native/runtime/src/main/cpp/Atomic.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#ifndef RUNTIME_ATOMIC_H
-#define RUNTIME_ATOMIC_H
-
-#include "Common.h"
-
-template <typename T>
-ALWAYS_INLINE inline T atomicAdd(volatile T* where, T what) {
- return __sync_add_and_fetch(where, what);
-}
-
-#pragma clang diagnostic push
-
-#if (KONAN_ANDROID || KONAN_IOS || KONAN_WATCHOS || KONAN_LINUX) && (KONAN_ARM32 || KONAN_X86)
-// On 32-bit Android clang generates library calls for "large" atomic operations
-// and warns about "significant performance penalty". See more details here:
-// https://github.com/llvm/llvm-project/blob/ce56e1a1cc5714f4af5675dd963cfebed766d9e1/clang/lib/CodeGen/CGAtomic.cpp#L775
-// Ignore these warnings:
-#pragma clang diagnostic ignored "-Watomic-alignment"
-#endif
-
-// as if (std::atomic<T> where).compare_exchange_strong(expectedValue, newValue)
-template <typename T>
-ALWAYS_INLINE inline bool compareExchange(volatile T& where, T &expectedValue, T newValue) {
-#ifdef KONAN_NO_64BIT_ATOMIC
- static_assert(sizeof(T) <= 4);
-#endif
- return __atomic_compare_exchange_n(&where, &expectedValue, newValue, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
-}
-
-template <typename T>
-ALWAYS_INLINE inline T compareAndSwap(volatile T* where, T expectedValue, T newValue) {
- compareExchange(*where, expectedValue, newValue);
- return expectedValue;
-}
-
-template <typename T>
-ALWAYS_INLINE inline bool compareAndSet(volatile T* where, T expectedValue, T newValue) {
- return compareExchange(*where, expectedValue, newValue);
-}
-
-
-template <int model = __ATOMIC_SEQ_CST, typename T>
-ALWAYS_INLINE inline void atomicSet(volatile T* where, T what) {
-#ifdef KONAN_NO_64BIT_ATOMIC
- static_assert(sizeof(T) <= 4);
-#endif
- __atomic_store(where, &what, model);
-}
-
-template <typename T>
-ALWAYS_INLINE inline void atomicSetRelease(volatile T* where, T what) {
- return atomicSet<__ATOMIC_RELEASE>(where, what);
-}
-
-
-template <int model = __ATOMIC_SEQ_CST, typename T>
-ALWAYS_INLINE inline T atomicGet(volatile const T* where) {
-#ifdef KONAN_NO_64BIT_ATOMIC
- static_assert(sizeof(T) <= 4);
-#endif
- T what;
- __atomic_load(where, &what, model);
- return what;
-}
-
-template <typename T>
-ALWAYS_INLINE inline T atomicGetAcquire(volatile const T* where) {
- return atomicGet<__ATOMIC_ACQUIRE>(where);
-}
-
-template <typename T>
-ALWAYS_INLINE inline T atomicGetRelaxed(volatile const T* where) {
- return atomicGet<__ATOMIC_RELAXED>(where);
-}
-
-#pragma clang diagnostic pop
-
-static ALWAYS_INLINE inline void synchronize() {
- __sync_synchronize();
-}
-
-#endif // RUNTIME_ATOMIC_H
diff --git a/kotlin-native/runtime/src/main/cpp/BoundedQueueTest.cpp b/kotlin-native/runtime/src/main/cpp/BoundedQueueTest.cpp
index 5cc812f..d624692 100644
--- a/kotlin-native/runtime/src/main/cpp/BoundedQueueTest.cpp
+++ b/kotlin-native/runtime/src/main/cpp/BoundedQueueTest.cpp
@@ -11,7 +11,7 @@
#include "IntrusiveList.hpp"
-#include "ParallelProcessor.hpp"
+#include "concurrent/ParallelProcessor.hpp"
#include "SingleThreadExecutor.hpp"
#include "TestSupport.hpp"
diff --git a/kotlin-native/runtime/src/main/cpp/Cleaner.cpp b/kotlin-native/runtime/src/main/cpp/Cleaner.cpp
index bb48243..57078a9 100644
--- a/kotlin-native/runtime/src/main/cpp/Cleaner.cpp
+++ b/kotlin-native/runtime/src/main/cpp/Cleaner.cpp
@@ -4,7 +4,7 @@
*/
#include "Cleaner.h"
-
+#include "concurrent/CAS.hpp"
#include "Memory.h"
#include "Runtime.h"
#include "Worker.h"
@@ -24,10 +24,10 @@
constexpr KInt kCleanerWorkerInitializing = -1;
constexpr KInt kCleanerWorkerShutdown = -2;
-KInt globalCleanerWorker = kCleanerWorkerUninitialized;
+std::atomic globalCleanerWorker = kCleanerWorkerUninitialized;
void disposeCleaner(CleanerImpl* thiz) {
- auto worker = atomicGet(&globalCleanerWorker);
+ auto worker = globalCleanerWorker.load();
RuntimeAssert(
worker != kCleanerWorkerUninitialized && worker != kCleanerWorkerInitializing,
"Cleaner worker must've been initialized by now");
@@ -66,10 +66,10 @@
// This loop may spin waiting for a proper worker state. Switch to the native thread state.
kotlin::ThreadStateGuard guard(kotlin::ThreadState::kNative);
do {
- worker = atomicGet(&globalCleanerWorker);
+ worker = globalCleanerWorker.load();
RuntimeAssert(worker != kCleanerWorkerShutdown, "Cleaner worker must not be shutdown twice");
if (worker == kCleanerWorkerUninitialized) {
- if (!compareAndSet(&globalCleanerWorker, kCleanerWorkerUninitialized, kCleanerWorkerShutdown)) {
+ if (!globalCleanerWorker.compare_exchange_weak(worker, kCleanerWorkerShutdown)) {
// Someone is trying to initialize the worker. Try again.
continue;
}
@@ -89,7 +89,7 @@
RuntimeAssert(worker > 0, "Cleaner worker must be fully initialized here");
- atomicSet(&globalCleanerWorker, kCleanerWorkerShutdown);
+ globalCleanerWorker.store(kCleanerWorkerShutdown);
Kotlin_CleanerImpl_shutdownCleanerWorker(worker, executeScheduledCleaners);
WaitNativeWorkerTermination(worker);
}
@@ -99,15 +99,15 @@
// This loop may spin waiting for a proper worker state. Switch to the native thread state.
kotlin::ThreadStateGuard guard(kotlin::ThreadState::kNative);
do {
- worker = atomicGet(&globalCleanerWorker);
+ worker = globalCleanerWorker.load();
RuntimeAssert(worker != kCleanerWorkerShutdown, "Cleaner worker must not have been shutdown");
if (worker == kCleanerWorkerUninitialized) {
- if (!compareAndSet(&globalCleanerWorker, kCleanerWorkerUninitialized, kCleanerWorkerInitializing)) {
+ if (!globalCleanerWorker.compare_exchange_weak(worker, kCleanerWorkerInitializing)) {
// Someone else is trying to initialize the worker. Try again.
continue;
}
worker = kotlin::CallWithThreadState<kotlin::ThreadState::kRunnable>(Kotlin_CleanerImpl_createCleanerWorker);
- if (!compareAndSet(&globalCleanerWorker, kCleanerWorkerInitializing, worker)) {
+ if (!compareAndSet(globalCleanerWorker, kCleanerWorkerInitializing, worker)) {
RuntimeCheck(false, "Someone interrupted worker initializing");
}
// Worker is initialized.
@@ -128,5 +128,5 @@
}
void ResetCleanerWorkerForTests() {
- atomicSet(&globalCleanerWorker, kCleanerWorkerUninitialized);
+ globalCleanerWorker.store(kCleanerWorkerUninitialized);
}
diff --git a/kotlin-native/runtime/src/main/cpp/CleanerTest.cpp b/kotlin-native/runtime/src/main/cpp/CleanerTest.cpp
index a2148ae..5a33fb0 100644
--- a/kotlin-native/runtime/src/main/cpp/CleanerTest.cpp
+++ b/kotlin-native/runtime/src/main/cpp/CleanerTest.cpp
@@ -11,7 +11,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "Atomic.h"
#include "TestSupport.hpp"
#include "TestSupportCompilerGenerated.hpp"
#include "Types.h"
@@ -38,23 +37,23 @@
EXPECT_CALL(*createCleanerWorkerMock, Call()).Times(1).WillOnce(testing::Return(workerId));
- int startedThreads = 0;
- bool allowRunning = false;
+ std::atomic startedThreads = 0;
+ std::atomic allowRunning = false;
std::vector<std::future<KInt>> futures;
for (int i = 0; i < threadCount; ++i) {
auto future = std::async(std::launch::async, [&startedThreads, &allowRunning]() {
// Thread state switching requires initilized memory subsystem.
ScopedMemoryInit init;
- atomicAdd(&startedThreads, 1);
- while (!atomicGet(&allowRunning)) {
+ ++startedThreads;
+ while (!allowRunning.load()) {
}
return Kotlin_CleanerImpl_getCleanerWorker();
});
futures.push_back(std::move(future));
}
- while (atomicGet(&startedThreads) != threadCount) {
+ while (startedThreads.load() != threadCount) {
}
- atomicSet(&allowRunning, true);
+ allowRunning = true;
std::vector<KInt> values;
for (auto& future : futures) {
values.push_back(future.get());
diff --git a/kotlin-native/runtime/src/main/cpp/ClockTest.cpp b/kotlin-native/runtime/src/main/cpp/ClockTest.cpp
index 7a0a296..38dfe26 100644
--- a/kotlin-native/runtime/src/main/cpp/ClockTest.cpp
+++ b/kotlin-native/runtime/src/main/cpp/ClockTest.cpp
@@ -17,7 +17,7 @@
#include "gtest/gtest.h"
#include "ClockTestSupport.hpp"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "TestSupport.hpp"
using namespace kotlin;
diff --git a/kotlin-native/runtime/src/main/cpp/ConditionVariableTest.cpp b/kotlin-native/runtime/src/main/cpp/ConditionVariableTest.cpp
index c906a88..e78417f 100644
--- a/kotlin-native/runtime/src/main/cpp/ConditionVariableTest.cpp
+++ b/kotlin-native/runtime/src/main/cpp/ConditionVariableTest.cpp
@@ -12,7 +12,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "TestSupport.hpp"
using namespace kotlin;
diff --git a/kotlin-native/runtime/src/main/cpp/Exceptions.cpp b/kotlin-native/runtime/src/main/cpp/Exceptions.cpp
index 1fb2808..b10dfc0 100644
--- a/kotlin-native/runtime/src/main/cpp/Exceptions.cpp
+++ b/kotlin-native/runtime/src/main/cpp/Exceptions.cpp
@@ -23,9 +23,12 @@
#include "KAssert.h"
#include "Exceptions.h"
+
+
#include "ExecFormat.h"
#include "Memory.h"
-#include "Mutex.hpp"
+#include <concurrent/CAS.hpp>
+#include "concurrent/Mutex.hpp"
#include "Porting.h"
#include "Types.h"
#include "Utils.hpp"
@@ -36,40 +39,41 @@
extern "C" void ReportUnhandledException(KRef exception);
void ThrowException(KRef exception) {
- RuntimeAssert(exception != nullptr && IsInstanceInternal(exception, theThrowableTypeInfo),
- "Throwing something non-throwable");
- ExceptionObjHolder::Throw(exception);
+ RuntimeAssert(exception != nullptr && IsInstanceInternal(exception, theThrowableTypeInfo),
+ "Throwing something non-throwable");
+ ExceptionObjHolder::Throw(exception);
}
void HandleCurrentExceptionWhenLeavingKotlinCode() {
- try {
- std::rethrow_exception(std::current_exception());
- } catch (ExceptionObjHolder& e) {
- std::terminate(); // Terminate when it's a kotlin exception.
- }
+ try {
+ std::rethrow_exception(std::current_exception());
+ } catch (ExceptionObjHolder& e) {
+ std::terminate(); // Terminate when it's a kotlin exception.
+ }
}
namespace {
-
class {
/**
* Timeout 5 sec for concurrent (second) terminate attempt to give a chance the first one to finish.
* If the terminate handler hangs for 5 sec it is probably fatally broken, so let's do abnormal _Exit in that case.
*/
unsigned int timeoutSec = 5;
- int terminatingFlag = 0;
- public:
- template <class Fun> RUNTIME_NORETURN void operator()(Fun block) {
- if (compareAndSet(&terminatingFlag, 0, 1)) {
- block();
- // block() is supposed to be NORETURN, otherwise go to normal abort()
- std::abort();
- } else {
- kotlin::NativeOrUnregisteredThreadGuard guard(/* reentrant = */ true);
- sleep(timeoutSec);
- // We come here when another terminate handler hangs for 5 sec, that looks fatally broken. Go to forced exit now.
- }
- _Exit(EXIT_FAILURE); // force exit
+ std::atomic <int> terminatingFlag = 0;
+
+public:
+ template<class Fun>
+ RUNTIME_NORETURN void operator()(Fun block) {
+ if (compareAndSet(terminatingFlag, 0, 1)) {
+ block();
+ // block() is supposed to be NORETURN, otherwise go to normal abort()
+ std::abort();
+ } else {
+ kotlin::NativeOrUnregisteredThreadGuard guard(/* reentrant = */ true);
+ sleep(timeoutSec);
+ // We come here when another terminate handler hangs for 5 sec, that looks fatally broken. Go to forced exit now.
+ }
+ _Exit(EXIT_FAILURE); // force exit
}
} concurrentTerminateWrapper;
@@ -92,7 +96,6 @@
terminateWithUnhandledException(e.GetExceptionObject());
}
}
-
} // namespace
ALWAYS_INLINE RUNTIME_NOTHROW OBJ_GETTER(Kotlin_getExceptionObject, void* holder) {
@@ -102,68 +105,70 @@
namespace {
// Copy, move and assign would be safe, but not much useful, so let's delete all (rule of 5)
class TerminateHandler : private kotlin::Pinned {
- RUNTIME_NORETURN static void queuedHandler() {
- concurrentTerminateWrapper([]() {
- // Not a Kotlin exception - call default handler
- instance().queuedHandler_();
- });
- }
+ RUNTIME_NORETURN static void queuedHandler() {
+ concurrentTerminateWrapper([]() {
+ // Not a Kotlin exception - call default handler
+ instance().queuedHandler_();
+ });
+ }
- // In fact, it's safe to call my_handler directly from outside: it will do the job and then invoke original handler,
- // even if it has not been initialized yet. So one may want to make it public and/or not the class member
- RUNTIME_NORETURN static void kotlinHandler() {
- if (auto currentException = std::current_exception()) {
- try {
- std::rethrow_exception(currentException);
- } catch (ExceptionObjHolder& e) {
- // Both thread states are allowed here because there is no guarantee that
- // C++ runtime will unwind the stack for an unhandled exception. Thus there
- // is no guarantee that state switches made on interop borders will be rolled back.
+ // In fact, it's safe to call my_handler directly from outside: it will do the job and then invoke original handler,
+ // even if it has not been initialized yet. So one may want to make it public and/or not the class member
+ RUNTIME_NORETURN static void kotlinHandler() {
+ if (auto currentException = std::current_exception()) {
+ try {
+ std::rethrow_exception(currentException);
+ } catch (ExceptionObjHolder& e) {
+ // Both thread states are allowed here because there is no guarantee that
+ // C++ runtime will unwind the stack for an unhandled exception. Thus there
+ // is no guarantee that state switches made on interop borders will be rolled back.
- // Moreover, a native code can catch an exception thrown by a Kotlin callback,
- // store it to a global and then re-throw it in another thread which is not attached
- // to the Kotlin runtime. To handle this case, use the CalledFromNativeGuard.
- // TODO: Forbid throwing Kotlin exceptions through the interop border to get rid of this case.
- kotlin::CalledFromNativeGuard guard(/* reentrant = */ true);
- processUnhandledException(e.GetExceptionObject());
- terminateWithUnhandledException(e.GetExceptionObject());
- } catch (...) {
- // Not a Kotlin exception - call default handler
- kotlin::NativeOrUnregisteredThreadGuard guard(/* reentrant = */ true);
- queuedHandler();
+ // Moreover, a native code can catch an exception thrown by a Kotlin callback,
+ // store it to a global and then re-throw it in another thread which is not attached
+ // to the Kotlin runtime. To handle this case, use the CalledFromNativeGuard.
+ // TODO: Forbid throwing Kotlin exceptions through the interop border to get rid of this case.
+ kotlin::CalledFromNativeGuard guard(/* reentrant = */ true);
+ processUnhandledException(e.GetExceptionObject());
+ terminateWithUnhandledException(e.GetExceptionObject());
+ } catch (...) {
+ // Not a Kotlin exception - call default handler
+ kotlin::NativeOrUnregisteredThreadGuard guard(/* reentrant = */ true);
+ queuedHandler();
+ }
}
- }
- // Come here in case of direct terminate() call or unknown exception - go to default terminate handler.
- kotlin::NativeOrUnregisteredThreadGuard guard(/* reentrant = */ true);
- queuedHandler();
- }
+ // Come here in case of direct terminate() call or unknown exception - go to default terminate handler.
+ kotlin::NativeOrUnregisteredThreadGuard guard(/* reentrant = */ true);
+ queuedHandler();
+ }
- using QH = __attribute__((noreturn)) void(*)();
- QH queuedHandler_;
+ using QH = __attribute__((noreturn)) void(*)();
+ QH queuedHandler_;
- /// Use machinery like Meyers singleton to provide thread safety
- TerminateHandler()
- : queuedHandler_((QH)std::set_terminate(kotlinHandler)) {}
+ /// Use machinery like Meyers singleton to provide thread safety
+ TerminateHandler()
+ : queuedHandler_((QH) std::set_terminate(kotlinHandler)) {
+ }
- static TerminateHandler& instance() {
- static TerminateHandler singleton [[clang::no_destroy]];
- return singleton;
- }
+ static TerminateHandler& instance() {
+ static TerminateHandler singleton [[clang::no_destroy]];
+ return singleton;
+ }
- // Dtor might be in use to restore original handler. However, consequent install
- // will not reconstruct handler anyway, so let's keep dtor deleted to avoid confusion.
- ~TerminateHandler() = delete;
+ // Dtor might be in use to restore original handler. However, consequent install
+ // will not reconstruct handler anyway, so let's keep dtor deleted to avoid confusion.
+ ~TerminateHandler() = delete;
+
public:
- /// First call will do the job, all consequent will do nothing.
- static void install() {
- instance(); // Use side effect of warming up
- }
+ /// First call will do the job, all consequent will do nothing.
+ static void install() {
+ instance(); // Use side effect of warming up
+ }
};
} // anon namespace
// Use one public function to limit access to the class declaration
void SetKonanTerminateHandler() {
- TerminateHandler::install();
+ TerminateHandler::install();
}
extern "C" void RUNTIME_NORETURN Kotlin_terminateWithUnhandledException(KRef exception) {
diff --git a/kotlin-native/runtime/src/main/cpp/ExceptionsTest.cpp b/kotlin-native/runtime/src/main/cpp/ExceptionsTest.cpp
index fb25e03..d8105b9 100644
--- a/kotlin-native/runtime/src/main/cpp/ExceptionsTest.cpp
+++ b/kotlin-native/runtime/src/main/cpp/ExceptionsTest.cpp
@@ -13,7 +13,7 @@
#include "Memory.h"
#include "ObjectTestSupport.hpp"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "TestSupportCompilerGenerated.hpp"
#include "TestSupport.hpp"
diff --git a/kotlin-native/runtime/src/main/cpp/Memory.h b/kotlin-native/runtime/src/main/cpp/Memory.h
index 9ff035f..636e019 100644
--- a/kotlin-native/runtime/src/main/cpp/Memory.h
+++ b/kotlin-native/runtime/src/main/cpp/Memory.h
@@ -18,13 +18,13 @@
#define RUNTIME_MEMORY_H
#include <utility>
+#include <std_support/AtomicRef.hpp>
#include "Alignment.hpp"
#include "KAssert.h"
#include "Common.h"
#include "TypeInfo.h"
#include "TypeLayout.hpp"
-#include "Atomic.h"
#include "PointerBits.h"
#include "Utils.hpp"
@@ -61,8 +61,8 @@
}
}
- TypeInfo* typeInfoOrMetaRelaxed() const { return atomicGetRelaxed(&typeInfoOrMeta_);}
- TypeInfo* typeInfoOrMetaAcquire() const { return atomicGetAcquire(&typeInfoOrMeta_);}
+ TypeInfo* typeInfoOrMetaRelaxed() const { return kotlin::std_support::atomic_ref{typeInfoOrMeta_}.load(std::memory_order_relaxed);}
+ TypeInfo* typeInfoOrMetaAcquire() const { return kotlin::std_support::atomic_ref{typeInfoOrMeta_}.load(std::memory_order_acquire);}
/**
* Formally, this code data races with installing ExtraObject. Even though, we are okey, with reading
@@ -77,7 +77,8 @@
* Hardware guaranties on many supported platforms doesn't allow this to happen.
*/
const TypeInfo* type_info() const {
- const TypeInfo* typeInfo = atomicGetRelaxed(&clearPointerBits(typeInfoOrMetaRelaxed(), OBJECT_TAG_MASK)->typeInfo_);
+ auto atomicTypeInfoPtr = kotlin::std_support::atomic_ref{clearPointerBits(typeInfoOrMetaRelaxed(), OBJECT_TAG_MASK)->typeInfo_};
+ const TypeInfo* typeInfo = atomicTypeInfoPtr.load(std::memory_order_relaxed);
RuntimeAssert(typeInfo != nullptr, "TypeInfo ptr in object %p in null", this);
return typeInfo;
}
diff --git a/kotlin-native/runtime/src/main/cpp/MemorySharedRefs.hpp b/kotlin-native/runtime/src/main/cpp/MemorySharedRefs.hpp
index 89a1a5f..2252cfd 100644
--- a/kotlin-native/runtime/src/main/cpp/MemorySharedRefs.hpp
+++ b/kotlin-native/runtime/src/main/cpp/MemorySharedRefs.hpp
@@ -10,7 +10,7 @@
#include "ManuallyScoped.hpp"
#include "Memory.h"
-#include "Mutex.hpp"
+#include "concurrent/Mutex.hpp"
// TODO: Generalize for uses outside this file.
enum class ErrorPolicy {
diff --git a/kotlin-native/runtime/src/main/cpp/MultiSourceQueue.hpp b/kotlin-native/runtime/src/main/cpp/MultiSourceQueue.hpp
index d6dbabf..a0b5623 100644
--- a/kotlin-native/runtime/src/main/cpp/MultiSourceQueue.hpp
+++ b/kotlin-native/runtime/src/main/cpp/MultiSourceQueue.hpp
@@ -11,7 +11,7 @@
#include <memory>
#include <mutex>
-#include "Mutex.hpp"
+#include "concurrent/Mutex.hpp"
#include "Utils.hpp"
namespace kotlin {
diff --git a/kotlin-native/runtime/src/main/cpp/MultiSourceQueueTest.cpp b/kotlin-native/runtime/src/main/cpp/MultiSourceQueueTest.cpp
index 780a9a6..0b7ba20 100644
--- a/kotlin-native/runtime/src/main/cpp/MultiSourceQueueTest.cpp
+++ b/kotlin-native/runtime/src/main/cpp/MultiSourceQueueTest.cpp
@@ -12,7 +12,7 @@
#include "gtest/gtest.h"
#include "StdAllocatorTestSupport.hpp"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "TestSupport.hpp"
using namespace kotlin;
diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExport.mm b/kotlin-native/runtime/src/main/cpp/ObjCExport.mm
index a49a70c..6243d45 100644
--- a/kotlin-native/runtime/src/main/cpp/ObjCExport.mm
+++ b/kotlin-native/runtime/src/main/cpp/ObjCExport.mm
@@ -35,7 +35,7 @@
#import "ObjCExportPrivate.h"
#import "ObjCMMAPI.h"
#import "Runtime.h"
-#import "Mutex.hpp"
+#import "concurrent/Mutex.hpp"
#import "Exceptions.h"
#import "Natives.h"
diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.mm b/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.mm
index b3f0dab..b059d7b 100644
--- a/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.mm
+++ b/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.mm
@@ -24,7 +24,7 @@
#import "ObjCExport.h"
#import "Porting.h"
#import "Runtime.h"
-#import "Mutex.hpp"
+#import "concurrent/Mutex.hpp"
#import "ObjCExportErrors.h"
diff --git a/kotlin-native/runtime/src/main/cpp/ObjCInterop.mm b/kotlin-native/runtime/src/main/cpp/ObjCInterop.mm
index 42476a0..1c428d4 100644
--- a/kotlin-native/runtime/src/main/cpp/ObjCInterop.mm
+++ b/kotlin-native/runtime/src/main/cpp/ObjCInterop.mm
@@ -25,7 +25,7 @@
#include "ObjCMMAPI.h"
#include "StackTrace.hpp"
#include "Types.h"
-#include "Mutex.hpp"
+#include "concurrent/Mutex.hpp"
using namespace kotlin;
diff --git a/kotlin-native/runtime/src/main/cpp/ReferenceOps.hpp b/kotlin-native/runtime/src/main/cpp/ReferenceOps.hpp
index 047f71b7..0b10bc4 100644
--- a/kotlin-native/runtime/src/main/cpp/ReferenceOps.hpp
+++ b/kotlin-native/runtime/src/main/cpp/ReferenceOps.hpp
@@ -72,10 +72,10 @@
}
ALWAYS_INLINE auto atomic() noexcept {
- return std_support::atomic_ref<ObjHeader*>{ref_};
+ return std_support::atomic_ref{ref_};
}
ALWAYS_INLINE auto atomic() const noexcept {
- return std_support::atomic_ref<ObjHeader*>{ref_};
+ return std_support::atomic_ref{ref_};
}
ALWAYS_INLINE ObjHeader* loadAtomic(std::memory_order order) const noexcept {
diff --git a/kotlin-native/runtime/src/main/cpp/RepeatedTimer.hpp b/kotlin-native/runtime/src/main/cpp/RepeatedTimer.hpp
index fe1b000..0fbc2dd 100644
--- a/kotlin-native/runtime/src/main/cpp/RepeatedTimer.hpp
+++ b/kotlin-native/runtime/src/main/cpp/RepeatedTimer.hpp
@@ -11,7 +11,7 @@
#include "Clock.hpp"
#include "KAssert.h"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "Utils.hpp"
namespace kotlin {
diff --git a/kotlin-native/runtime/src/main/cpp/Runtime.cpp b/kotlin-native/runtime/src/main/cpp/Runtime.cpp
index f736f61..0da2dd9 100644
--- a/kotlin-native/runtime/src/main/cpp/Runtime.cpp
+++ b/kotlin-native/runtime/src/main/cpp/Runtime.cpp
@@ -3,7 +3,7 @@
* that can be found in the LICENSE file.
*/
-#include "Atomic.h"
+#include "concurrent/CAS.hpp"
#include "Cleaner.h"
#include "CompilerConstants.hpp"
#include "Exceptions.h"
@@ -73,7 +73,7 @@
return ::runtimeState != kInvalidRuntime;
}
-volatile int aliveRuntimesCount = 0;
+std::atomic<int> aliveRuntimesCount = 0;
enum GlobalRuntimeStatus {
kGlobalRuntimeUninitialized = 0,
@@ -81,7 +81,7 @@
kGlobalRuntimeShutdown,
};
-volatile GlobalRuntimeStatus globalRuntimeStatus = kGlobalRuntimeUninitialized;
+std::atomic<GlobalRuntimeStatus> globalRuntimeStatus = kGlobalRuntimeUninitialized;
RuntimeState* initRuntime() {
SetKonanTerminateHandler();
@@ -96,13 +96,13 @@
kotlin::ThreadStateGuard stateGuard;
switch (kotlin::compiler::destroyRuntimeMode()) {
case kotlin::compiler::DestroyRuntimeMode::kLegacy:
- compareAndSwap(&globalRuntimeStatus, kGlobalRuntimeUninitialized, kGlobalRuntimeRunning);
+ compareAndSwap(globalRuntimeStatus, kGlobalRuntimeUninitialized, kGlobalRuntimeRunning);
result->memoryState = InitMemory(false); // The argument will be ignored for legacy DestroyRuntimeMode
// Switch thread state because worker and globals inits require the runnable state.
// This call may block if GC requested suspending threads.
stateGuard = kotlin::ThreadStateGuard(result->memoryState, kotlin::ThreadState::kRunnable);
result->worker = WorkerInit(result->memoryState);
- firstRuntime = atomicAdd(&aliveRuntimesCount, 1) == 1;
+ firstRuntime = ++aliveRuntimesCount == 1;
if (!kotlin::kSupportsMultipleMutators && !firstRuntime) {
konan::consoleErrorf("This GC implementation does not support multiple mutator threads.");
std::abort();
@@ -111,8 +111,8 @@
case kotlin::compiler::DestroyRuntimeMode::kOnShutdown:
// First update `aliveRuntimesCount` and then update `globalRuntimeStatus`, for synchronization with
// runtime shutdown, which does it the other way around.
- atomicAdd(&aliveRuntimesCount, 1);
- auto lastStatus = compareAndSwap(&globalRuntimeStatus, kGlobalRuntimeUninitialized, kGlobalRuntimeRunning);
+ ++aliveRuntimesCount;
+ auto lastStatus = compareAndSwap(globalRuntimeStatus, kGlobalRuntimeUninitialized, kGlobalRuntimeRunning);
if (Kotlin_forceCheckedShutdown()) {
RuntimeAssert(lastStatus != kGlobalRuntimeShutdown, "Kotlin runtime was shut down. Cannot create new runtimes.");
}
@@ -157,7 +157,7 @@
// TODO: This may in fact reallocate TLS without guarantees that it'll be deallocated again.
::runtimeState = state;
RestoreMemory(state->memoryState);
- bool lastRuntime = atomicAdd(&aliveRuntimesCount, -1) == 0;
+ bool lastRuntime = --aliveRuntimesCount == 0;
switch (kotlin::compiler::destroyRuntimeMode()) {
case kotlin::compiler::DestroyRuntimeMode::kLegacy:
destroyRuntime = lastRuntime;
@@ -233,7 +233,7 @@
break;
}
if (!needsFullShutdown) {
- auto lastStatus = compareAndSwap(&globalRuntimeStatus, kGlobalRuntimeRunning, kGlobalRuntimeShutdown);
+ 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.
@@ -254,7 +254,7 @@
ShutdownCleaners(Kotlin_cleanersLeakCheckerEnabled());
// Cleaners are now done, disallow new runtimes.
- auto lastStatus = compareAndSwap(&globalRuntimeStatus, kGlobalRuntimeRunning, kGlobalRuntimeShutdown);
+ auto lastStatus = compareAndSwap(globalRuntimeStatus, kGlobalRuntimeRunning, kGlobalRuntimeShutdown);
RuntimeAssert(lastStatus == kGlobalRuntimeRunning, "Invalid runtime status for shutdown");
bool canDestroyRuntime = true;
@@ -271,7 +271,7 @@
}
// Now check for existence of any other runtimes.
- auto otherRuntimesCount = atomicGet(&aliveRuntimesCount) - knownRuntimes;
+ auto otherRuntimesCount = aliveRuntimesCount.load() - knownRuntimes;
RuntimeAssert(otherRuntimesCount >= 0, "Cannot be negative");
if (Kotlin_forceCheckedShutdown()) {
if (otherRuntimesCount > 0) {
@@ -451,14 +451,14 @@
{
kotlin::ThreadStateGuard guard(kotlin::ThreadState::kNative);
do {
- localState = atomicGetAcquire(state);
+ localState = std_support::atomic_ref{*state}.load(std::memory_order_acquire);
} while (localState != FILE_INITIALIZED && localState != FILE_FAILED_TO_INITIALIZE);
}
if (localState == FILE_FAILED_TO_INITIALIZE) ThrowFileFailedToInitializeException(nullptr);
}
NO_INLINE void CallInitGlobalPossiblyLock(int* state, void (*init)()) {
- int localState = atomicGetAcquire(state);
+ int localState = std_support::atomic_ref{*state}.load(std::memory_order_acquire);
if (localState == FILE_INITIALIZED) return;
if (localState == FILE_FAILED_TO_INITIALIZE)
ThrowFileFailedToInitializeException(nullptr);
@@ -469,7 +469,7 @@
}
return;
}
- if (compareAndSwap(state, FILE_NOT_INITIALIZED, FILE_BEING_INITIALIZED | (threadId << 2)) == FILE_NOT_INITIALIZED) {
+ if (compareAndSwap(std_support::atomic_ref{*state}, FILE_NOT_INITIALIZED, FILE_BEING_INITIALIZED | (threadId << 2)) == FILE_NOT_INITIALIZED) {
// actual initialization
try {
CurrentFrameGuard guard;
@@ -477,10 +477,10 @@
} catch (ExceptionObjHolder& e) {
ObjHolder holder;
auto *exception = Kotlin_getExceptionObject(&e, holder.slot());
- atomicSetRelease(state, FILE_FAILED_TO_INITIALIZE);
+ std_support::atomic_ref{*state}.store(FILE_FAILED_TO_INITIALIZE, std::memory_order_release);
ThrowFileFailedToInitializeException(exception);
}
- atomicSetRelease(state, FILE_INITIALIZED);
+ std_support::atomic_ref{*state}.store(FILE_INITIALIZED, std::memory_order_release);
} else {
CallInitGlobalAwaitInitialized(state);
}
diff --git a/kotlin-native/runtime/src/main/cpp/SingleLockList.hpp b/kotlin-native/runtime/src/main/cpp/SingleLockList.hpp
index 8d54009..e08d830 100644
--- a/kotlin-native/runtime/src/main/cpp/SingleLockList.hpp
+++ b/kotlin-native/runtime/src/main/cpp/SingleLockList.hpp
@@ -12,7 +12,7 @@
#include <mutex>
#include <type_traits>
-#include "Mutex.hpp"
+#include "concurrent/Mutex.hpp"
#include "Utils.hpp"
#include "std_support/Memory.hpp"
diff --git a/kotlin-native/runtime/src/main/cpp/SingleLockListTest.cpp b/kotlin-native/runtime/src/main/cpp/SingleLockListTest.cpp
index b59c9c2..ae1c4e5 100644
--- a/kotlin-native/runtime/src/main/cpp/SingleLockListTest.cpp
+++ b/kotlin-native/runtime/src/main/cpp/SingleLockListTest.cpp
@@ -14,7 +14,7 @@
#include "gtest/gtest.h"
#include "StdAllocatorTestSupport.hpp"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "TestSupport.hpp"
using namespace kotlin;
diff --git a/kotlin-native/runtime/src/main/cpp/SingleThreadExecutor.hpp b/kotlin-native/runtime/src/main/cpp/SingleThreadExecutor.hpp
index cabebb2..c0e22fb 100644
--- a/kotlin-native/runtime/src/main/cpp/SingleThreadExecutor.hpp
+++ b/kotlin-native/runtime/src/main/cpp/SingleThreadExecutor.hpp
@@ -12,7 +12,7 @@
#include <mutex>
#include <shared_mutex>
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "Utils.hpp"
namespace kotlin {
diff --git a/kotlin-native/runtime/src/main/cpp/TestSupport.hpp b/kotlin-native/runtime/src/main/cpp/TestSupport.hpp
index 72975b0..76ee77a 100644
--- a/kotlin-native/runtime/src/main/cpp/TestSupport.hpp
+++ b/kotlin-native/runtime/src/main/cpp/TestSupport.hpp
@@ -9,7 +9,7 @@
#include "Memory.h"
#include "Runtime.h"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
namespace kotlin {
diff --git a/kotlin-native/runtime/src/main/cpp/concurrent/CAS.hpp b/kotlin-native/runtime/src/main/cpp/concurrent/CAS.hpp
new file mode 100644
index 0000000..1c95b95
--- /dev/null
+++ b/kotlin-native/runtime/src/main/cpp/concurrent/CAS.hpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2010-2024 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.
+ */
+
+#pragma once
+
+#include "std_support/AtomicRef.hpp"
+
+template<typename T, typename Atomic>
+ALWAYS_INLINE T compareAndSwap(Atomic&& atomic, T expectedValue, T newValue) {
+ atomic.compare_exchange_strong(expectedValue, newValue);
+ return expectedValue;
+}
+
+template<typename T, typename Atomic>
+ALWAYS_INLINE bool compareAndSet(Atomic&& atomic, T expectedValue, T newValue) {
+ return atomic.compare_exchange_strong(expectedValue, newValue);
+}
diff --git a/kotlin-native/runtime/src/main/cpp/Mutex.hpp b/kotlin-native/runtime/src/main/cpp/concurrent/Mutex.hpp
similarity index 98%
rename from kotlin-native/runtime/src/main/cpp/Mutex.hpp
rename to kotlin-native/runtime/src/main/cpp/concurrent/Mutex.hpp
index 195f011..0948f61 100644
--- a/kotlin-native/runtime/src/main/cpp/Mutex.hpp
+++ b/kotlin-native/runtime/src/main/cpp/concurrent/Mutex.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2017 JetBrains s.r.o.
+ * Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/kotlin-native/runtime/src/main/cpp/MutexTest.cpp b/kotlin-native/runtime/src/main/cpp/concurrent/MutexTest.cpp
similarity index 97%
rename from kotlin-native/runtime/src/main/cpp/MutexTest.cpp
rename to kotlin-native/runtime/src/main/cpp/concurrent/MutexTest.cpp
index ef3e292..efdfd9f 100644
--- a/kotlin-native/runtime/src/main/cpp/MutexTest.cpp
+++ b/kotlin-native/runtime/src/main/cpp/concurrent/MutexTest.cpp
@@ -1,9 +1,9 @@
/*
- * Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
+ * Copyright 2010-2024 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 "Mutex.hpp"
+#include "concurrent/Mutex.hpp"
#include <mutex>
#include <shared_mutex>
@@ -11,7 +11,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "TestSupport.hpp"
using namespace kotlin;
diff --git a/kotlin-native/runtime/src/main/cpp/ParallelProcessor.hpp b/kotlin-native/runtime/src/main/cpp/concurrent/ParallelProcessor.hpp
similarity index 99%
rename from kotlin-native/runtime/src/main/cpp/ParallelProcessor.hpp
rename to kotlin-native/runtime/src/main/cpp/concurrent/ParallelProcessor.hpp
index e8bab4a..30c46e0 100644
--- a/kotlin-native/runtime/src/main/cpp/ParallelProcessor.hpp
+++ b/kotlin-native/runtime/src/main/cpp/concurrent/ParallelProcessor.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
+ * Copyright 2010-2024 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.
*/
diff --git a/kotlin-native/runtime/src/main/cpp/ParallelProcessorTest.cpp b/kotlin-native/runtime/src/main/cpp/concurrent/ParallelProcessorTest.cpp
similarity index 97%
rename from kotlin-native/runtime/src/main/cpp/ParallelProcessorTest.cpp
rename to kotlin-native/runtime/src/main/cpp/concurrent/ParallelProcessorTest.cpp
index 2b4a30b..fe0a7aa 100644
--- a/kotlin-native/runtime/src/main/cpp/ParallelProcessorTest.cpp
+++ b/kotlin-native/runtime/src/main/cpp/concurrent/ParallelProcessorTest.cpp
@@ -1,9 +1,9 @@
/*
- * Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
+ * Copyright 2010-2024 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 "ParallelProcessor.hpp"
+#include "concurrent/ParallelProcessor.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
diff --git a/kotlin-native/runtime/src/main/cpp/ScopedThread.cpp b/kotlin-native/runtime/src/main/cpp/concurrent/ScopedThread.cpp
similarity index 93%
rename from kotlin-native/runtime/src/main/cpp/ScopedThread.cpp
rename to kotlin-native/runtime/src/main/cpp/concurrent/ScopedThread.cpp
index 1f1ae77..01a63a6 100644
--- a/kotlin-native/runtime/src/main/cpp/ScopedThread.cpp
+++ b/kotlin-native/runtime/src/main/cpp/concurrent/ScopedThread.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
+ * Copyright 2010-2024 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.
*/
diff --git a/kotlin-native/runtime/src/main/cpp/ScopedThread.hpp b/kotlin-native/runtime/src/main/cpp/concurrent/ScopedThread.hpp
similarity index 97%
rename from kotlin-native/runtime/src/main/cpp/ScopedThread.hpp
rename to kotlin-native/runtime/src/main/cpp/concurrent/ScopedThread.hpp
index deb512e..e45dec4 100644
--- a/kotlin-native/runtime/src/main/cpp/ScopedThread.hpp
+++ b/kotlin-native/runtime/src/main/cpp/concurrent/ScopedThread.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
+ * Copyright 2010-2024 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.
*/
diff --git a/kotlin-native/runtime/src/main/cpp/ScopedThreadTest.cpp b/kotlin-native/runtime/src/main/cpp/concurrent/ScopedThreadTest.cpp
similarity index 96%
rename from kotlin-native/runtime/src/main/cpp/ScopedThreadTest.cpp
rename to kotlin-native/runtime/src/main/cpp/concurrent/ScopedThreadTest.cpp
index 3549658..93e2c66 100644
--- a/kotlin-native/runtime/src/main/cpp/ScopedThreadTest.cpp
+++ b/kotlin-native/runtime/src/main/cpp/concurrent/ScopedThreadTest.cpp
@@ -1,9 +1,9 @@
/*
- * Copyright 2010-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
+ * Copyright 2010-2024 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 "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include <array>
#include <atomic>
diff --git a/kotlin-native/runtime/src/main/cpp/std_support/AtomicRef.hpp b/kotlin-native/runtime/src/main/cpp/std_support/AtomicRef.hpp
index fbdbe9c..a5717d2 100644
--- a/kotlin-native/runtime/src/main/cpp/std_support/AtomicRef.hpp
+++ b/kotlin-native/runtime/src/main/cpp/std_support/AtomicRef.hpp
@@ -18,6 +18,9 @@
template<typename T>
class atomic_ref {
+#ifdef KONAN_NO_64BIT_ATOMIC
+ static_assert(sizeof(T) <= 4);
+#endif
// TODO current implementation supports only pointer or integral T
public:
explicit atomic_ref(T& ref) : ref_(ref) {}
diff --git a/kotlin-native/runtime/src/main/cpp/std_support/AtomicRefTest.cpp b/kotlin-native/runtime/src/main/cpp/std_support/AtomicRefTest.cpp
index a3bf6d3..397bf6e 100644
--- a/kotlin-native/runtime/src/main/cpp/std_support/AtomicRefTest.cpp
+++ b/kotlin-native/runtime/src/main/cpp/std_support/AtomicRefTest.cpp
@@ -10,7 +10,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
using namespace kotlin;
diff --git a/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.cpp b/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.cpp
index d368b82..09608ae 100644
--- a/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.cpp
+++ b/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.cpp
@@ -30,7 +30,8 @@
auto& allocator = mm::ThreadRegistry::Instance().CurrentThreadData()->allocator();
auto& data = allocator.allocateExtraObjectData(object, typeInfo);
- if (!compareExchange(object->typeInfoOrMeta_, typeInfo, reinterpret_cast<TypeInfo*>(&data))) {
+ std_support::atomic_ref objectAtomicTypeInfo{object->typeInfoOrMeta_};
+ if (!objectAtomicTypeInfo.compare_exchange_strong(typeInfo, reinterpret_cast<TypeInfo*>(&data))) {
// Somebody else created `mm::ExtraObjectData` for this object.
allocator.destroyUnattachedExtraObjectData(data);
return *reinterpret_cast<mm::ExtraObjectData*>(typeInfo);
@@ -44,7 +45,7 @@
RuntimeAssert(
!hasPointerBits(object, WEAK_REF_TAG), "ExtraObjectData %p has uncleared weak reference %p during unlink", this,
clearPointerBits(object, WEAK_REF_TAG));
- atomicSetRelease(const_cast<const TypeInfo**>(&object->typeInfoOrMeta_), typeInfo_);
+ std_support::atomic_ref{object->typeInfoOrMeta_}.store(const_cast<TypeInfo*>(typeInfo_), std::memory_order_release);
RuntimeAssert(
!object->has_meta_object(), "Object %p has metaobject %p after removing metaobject %p", object, object->meta_object_or_null(),
this);
diff --git a/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.hpp b/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.hpp
index 5118b14..324b1a8d 100644
--- a/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.hpp
+++ b/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.hpp
@@ -81,7 +81,7 @@
// info must be equal to objHeader->type_info(), but it needs to be loaded in advance to avoid data races
explicit ExtraObjectData(ObjHeader* objHeader, const TypeInfo* info) noexcept :
typeInfo_(nullptr), weakReferenceOrBaseObject_(objHeader) {
- atomicSetRelease(&typeInfo_, info);
+ std_support::atomic_ref{typeInfo_}.store(info, std::memory_order_release);
}
~ExtraObjectData();
private:
diff --git a/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataTest.cpp b/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataTest.cpp
index c930781..fa17b37 100644
--- a/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataTest.cpp
+++ b/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataTest.cpp
@@ -12,7 +12,7 @@
#include "AllocatorTestSupport.hpp"
#include "ObjectTestSupport.hpp"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "TestSupport.hpp"
using namespace kotlin;
diff --git a/kotlin-native/runtime/src/mm/cpp/MutexTest.cpp b/kotlin-native/runtime/src/mm/cpp/MutexTest.cpp
index 9f10189..2228912 100644
--- a/kotlin-native/runtime/src/mm/cpp/MutexTest.cpp
+++ b/kotlin-native/runtime/src/mm/cpp/MutexTest.cpp
@@ -3,11 +3,11 @@
* that can be found in the LICENSE file.
*/
-#include "Mutex.hpp"
+#include "concurrent/Mutex.hpp"
#include "gtest/gtest.h"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "TestSupport.hpp"
#include "ThreadState.hpp"
diff --git a/kotlin-native/runtime/src/mm/cpp/SafePointTest.cpp b/kotlin-native/runtime/src/mm/cpp/SafePointTest.cpp
index 57d563f..64b9836 100644
--- a/kotlin-native/runtime/src/mm/cpp/SafePointTest.cpp
+++ b/kotlin-native/runtime/src/mm/cpp/SafePointTest.cpp
@@ -12,7 +12,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "TestSupport.hpp"
using namespace kotlin;
diff --git a/kotlin-native/runtime/src/mm/cpp/ThreadRegistryTest.cpp b/kotlin-native/runtime/src/mm/cpp/ThreadRegistryTest.cpp
index 3e8a25f..727d740 100644
--- a/kotlin-native/runtime/src/mm/cpp/ThreadRegistryTest.cpp
+++ b/kotlin-native/runtime/src/mm/cpp/ThreadRegistryTest.cpp
@@ -8,7 +8,7 @@
#include "gtest/gtest.h"
#include "Porting.h"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "ThreadData.hpp"
using namespace kotlin;
diff --git a/kotlin-native/runtime/src/mm/cpp/ThreadStateTest.cpp b/kotlin-native/runtime/src/mm/cpp/ThreadStateTest.cpp
index 9ae568b..f079afa 100644
--- a/kotlin-native/runtime/src/mm/cpp/ThreadStateTest.cpp
+++ b/kotlin-native/runtime/src/mm/cpp/ThreadStateTest.cpp
@@ -10,7 +10,7 @@
#include "Memory.h"
#include "MemoryPrivate.hpp"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "TestSupport.hpp"
#include "ThreadData.hpp"
#include "ThreadState.hpp"
diff --git a/kotlin-native/runtime/src/mm/cpp/ThreadSuspensionTest.cpp b/kotlin-native/runtime/src/mm/cpp/ThreadSuspensionTest.cpp
index 051f7a3..512bb79 100644
--- a/kotlin-native/runtime/src/mm/cpp/ThreadSuspensionTest.cpp
+++ b/kotlin-native/runtime/src/mm/cpp/ThreadSuspensionTest.cpp
@@ -16,7 +16,7 @@
#include "Runtime.h"
#include "RuntimePrivate.hpp"
#include "SafePoint.hpp"
-#include "ScopedThread.hpp"
+#include "concurrent/ScopedThread.hpp"
#include "TestSupport.hpp"
#include "TestSupportCompilerGenerated.hpp"
#include "ThreadState.hpp"
diff --git a/kotlin-native/runtime/src/objc/cpp/ObjCExportClasses.mm b/kotlin-native/runtime/src/objc/cpp/ObjCExportClasses.mm
index 43269b5..f640ab1 100644
--- a/kotlin-native/runtime/src/objc/cpp/ObjCExportClasses.mm
+++ b/kotlin-native/runtime/src/objc/cpp/ObjCExportClasses.mm
@@ -22,7 +22,7 @@
#import "ObjCExportInit.h"
#import "ObjCExportPrivate.h"
#import "Runtime.h"
-#import "Mutex.hpp"
+#import "concurrent/Mutex.hpp"
#import "Exceptions.h"
@interface NSObject (NSObjectPrivateMethods)
diff --git a/kotlin-native/runtime/src/objc/cpp/ObjCExportNumbers.mm b/kotlin-native/runtime/src/objc/cpp/ObjCExportNumbers.mm
index 24b0973..dfb51ba 100644
--- a/kotlin-native/runtime/src/objc/cpp/ObjCExportNumbers.mm
+++ b/kotlin-native/runtime/src/objc/cpp/ObjCExportNumbers.mm
@@ -23,7 +23,7 @@
#import "ObjCExport.h"
#import "Runtime.h"
-#import "Mutex.hpp"
+#import "concurrent/Mutex.hpp"
extern "C" {