blob: 6ed2c834cd33c9a48da78a56cb221f5611ee4dd7 [file]
/*
* Copyright 2010-2021 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.
*/
#ifndef RUNTIME_MM_THREAD_SUSPENSION_H
#define RUNTIME_MM_THREAD_SUSPENSION_H
#include <atomic>
#include "Memory.h"
#include "Utils.hpp"
namespace kotlin {
namespace mm {
class ThreadData;
namespace internal {
using SuspensionReason = const char*;
extern std::atomic<SuspensionReason> gSuspensionRequestReason;
} // namespace internal
inline bool IsThreadSuspensionRequested() noexcept {
// Must use seq_cst ordering for synchronization with GC
// in native->runnable transition.
return internal::gSuspensionRequestReason.load();
}
class ThreadSuspensionData : private Pinned {
private:
class MutatorPauseHandle : private Pinned {
public:
explicit MutatorPauseHandle(const char* reason, ThreadData& threadData) noexcept;
~MutatorPauseHandle() noexcept;
void resume() noexcept;
private:
const char* reason_;
ThreadData& threadData_;
uint64_t pauseStartTimeMicros_;
bool resumed = false;
};
public:
explicit ThreadSuspensionData(ThreadState initialState, mm::ThreadData& threadData) noexcept : state_(initialState), threadData_(threadData) {}
~ThreadSuspensionData() = default;
ThreadState state() noexcept { return state_; }
ThreadState setState(ThreadState newState) noexcept;
ThreadState setStateNoSafePoint(ThreadState newState) noexcept { return state_.exchange(newState, std::memory_order_acq_rel); }
bool suspendedOrNative() noexcept { return state() == kotlin::ThreadState::kNative; }
void suspendIfRequested() noexcept;
void requestThreadsSuspension(const char* reason) noexcept;
/**
* Signals that the thread would not mutate a heap during a relatively long time.
* For example while waiting for or participating in the GC.
* Effectively sets the thread's state to `kNative`.
*
* The pause is considered completed upon destruction of a returned pause-handle object.
*
* NOTE: the safe point actions will NOT be automatically executed after the pause.
*/
[[nodiscard]] MutatorPauseHandle pauseMutationInScope(const char* reason) noexcept;
private:
std::atomic<ThreadState> state_;
mm::ThreadData& threadData_;
};
/**
* Sends a request to suspend all threads registered in ThreadRegistry except threads that are in the Native state.
* Blocks until all such threads are suspended. Threads that are in the Native state on the moment
* of this call will be suspended on exit from the Native state.
*
* Returns false if some other thread tries to suspended the threads at the moment.
*/
bool TryRequestThreadsSuspension(const char* reason) noexcept;
void RequestThreadsSuspension(const char* reason) noexcept;
void WaitForThreadsSuspension() noexcept;
/**
* Resumes all threads registered in ThreadRegistry that were suspended by the SuspendThreads call.
* Does not wait until all such threads are actually resumed.
*/
void ResumeThreads() noexcept;
} // namespace mm
} // namespace kotlin
#endif // RUNTIME_MM_THREAD_SUSPENSION_H