[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" {