summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/psc/time/shared_memory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/psc/time/shared_memory.cpp')
-rw-r--r--src/core/hle/service/psc/time/shared_memory.cpp84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/core/hle/service/psc/time/shared_memory.cpp b/src/core/hle/service/psc/time/shared_memory.cpp
new file mode 100644
index 000000000..defaceebe
--- /dev/null
+++ b/src/core/hle/service/psc/time/shared_memory.cpp
@@ -0,0 +1,84 @@
+// 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