mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-06-03 02:20:02 +00:00
85 lines
2.7 KiB
C++
85 lines
2.7 KiB
C++
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "core/core.h"
|
|
#include "core/hle/kernel/k_shared_memory.h"
|
|
#include "core/hle/service/psc/time/shared_memory.h"
|
|
|
|
namespace Service::PSC::Time {
|
|
namespace {
|
|
template <typename T>
|
|
constexpr inline T ReadFromLockFreeAtomicType(const LockFreeAtomicType<T>* p) {
|
|
while (true) {
|
|
// Get the counter.
|
|
auto counter = p->m_counter;
|
|
|
|
// Get the value.
|
|
auto value = p->m_value[counter % 2];
|
|
|
|
// Fence memory.
|
|
std::atomic_thread_fence(std::memory_order_acquire);
|
|
|
|
// Check that the counter matches.
|
|
if (counter == p->m_counter) {
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
constexpr inline void WriteToLockFreeAtomicType(LockFreeAtomicType<T>* p, const T& value) {
|
|
// Get the current counter.
|
|
auto counter = p->m_counter;
|
|
|
|
// Increment the counter.
|
|
++counter;
|
|
|
|
// Store the updated value.
|
|
p->m_value[counter % 2] = value;
|
|
|
|
// Fence memory.
|
|
std::atomic_thread_fence(std::memory_order_release);
|
|
|
|
// Set the updated counter.
|
|
p->m_counter = counter;
|
|
}
|
|
} // namespace
|
|
|
|
SharedMemory::SharedMemory(Core::System& system)
|
|
: m_system{system}, m_k_shared_memory{m_system.Kernel().GetTimeSharedMem()},
|
|
m_shared_memory_ptr{reinterpret_cast<SharedMemoryStruct*>(m_k_shared_memory.GetPointer())} {
|
|
std::memset(m_shared_memory_ptr, 0, sizeof(*m_shared_memory_ptr));
|
|
}
|
|
|
|
void SharedMemory::SetLocalSystemContext(SystemClockContext& context) {
|
|
WriteToLockFreeAtomicType(&m_shared_memory_ptr->local_system_clock_contexts, context);
|
|
}
|
|
|
|
void SharedMemory::SetNetworkSystemContext(SystemClockContext& context) {
|
|
WriteToLockFreeAtomicType(&m_shared_memory_ptr->network_system_clock_contexts, context);
|
|
}
|
|
|
|
void SharedMemory::SetSteadyClockTimePoint(ClockSourceId clock_source_id, s64 time_point) {
|
|
WriteToLockFreeAtomicType(&m_shared_memory_ptr->steady_time_points,
|
|
{time_point, clock_source_id});
|
|
}
|
|
|
|
void SharedMemory::SetContinuousAdjustment(ContinuousAdjustmentTimePoint& time_point) {
|
|
WriteToLockFreeAtomicType(&m_shared_memory_ptr->continuous_adjustment_time_points, time_point);
|
|
}
|
|
|
|
void SharedMemory::SetAutomaticCorrection(bool automatic_correction) {
|
|
WriteToLockFreeAtomicType(&m_shared_memory_ptr->automatic_corrections, automatic_correction);
|
|
}
|
|
|
|
void SharedMemory::UpdateBaseTime(s64 time) {
|
|
SteadyClockTimePoint time_point{
|
|
ReadFromLockFreeAtomicType(&m_shared_memory_ptr->steady_time_points)};
|
|
|
|
time_point.time_point = time;
|
|
|
|
WriteToLockFreeAtomicType(&m_shared_memory_ptr->steady_time_points, time_point);
|
|
}
|
|
|
|
} // namespace Service::PSC::Time
|