Implement Time::GetSharedMemoryNativeHandle
This PR attempts to implement the shared memory provided by GetSharedMemoryNativeHandle. There is still more work to be done however that requires a rehaul of the current time module to handle clock contexts. This PR is mainly to get the basic functionality of the SharedMemory working and allow the use of addition to it whilst things get improved on. Things to note: Memory Barriers are used in the SharedMemory and a better solution would need to be done to implement this. Currently in this PR I’m faking the memory barriers as everything is sync and single threaded. They work by incrementing the counter and just populate the two data slots. On data reading, it will read the last added data. Specific values in the shared memory would need to be updated periodically. This isn't included in this PR since we don't actively do this yet. In a later PR when time is refactored this should be done. Finally, as we don't handle clock contexts. When time is refactored, we will need to update the shared memory for specific contexts. This PR does this already however since the contexts are all identical and not separated. We're just updating the same values for each context which in this case is empty. Tiime:SetStandardUserSystemClockAutomaticCorrectionEnabled, Time:IsStandardUserSystemClockAutomaticCorrectionEnabled are also partially implemented in this PR. The reason the implementation is partial is because once again, a lack of clock contexts. This will be improved on in a future PR. This PR closes issue #2556
This commit is contained in:
parent
221996a194
commit
19dc36ce06
|
@ -422,6 +422,8 @@ add_library(core STATIC
|
||||||
hle/service/time/interface.h
|
hle/service/time/interface.h
|
||||||
hle/service/time/time.cpp
|
hle/service/time/time.cpp
|
||||||
hle/service/time/time.h
|
hle/service/time/time.h
|
||||||
|
hle/service/time/time_sharedmemory.cpp
|
||||||
|
hle/service/time/time_sharedmemory.h
|
||||||
hle/service/usb/usb.cpp
|
hle/service/usb/usb.cpp
|
||||||
hle/service/usb/usb.h
|
hle/service/usb/usb.h
|
||||||
hle/service/vi/display/vi_display.cpp
|
hle/service/vi/display/vi_display.cpp
|
||||||
|
|
|
@ -249,7 +249,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,
|
||||||
Sockets::InstallInterfaces(*sm);
|
Sockets::InstallInterfaces(*sm);
|
||||||
SPL::InstallInterfaces(*sm);
|
SPL::InstallInterfaces(*sm);
|
||||||
SSL::InstallInterfaces(*sm);
|
SSL::InstallInterfaces(*sm);
|
||||||
Time::InstallInterfaces(*sm);
|
Time::InstallInterfaces(system);
|
||||||
USB::InstallInterfaces(*sm);
|
USB::InstallInterfaces(*sm);
|
||||||
VI::InstallInterfaces(*sm, nv_flinger);
|
VI::InstallInterfaces(*sm, nv_flinger);
|
||||||
WLAN::InstallInterfaces(*sm);
|
WLAN::InstallInterfaces(*sm);
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
|
|
||||||
namespace Service::Time {
|
namespace Service::Time {
|
||||||
|
|
||||||
Time::Time(std::shared_ptr<Module> time, const char* name)
|
Time::Time(std::shared_ptr<Module> time, std::shared_ptr<SharedMemory> shared_memory,
|
||||||
: Module::Interface(std::move(time), name) {
|
const char* name)
|
||||||
|
: Module::Interface(std::move(time), std::move(shared_memory), name) {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
|
{0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
|
||||||
|
@ -16,12 +17,12 @@ Time::Time(std::shared_ptr<Module> time, const char* name)
|
||||||
{3, &Time::GetTimeZoneService, "GetTimeZoneService"},
|
{3, &Time::GetTimeZoneService, "GetTimeZoneService"},
|
||||||
{4, &Time::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
|
{4, &Time::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
|
||||||
{5, nullptr, "GetEphemeralNetworkSystemClock"},
|
{5, nullptr, "GetEphemeralNetworkSystemClock"},
|
||||||
{20, nullptr, "GetSharedMemoryNativeHandle"},
|
{20, &Time::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
|
||||||
{30, nullptr, "GetStandardNetworkClockOperationEventReadableHandle"},
|
{30, nullptr, "GetStandardNetworkClockOperationEventReadableHandle"},
|
||||||
{31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"},
|
{31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"},
|
||||||
{50, nullptr, "SetStandardSteadyClockInternalOffset"},
|
{50, nullptr, "SetStandardSteadyClockInternalOffset"},
|
||||||
{100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
{100, &Time::IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||||
{101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
{101, &Time::SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||||
{102, nullptr, "GetStandardUserSystemClockInitialYear"},
|
{102, nullptr, "GetStandardUserSystemClockInitialYear"},
|
||||||
{200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"},
|
{200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"},
|
||||||
{201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
|
{201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
|
||||||
|
|
|
@ -7,10 +7,11 @@
|
||||||
#include "core/hle/service/time/time.h"
|
#include "core/hle/service/time/time.h"
|
||||||
|
|
||||||
namespace Service::Time {
|
namespace Service::Time {
|
||||||
|
class SharedMemory;
|
||||||
class Time final : public Module::Interface {
|
class Time final : public Module::Interface {
|
||||||
public:
|
public:
|
||||||
explicit Time(std::shared_ptr<Module> time, const char* name);
|
explicit Time(std::shared_ptr<Module> time, std::shared_ptr<SharedMemory> shared_memory,
|
||||||
|
const char* name);
|
||||||
~Time() override;
|
~Time() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "core/hle/kernel/client_session.h"
|
#include "core/hle/kernel/client_session.h"
|
||||||
#include "core/hle/service/time/interface.h"
|
#include "core/hle/service/time/interface.h"
|
||||||
#include "core/hle/service/time/time.h"
|
#include "core/hle/service/time/time.h"
|
||||||
|
#include "core/hle/service/time/time_sharedmemory.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
|
|
||||||
namespace Service::Time {
|
namespace Service::Time {
|
||||||
|
@ -61,9 +62,18 @@ static u64 CalendarToPosix(const CalendarTime& calendar_time,
|
||||||
return static_cast<u64>(epoch_time);
|
return static_cast<u64>(epoch_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class ClockContextType {
|
||||||
|
StandardSteady,
|
||||||
|
StandardUserSystem,
|
||||||
|
StandardNetworkSystem,
|
||||||
|
StandardLocalSystem,
|
||||||
|
};
|
||||||
|
|
||||||
class ISystemClock final : public ServiceFramework<ISystemClock> {
|
class ISystemClock final : public ServiceFramework<ISystemClock> {
|
||||||
public:
|
public:
|
||||||
ISystemClock() : ServiceFramework("ISystemClock") {
|
ISystemClock(std::shared_ptr<Service::Time::SharedMemory> shared_memory,
|
||||||
|
ClockContextType clock_type)
|
||||||
|
: ServiceFramework("ISystemClock"), shared_memory(shared_memory), clock_type(clock_type) {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &ISystemClock::GetCurrentTime, "GetCurrentTime"},
|
{0, &ISystemClock::GetCurrentTime, "GetCurrentTime"},
|
||||||
{1, nullptr, "SetCurrentTime"},
|
{1, nullptr, "SetCurrentTime"},
|
||||||
|
@ -72,6 +82,8 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
|
UpdateSharedMemoryContext(system_clock_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -87,34 +99,63 @@ private:
|
||||||
void GetSystemClockContext(Kernel::HLERequestContext& ctx) {
|
void GetSystemClockContext(Kernel::HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_Time, "(STUBBED) called");
|
LOG_WARNING(Service_Time, "(STUBBED) called");
|
||||||
|
|
||||||
SystemClockContext system_clock_ontext{};
|
// TODO(ogniK): This should be updated periodically however since we have it stubbed we'll
|
||||||
|
// only update when we get a new context
|
||||||
|
UpdateSharedMemoryContext(system_clock_context);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2};
|
IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2};
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
rb.PushRaw(system_clock_ontext);
|
rb.PushRaw(system_clock_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateSharedMemoryContext(const SystemClockContext& clock_context) {
|
||||||
|
switch (clock_type) {
|
||||||
|
case ClockContextType::StandardLocalSystem:
|
||||||
|
shared_memory->SetStandardLocalSystemClockContext(clock_context);
|
||||||
|
break;
|
||||||
|
case ClockContextType::StandardNetworkSystem:
|
||||||
|
shared_memory->SetStandardNetworkSystemClockContext(clock_context);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemClockContext system_clock_context{};
|
||||||
|
std::shared_ptr<Service::Time::SharedMemory> shared_memory;
|
||||||
|
ClockContextType clock_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ISteadyClock final : public ServiceFramework<ISteadyClock> {
|
class ISteadyClock final : public ServiceFramework<ISteadyClock> {
|
||||||
public:
|
public:
|
||||||
ISteadyClock() : ServiceFramework("ISteadyClock") {
|
ISteadyClock(std::shared_ptr<SharedMemory> shared_memory)
|
||||||
|
: ServiceFramework("ISteadyClock"), shared_memory(shared_memory) {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"},
|
{0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"},
|
||||||
};
|
};
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
|
shared_memory->SetStandardSteadyClockTimepoint(GetCurrentTimePoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) {
|
void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_Time, "called");
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
const auto& core_timing = Core::System::GetInstance().CoreTiming();
|
const auto time_point = GetCurrentTimePoint();
|
||||||
const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks());
|
// TODO(ogniK): This should be updated periodically
|
||||||
const SteadyClockTimePoint steady_clock_time_point{static_cast<u64_le>(ms.count() / 1000),
|
shared_memory->SetStandardSteadyClockTimepoint(time_point);
|
||||||
{}};
|
|
||||||
IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2};
|
IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2};
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
rb.PushRaw(steady_clock_time_point);
|
rb.PushRaw(time_point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SteadyClockTimePoint GetCurrentTimePoint() const {
|
||||||
|
const auto& core_timing = Core::System::GetInstance().CoreTiming();
|
||||||
|
const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks());
|
||||||
|
return {static_cast<u64_le>(ms.count() / 1000), {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<SharedMemory> shared_memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ITimeZoneService final : public ServiceFramework<ITimeZoneService> {
|
class ITimeZoneService final : public ServiceFramework<ITimeZoneService> {
|
||||||
|
@ -233,7 +274,7 @@ void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ct
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
rb.PushIpcInterface<ISystemClock>();
|
rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardUserSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) {
|
||||||
|
@ -241,7 +282,7 @@ void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext&
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
rb.PushIpcInterface<ISystemClock>();
|
rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardNetworkSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
|
||||||
|
@ -249,7 +290,7 @@ void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
rb.PushIpcInterface<ISteadyClock>();
|
rb.PushIpcInterface<ISteadyClock>(shared_memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
|
||||||
|
@ -265,7 +306,7 @@ void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& c
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
rb.PushIpcInterface<ISystemClock>();
|
rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardLocalSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
|
||||||
|
@ -333,16 +374,51 @@ void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(
|
||||||
rb.PushRaw<u64>(difference);
|
rb.PushRaw<u64>(difference);
|
||||||
}
|
}
|
||||||
|
|
||||||
Module::Interface::Interface(std::shared_ptr<Module> time, const char* name)
|
void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
|
||||||
: ServiceFramework(name), time(std::move(time)) {}
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushCopyObjects(shared_memory->GetSharedMemoryHolder());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::Interface::IsStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||||
|
Kernel::HLERequestContext& ctx) {
|
||||||
|
// ogniK(TODO): When clock contexts are implemented, the value should be read from the context
|
||||||
|
// instead of our shared memory holder
|
||||||
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.Push<u8>(shared_memory->GetStandardUserSystemClockAutomaticCorrectionEnabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::Interface::SetStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||||
|
Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto enabled = rp.Pop<u8>();
|
||||||
|
|
||||||
|
LOG_WARNING(Service_Time, "(PARTIAL IMPLEMENTATION) called");
|
||||||
|
|
||||||
|
// TODO(ogniK): Update clock contexts and correct timespans
|
||||||
|
|
||||||
|
shared_memory->SetStandardUserSystemClockAutomaticCorrectionEnabled(enabled > 0);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
Module::Interface::Interface(std::shared_ptr<Module> time,
|
||||||
|
std::shared_ptr<SharedMemory> shared_memory, const char* name)
|
||||||
|
: ServiceFramework(name), time(std::move(time)), shared_memory(std::move(shared_memory)) {}
|
||||||
|
|
||||||
Module::Interface::~Interface() = default;
|
Module::Interface::~Interface() = default;
|
||||||
|
|
||||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
void InstallInterfaces(Core::System& system) {
|
||||||
auto time = std::make_shared<Module>();
|
auto time = std::make_shared<Module>();
|
||||||
std::make_shared<Time>(time, "time:a")->InstallAsService(service_manager);
|
auto shared_mem = std::make_shared<SharedMemory>(system);
|
||||||
std::make_shared<Time>(time, "time:s")->InstallAsService(service_manager);
|
|
||||||
std::make_shared<Time>(time, "time:u")->InstallAsService(service_manager);
|
std::make_shared<Time>(time, shared_mem, "time:a")->InstallAsService(system.ServiceManager());
|
||||||
|
std::make_shared<Time>(time, shared_mem, "time:s")->InstallAsService(system.ServiceManager());
|
||||||
|
std::make_shared<Time>(time, shared_mem, "time:u")->InstallAsService(system.ServiceManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::Time
|
} // namespace Service::Time
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
namespace Service::Time {
|
namespace Service::Time {
|
||||||
|
class SharedMemory;
|
||||||
|
|
||||||
struct LocationName {
|
struct LocationName {
|
||||||
std::array<u8, 0x24> name;
|
std::array<u8, 0x24> name;
|
||||||
|
@ -77,7 +78,8 @@ class Module final {
|
||||||
public:
|
public:
|
||||||
class Interface : public ServiceFramework<Interface> {
|
class Interface : public ServiceFramework<Interface> {
|
||||||
public:
|
public:
|
||||||
explicit Interface(std::shared_ptr<Module> time, const char* name);
|
explicit Interface(std::shared_ptr<Module> time,
|
||||||
|
std::shared_ptr<SharedMemory> shared_memory, const char* name);
|
||||||
~Interface() override;
|
~Interface() override;
|
||||||
|
|
||||||
void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx);
|
void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx);
|
||||||
|
@ -87,13 +89,17 @@ public:
|
||||||
void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx);
|
void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx);
|
||||||
void GetClockSnapshot(Kernel::HLERequestContext& ctx);
|
void GetClockSnapshot(Kernel::HLERequestContext& ctx);
|
||||||
void CalculateStandardUserSystemClockDifferenceByUser(Kernel::HLERequestContext& ctx);
|
void CalculateStandardUserSystemClockDifferenceByUser(Kernel::HLERequestContext& ctx);
|
||||||
|
void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx);
|
||||||
|
void IsStandardUserSystemClockAutomaticCorrectionEnabled(Kernel::HLERequestContext& ctx);
|
||||||
|
void SetStandardUserSystemClockAutomaticCorrectionEnabled(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<Module> time;
|
std::shared_ptr<Module> time;
|
||||||
|
std::shared_ptr<SharedMemory> shared_memory;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Registers all Time services with the specified service manager.
|
/// Registers all Time services with the specified service manager.
|
||||||
void InstallInterfaces(SM::ServiceManager& service_manager);
|
void InstallInterfaces(Core::System& system);
|
||||||
|
|
||||||
} // namespace Service::Time
|
} // namespace Service::Time
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright 2018 yuzu emulator team
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/time/time_sharedmemory.h"
|
||||||
|
|
||||||
|
namespace Service::Time {
|
||||||
|
|
||||||
|
SharedMemory::SharedMemory(Core::System& system) : system(system) {
|
||||||
|
shared_memory_holder = Kernel::SharedMemory::Create(
|
||||||
|
system.Kernel(), nullptr, SHARED_MEMORY_SIZE, Kernel::MemoryPermission::ReadWrite,
|
||||||
|
Kernel::MemoryPermission::Read, 0, Kernel::MemoryRegion::BASE, "Time:SharedMemory");
|
||||||
|
shared_memory_format = reinterpret_cast<Format*>(shared_memory_holder->GetPointer());
|
||||||
|
shared_memory_format->format_version =
|
||||||
|
14; // Seems static from 1.0.0 -> 8.1.0. Specific games seem to check this value and crash
|
||||||
|
// if it's set to anything else
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedMemory::~SharedMemory() = default;
|
||||||
|
|
||||||
|
Kernel::SharedPtr<Kernel::SharedMemory> SharedMemory::GetSharedMemoryHolder() const {
|
||||||
|
return shared_memory_holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedMemory::SetStandardSteadyClockTimepoint(const SteadyClockTimePoint& timepoint) {
|
||||||
|
shared_memory_format->standard_steady_clock_timepoint.StoreData(timepoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedMemory::SetStandardLocalSystemClockContext(const SystemClockContext& context) {
|
||||||
|
shared_memory_format->standard_local_system_clock_context.StoreData(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedMemory::SetStandardNetworkSystemClockContext(const SystemClockContext& context) {
|
||||||
|
shared_memory_format->standard_network_system_clock_context.StoreData(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedMemory::SetStandardUserSystemClockAutomaticCorrectionEnabled(const bool enabled) {
|
||||||
|
shared_memory_format->standard_user_system_clock_automatic_correction.StoreData(enabled ? 1
|
||||||
|
: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SteadyClockTimePoint SharedMemory::GetStandardSteadyClockTimepoint() const {
|
||||||
|
return shared_memory_format->standard_steady_clock_timepoint.ReadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemClockContext SharedMemory::GetStandardLocalSystemClockContext() const {
|
||||||
|
return shared_memory_format->standard_local_system_clock_context.ReadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemClockContext SharedMemory::GetStandardNetworkSystemClockContext() const {
|
||||||
|
return shared_memory_format->standard_network_system_clock_context.ReadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SharedMemory::GetStandardUserSystemClockAutomaticCorrectionEnabled() const {
|
||||||
|
return shared_memory_format->standard_user_system_clock_automatic_correction.ReadData() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::Time
|
|
@ -0,0 +1,71 @@
|
||||||
|
// Copyright 2018 yuzu emulator team
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "core/hle/kernel/shared_memory.h"
|
||||||
|
#include "core/hle/service/time/time.h"
|
||||||
|
|
||||||
|
namespace Service::Time {
|
||||||
|
class SharedMemory {
|
||||||
|
public:
|
||||||
|
SharedMemory(Core::System& system);
|
||||||
|
~SharedMemory();
|
||||||
|
|
||||||
|
// Return the shared memory handle
|
||||||
|
Kernel::SharedPtr<Kernel::SharedMemory> GetSharedMemoryHolder() const;
|
||||||
|
|
||||||
|
// Set memory barriers in shared memory and update them
|
||||||
|
void SetStandardSteadyClockTimepoint(const SteadyClockTimePoint& timepoint);
|
||||||
|
void SetStandardLocalSystemClockContext(const SystemClockContext& context);
|
||||||
|
void SetStandardNetworkSystemClockContext(const SystemClockContext& context);
|
||||||
|
void SetStandardUserSystemClockAutomaticCorrectionEnabled(const bool enabled);
|
||||||
|
|
||||||
|
// Pull from memory barriers in the shared memory
|
||||||
|
SteadyClockTimePoint GetStandardSteadyClockTimepoint() const;
|
||||||
|
SystemClockContext GetStandardLocalSystemClockContext() const;
|
||||||
|
SystemClockContext GetStandardNetworkSystemClockContext() const;
|
||||||
|
bool GetStandardUserSystemClockAutomaticCorrectionEnabled() const;
|
||||||
|
|
||||||
|
// TODO(ogniK): We have to properly simulate memory barriers, how are we going to do this?
|
||||||
|
template <typename T>
|
||||||
|
struct MemoryBarrier {
|
||||||
|
u32_le read_attempt{};
|
||||||
|
T data[2]{};
|
||||||
|
|
||||||
|
// These are not actually memory barriers at the moment as we don't have multicore and all
|
||||||
|
// HLE is mutexed. This will need to properly be implemented when we start updating the time
|
||||||
|
// points on threads. As of right now, we'll be updated both values synchronously and just
|
||||||
|
// incrementing the read_attempt to indicate that we waited.
|
||||||
|
void StoreData(T data_to_store) {
|
||||||
|
read_attempt++;
|
||||||
|
data[read_attempt & 1] = data_to_store;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For reading we're just going to read the last stored value. If there was no value stored
|
||||||
|
// it will just end up reading an empty value as intended.
|
||||||
|
T ReadData() const {
|
||||||
|
return data[(read_attempt - 1) & 1];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Shared memory format
|
||||||
|
struct Format {
|
||||||
|
MemoryBarrier<SteadyClockTimePoint> standard_steady_clock_timepoint;
|
||||||
|
MemoryBarrier<SystemClockContext> standard_local_system_clock_context;
|
||||||
|
MemoryBarrier<SystemClockContext> standard_network_system_clock_context;
|
||||||
|
MemoryBarrier<u8> standard_user_system_clock_automatic_correction;
|
||||||
|
u32_le format_version;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(Format) == 0xd8, "Format is an invalid size");
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::size_t SHARED_MEMORY_SIZE = 0x1000;
|
||||||
|
Kernel::SharedPtr<Kernel::SharedMemory> shared_memory_holder{};
|
||||||
|
Core::System& system;
|
||||||
|
Format* shared_memory_format;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::Time
|
Loading…
Reference in New Issue