yuzu/src/core/hle/service/time/time.cpp

440 lines
16 KiB
C++
Raw Normal View History

// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <chrono>
#include <ctime>
#include "common/logging/log.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/service/time/interface.h"
#include "core/hle/service/time/time.h"
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
2019-06-25 14:45:53 +00:00
#include "core/hle/service/time/time_sharedmemory.h"
#include "core/settings.h"
namespace Service::Time {
static std::chrono::seconds GetSecondsSinceEpoch() {
return std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()) +
Settings::values.custom_rtc_differential;
}
2018-11-10 01:31:48 +00:00
static void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time,
2018-11-10 07:07:34 +00:00
CalendarAdditionalInfo& additional_info,
[[maybe_unused]] const TimeZoneRule& /*rule*/) {
2018-11-10 01:31:48 +00:00
const std::time_t time(posix_time);
const std::tm* tm = std::localtime(&time);
if (tm == nullptr) {
2018-11-10 07:07:34 +00:00
calendar_time = {};
additional_info = {};
return;
}
calendar_time.year = static_cast<u16_le>(tm->tm_year + 1900);
calendar_time.month = static_cast<u8>(tm->tm_mon + 1);
calendar_time.day = static_cast<u8>(tm->tm_mday);
calendar_time.hour = static_cast<u8>(tm->tm_hour);
calendar_time.minute = static_cast<u8>(tm->tm_min);
calendar_time.second = static_cast<u8>(tm->tm_sec);
additional_info.day_of_week = tm->tm_wday;
additional_info.day_of_year = tm->tm_yday;
std::memcpy(additional_info.name.data(), "UTC", sizeof("UTC"));
additional_info.utc_offset = 0;
}
2018-11-10 07:07:34 +00:00
static u64 CalendarToPosix(const CalendarTime& calendar_time,
[[maybe_unused]] const TimeZoneRule& /*rule*/) {
std::tm time{};
time.tm_year = calendar_time.year - 1900;
time.tm_mon = calendar_time.month - 1;
time.tm_mday = calendar_time.day;
time.tm_hour = calendar_time.hour;
time.tm_min = calendar_time.minute;
time.tm_sec = calendar_time.second;
std::time_t epoch_time = std::mktime(&time);
return static_cast<u64>(epoch_time);
}
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
2019-06-25 14:45:53 +00:00
enum class ClockContextType {
StandardSteady,
StandardUserSystem,
StandardNetworkSystem,
StandardLocalSystem,
};
class ISystemClock final : public ServiceFramework<ISystemClock> {
public:
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
2019-06-25 14:45:53 +00:00
ISystemClock(std::shared_ptr<Service::Time::SharedMemory> shared_memory,
ClockContextType clock_type)
: ServiceFramework("ISystemClock"), shared_memory(shared_memory), clock_type(clock_type) {
// clang-format off
static const FunctionInfo functions[] = {
{0, &ISystemClock::GetCurrentTime, "GetCurrentTime"},
{1, nullptr, "SetCurrentTime"},
{2, &ISystemClock::GetSystemClockContext, "GetSystemClockContext"},
{3, nullptr, "SetSystemClockContext"},
{4, nullptr, "GetOperationEventReadableHandle"},
};
// clang-format on
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
2019-06-25 14:45:53 +00:00
RegisterHandlers(functions);
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
2019-06-25 14:45:53 +00:00
UpdateSharedMemoryContext(system_clock_context);
}
private:
void GetCurrentTime(Kernel::HLERequestContext& ctx) {
const s64 time_since_epoch{GetSecondsSinceEpoch().count()};
2018-07-02 16:13:26 +00:00
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(time_since_epoch);
}
void GetSystemClockContext(Kernel::HLERequestContext& ctx) {
2018-07-02 16:13:26 +00:00
LOG_WARNING(Service_Time, "(STUBBED) called");
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
2019-06-25 14:45:53 +00:00
// 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};
rb.Push(RESULT_SUCCESS);
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
2019-06-25 14:45:53 +00:00
rb.PushRaw(system_clock_context);
}
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
2019-06-25 14:45:53 +00:00
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> {
public:
2019-09-21 09:35:01 +00:00
ISteadyClock(std::shared_ptr<SharedMemory> shared_memory, Core::System& system)
: ServiceFramework("ISteadyClock"), shared_memory(shared_memory), system(system) {
static const FunctionInfo functions[] = {
{0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"},
};
RegisterHandlers(functions);
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
2019-06-25 14:45:53 +00:00
shared_memory->SetStandardSteadyClockTimepoint(GetCurrentTimePoint());
}
private:
void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) {
2018-07-02 16:13:26 +00:00
LOG_DEBUG(Service_Time, "called");
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
2019-06-25 14:45:53 +00:00
const auto time_point = GetCurrentTimePoint();
// TODO(ogniK): This should be updated periodically
shared_memory->SetStandardSteadyClockTimepoint(time_point);
IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2};
rb.Push(RESULT_SUCCESS);
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
2019-06-25 14:45:53 +00:00
rb.PushRaw(time_point);
}
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
2019-06-25 14:45:53 +00:00
SteadyClockTimePoint GetCurrentTimePoint() const {
2019-09-21 09:35:01 +00:00
const auto& core_timing = system.CoreTiming();
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
2019-06-25 14:45:53 +00:00
const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks());
return {static_cast<u64_le>(ms.count() / 1000), {}};
}
std::shared_ptr<SharedMemory> shared_memory;
2019-09-21 09:35:01 +00:00
Core::System& system;
};
class ITimeZoneService final : public ServiceFramework<ITimeZoneService> {
public:
ITimeZoneService() : ServiceFramework("ITimeZoneService") {
// clang-format off
static const FunctionInfo functions[] = {
{0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},
{1, nullptr, "SetDeviceLocationName"},
{2, &ITimeZoneService::GetTotalLocationNameCount, "GetTotalLocationNameCount"},
{3, nullptr, "LoadLocationNameList"},
{4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"},
{5, nullptr, "GetTimeZoneRuleVersion"},
{6, nullptr, "GetDeviceLocationNameAndUpdatedTime"},
{7, nullptr, "SetDeviceLocationNameWithTimeZoneRule"},
{8, nullptr, "ParseTimeZoneBinary"},
{20, nullptr, "GetDeviceLocationNameOperationEventReadableHandle"},
{100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
{101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
{201, &ITimeZoneService::ToPosixTime, "ToPosixTime"},
{202, &ITimeZoneService::ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
LocationName location_name{"UTC"};
TimeZoneRule my_time_zone_rule{};
void GetDeviceLocationName(Kernel::HLERequestContext& ctx) {
2018-07-02 16:13:26 +00:00
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, (sizeof(LocationName) / 4) + 2};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(location_name);
}
void GetTotalLocationNameCount(Kernel::HLERequestContext& ctx) {
2018-07-02 16:13:26 +00:00
LOG_WARNING(Service_Time, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0);
}
void LoadTimeZoneRule(Kernel::HLERequestContext& ctx) {
2018-07-02 16:13:26 +00:00
LOG_WARNING(Service_Time, "(STUBBED) called");
ctx.WriteBuffer(&my_time_zone_rule, sizeof(TimeZoneRule));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void ToCalendarTime(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 posix_time = rp.Pop<u64>();
2018-07-02 16:13:26 +00:00
LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time);
TimeZoneRule time_zone_rule{};
auto buffer = ctx.ReadBuffer();
std::memcpy(&time_zone_rule, buffer.data(), buffer.size());
CalendarTime calendar_time{2018, 1, 1, 0, 0, 0};
CalendarAdditionalInfo additional_info{};
PosixToCalendar(posix_time, calendar_time, additional_info, time_zone_rule);
IPC::ResponseBuilder rb{ctx, 10};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(calendar_time);
rb.PushRaw(additional_info);
}
void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 posix_time = rp.Pop<u64>();
2018-07-02 16:13:26 +00:00
LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time);
CalendarTime calendar_time{2018, 1, 1, 0, 0, 0};
CalendarAdditionalInfo additional_info{};
PosixToCalendar(posix_time, calendar_time, additional_info, my_time_zone_rule);
IPC::ResponseBuilder rb{ctx, 10};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(calendar_time);
rb.PushRaw(additional_info);
}
void ToPosixTime(Kernel::HLERequestContext& ctx) {
// TODO(ogniK): Figure out how to handle multiple times
LOG_WARNING(Service_Time, "(STUBBED) called");
IPC::RequestParser rp{ctx};
auto calendar_time = rp.PopRaw<CalendarTime>();
auto posix_time = CalendarToPosix(calendar_time, {});
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u32>(1); // Amount of times we're returning
ctx.WriteBuffer(&posix_time, sizeof(u64));
}
void ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Time, "(STUBBED) called");
IPC::RequestParser rp{ctx};
auto calendar_time = rp.PopRaw<CalendarTime>();
auto posix_time = CalendarToPosix(calendar_time, {});
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u32>(1); // Amount of times we're returning
ctx.WriteBuffer(&posix_time, sizeof(u64));
}
};
void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
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
2019-06-25 14:45:53 +00:00
rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardUserSystem);
}
void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
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
2019-06-25 14:45:53 +00:00
rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardNetworkSystem);
}
void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
2019-09-21 09:35:01 +00:00
rb.PushIpcInterface<ISteadyClock>(shared_memory, system);
}
void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ITimeZoneService>();
}
void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
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
2019-06-25 14:45:53 +00:00
rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardLocalSystem);
}
void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::RequestParser rp{ctx};
const auto initial_type = rp.PopRaw<u8>();
const s64 time_since_epoch{GetSecondsSinceEpoch().count()};
2018-11-10 01:31:48 +00:00
const std::time_t time(time_since_epoch);
const std::tm* tm = std::localtime(&time);
if (tm == nullptr) {
LOG_ERROR(Service_Time, "tm is a nullptr");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_UNKNOWN); // TODO(ogniK): Find appropriate error code
return;
}
2019-09-21 09:35:01 +00:00
const auto& core_timing = system.CoreTiming();
const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks());
const SteadyClockTimePoint steady_clock_time_point{static_cast<u64_le>(ms.count() / 1000), {}};
CalendarTime calendar_time{};
calendar_time.year = static_cast<u16_le>(tm->tm_year + 1900);
calendar_time.month = static_cast<u8>(tm->tm_mon + 1);
calendar_time.day = static_cast<u8>(tm->tm_mday);
calendar_time.hour = static_cast<u8>(tm->tm_hour);
calendar_time.minute = static_cast<u8>(tm->tm_min);
calendar_time.second = static_cast<u8>(tm->tm_sec);
ClockSnapshot clock_snapshot{};
clock_snapshot.system_posix_time = time_since_epoch;
clock_snapshot.network_posix_time = time_since_epoch;
clock_snapshot.system_calendar_time = calendar_time;
clock_snapshot.network_calendar_time = calendar_time;
CalendarAdditionalInfo additional_info{};
PosixToCalendar(time_since_epoch, calendar_time, additional_info, {});
clock_snapshot.system_calendar_info = additional_info;
clock_snapshot.network_calendar_info = additional_info;
clock_snapshot.steady_clock_timepoint = steady_clock_time_point;
clock_snapshot.location_name = LocationName{"UTC"};
clock_snapshot.clock_auto_adjustment_enabled = 1;
clock_snapshot.type = initial_type;
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
ctx.WriteBuffer(&clock_snapshot, sizeof(ClockSnapshot));
}
void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(
Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::RequestParser rp{ctx};
const auto snapshot_a = rp.PopRaw<ClockSnapshot>();
const auto snapshot_b = rp.PopRaw<ClockSnapshot>();
const u64 difference =
snapshot_b.user_clock_context.offset - snapshot_a.user_clock_context.offset;
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u64>(difference);
}
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
2019-06-25 14:45:53 +00:00
void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
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,
2019-09-21 09:35:01 +00:00
std::shared_ptr<SharedMemory> shared_memory, Core::System& system,
const char* name)
: ServiceFramework(name), time(std::move(time)), shared_memory(std::move(shared_memory)),
system(system) {}
hle/service: Default constructors and destructors in the cpp file where applicable When a destructor isn't defaulted into a cpp file, it can cause the use of forward declarations to seemingly fail to compile for non-obvious reasons. It also allows inlining of the construction/destruction logic all over the place where a constructor or destructor is invoked, which can lead to code bloat. This isn't so much a worry here, given the services won't be created and destroyed frequently. The cause of the above mentioned non-obvious errors can be demonstrated as follows: ------- Demonstrative example, if you know how the described error happens, skip forwards ------- Assume we have the following in the header, which we'll call "thing.h": \#include <memory> // Forward declaration. For example purposes, assume the definition // of Object is in some header named "object.h" class Object; class Thing { public: // assume no constructors or destructors are specified here, // or the constructors/destructors are defined as: // // Thing() = default; // ~Thing() = default; // // ... Some interface member functions would be defined here private: std::shared_ptr<Object> obj; }; If this header is included in a cpp file, (which we'll call "main.cpp"), this will result in a compilation error, because even though no destructor is specified, the destructor will still need to be generated by the compiler because std::shared_ptr's destructor is *not* trivial (in other words, it does something other than nothing), as std::shared_ptr's destructor needs to do two things: 1. Decrement the shared reference count of the object being pointed to, and if the reference count decrements to zero, 2. Free the Object instance's memory (aka deallocate the memory it's pointing to). And so the compiler generates the code for the destructor doing this inside main.cpp. Now, keep in mind, the Object forward declaration is not a complete type. All it does is tell the compiler "a type named Object exists" and allows us to use the name in certain situations to avoid a header dependency. So the compiler needs to generate destruction code for Object, but the compiler doesn't know *how* to destruct it. A forward declaration doesn't tell the compiler anything about Object's constructor or destructor. So, the compiler will issue an error in this case because it's undefined behavior to try and deallocate (or construct) an incomplete type and std::shared_ptr and std::unique_ptr make sure this isn't the case internally. Now, if we had defaulted the destructor in "thing.cpp", where we also include "object.h", this would never be an issue, as the destructor would only have its code generated in one place, and it would be in a place where the full class definition of Object would be visible to the compiler. ---------------------- End example ---------------------------- Given these service classes are more than certainly going to change in the future, this defaults the constructors and destructors into the relevant cpp files to make the construction and destruction of all of the services consistent and unlikely to run into cases where forward declarations are indirectly causing compilation errors. It also has the plus of avoiding the need to rebuild several services if destruction logic changes, since it would only be necessary to recompile the single cpp file.
2018-09-11 01:20:52 +00:00
Module::Interface::~Interface() = default;
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
2019-06-25 14:45:53 +00:00
void InstallInterfaces(Core::System& system) {
auto time = std::make_shared<Module>();
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
2019-06-25 14:45:53 +00:00
auto shared_mem = std::make_shared<SharedMemory>(system);
2019-09-21 09:35:01 +00:00
std::make_shared<Time>(time, shared_mem, system, "time:a")
->InstallAsService(system.ServiceManager());
std::make_shared<Time>(time, shared_mem, system, "time:s")
->InstallAsService(system.ServiceManager());
std::make_shared<Time>(std::move(time), shared_mem, system, "time:u")
2019-06-26 06:52:34 +00:00
->InstallAsService(system.ServiceManager());
}
} // namespace Service::Time