Move every clocks instances + timezone to a global manager

This commit is contained in:
Thog 2019-09-28 22:26:53 +02:00
parent 26b4aad831
commit eb02cfa777
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
12 changed files with 105 additions and 146 deletions

View file

@ -1,6 +1,6 @@
using LibHac.Fs;
using LibHac.Fs.NcaUtils;
using Ryujinx.HLE.HOS.Services.Time.TimeZone;
using Ryujinx.HLE.HOS.Services.Time;
using Ryujinx.HLE.Utilities;
using System;
using System.Collections.Generic;
@ -143,7 +143,7 @@ namespace Ryujinx.HLE.FileSystem.Content
}
}
TimeZoneManager.Instance.Initialize(_device);
TimeManager.Instance.TimeZone.Initialize(_device);
}
public void ClearEntry(long titleId, ContentType contentType, StorageId storageId)

View file

@ -22,6 +22,8 @@ using System.Linq;
using System.Reflection;
using System.Threading;
using TimeServiceManager = Ryujinx.HLE.HOS.Services.Time.TimeManager;
using NxStaticObject = Ryujinx.HLE.Loaders.Executables.NxStaticObject;
namespace Ryujinx.HLE.HOS
@ -202,13 +204,15 @@ namespace Ryujinx.HLE.HOS
// TODO: use set:sys (and set external clock source id from settings)
// TODO: use "time!standard_steady_clock_rtc_update_interval_minutes" and implement a worker thread to be accurate.
StandardSteadyClockCore.Instance.ConfigureSetupValue();
// TODO: migrate to 9.0.0+
TimeServiceManager.Instance.StandardSteadyClock.ConfigureSetupValue();
TimeServiceManager.Instance.StandardSteadyClock.MarkInitialized();
if (NxSettings.Settings.TryGetValue("time!standard_network_clock_sufficient_accuracy_minutes", out object standardNetworkClockSufficientAccuracyMinutes))
{
TimeSpanType standardNetworkClockSufficientAccuracy = new TimeSpanType((int)standardNetworkClockSufficientAccuracyMinutes * 60000000000);
StandardNetworkSystemClockCore.Instance.SetStandardNetworkClockSufficientAccuracy(standardNetworkClockSufficientAccuracy);
TimeServiceManager.Instance.StandardNetworkSystemClock.SetStandardNetworkClockSufficientAccuracy(standardNetworkClockSufficientAccuracy);
}
}

View file

@ -2,21 +2,6 @@
{
class EphemeralNetworkSystemClockCore : SystemClockCore
{
private static EphemeralNetworkSystemClockCore _instance;
public static EphemeralNetworkSystemClockCore Instance
{
get
{
if (_instance == null)
{
_instance = new EphemeralNetworkSystemClockCore(TickBasedSteadyClockCore.Instance);
}
return _instance;
}
}
public EphemeralNetworkSystemClockCore(SteadyClockCore steadyClockCore) : base(steadyClockCore) { }
protected override ResultCode Flush(SystemClockContext context)

View file

@ -2,21 +2,6 @@
{
class StandardLocalSystemClockCore : SystemClockCore
{
private static StandardLocalSystemClockCore _instance;
public static StandardLocalSystemClockCore Instance
{
get
{
if (_instance == null)
{
_instance = new StandardLocalSystemClockCore(StandardSteadyClockCore.Instance);
}
return _instance;
}
}
public StandardLocalSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore) {}
protected override ResultCode Flush(SystemClockContext context)

View file

@ -6,21 +6,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
private TimeSpanType _standardNetworkClockSufficientAccuracy;
private static StandardNetworkSystemClockCore _instance;
public static StandardNetworkSystemClockCore Instance
{
get
{
if (_instance == null)
{
_instance = new StandardNetworkSystemClockCore(StandardSteadyClockCore.Instance);
}
return _instance;
}
}
public StandardNetworkSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore)
{
_standardNetworkClockSufficientAccuracy = new TimeSpanType(0);

View file

@ -7,27 +7,12 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
private TimeSpanType _setupValue;
// TODO: move this to glue when we will have psc fully done
//private ResultCode _setupResultCode;
private ResultCode _setupResultCode;
private TimeSpanType _testOffset;
private TimeSpanType _internalOffset;
private TimeSpanType _cachedRawTimePoint;
private static StandardSteadyClockCore _instance;
public static StandardSteadyClockCore Instance
{
get
{
if (_instance == null)
{
_instance = new StandardSteadyClockCore();
}
return _instance;
}
}
private StandardSteadyClockCore()
public StandardSteadyClockCore()
{
_setupValue = new TimeSpanType(0);
_testOffset = new TimeSpanType(0);
@ -83,7 +68,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
}
// TODO: move this to glue when we will have psc fully done
/*public void ConfigureSetupValue()
public void ConfigureSetupValue()
{
int retry = 0;
@ -103,6 +88,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
}
_setupResultCode = result;
}*/
}
}
}

View file

@ -8,21 +8,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
private StandardNetworkSystemClockCore _networkSystemClockCore;
private bool _autoCorrectionEnabled;
private static StandardUserSystemClockCore _instance;
public static StandardUserSystemClockCore Instance
{
get
{
if (_instance == null)
{
_instance = new StandardUserSystemClockCore(StandardLocalSystemClockCore.Instance, StandardNetworkSystemClockCore.Instance);
}
return _instance;
}
}
public StandardUserSystemClockCore(StandardLocalSystemClockCore localSystemClockCore, StandardNetworkSystemClockCore networkSystemClockCore) : base(localSystemClockCore.GetSteadyClockCore())
{
_localSystemClockCore = localSystemClockCore;

View file

@ -4,22 +4,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
class TickBasedSteadyClockCore : SteadyClockCore
{
private static TickBasedSteadyClockCore _instance;
public static TickBasedSteadyClockCore Instance
{
get
{
if (_instance == null)
{
_instance = new TickBasedSteadyClockCore();
}
return _instance;
}
}
private TickBasedSteadyClockCore() {}
public TickBasedSteadyClockCore() {}
public override SteadyClockTimePoint GetTimePoint(KThread thread)
{

View file

@ -15,25 +15,27 @@ namespace Ryujinx.HLE.HOS.Services.Time
//[Service("time:a", TimePermissions.Admin)]
[Service("time:s", TimePermissions.System)]
//[Service("time:u", TimePermissions.User)]
[Service("time:su", TimePermissions.System)]
[Service("time:su", TimePermissions.SystemUpdate)]
class IStaticService : IpcService
{
private TimeManager _timeManager;
private TimePermissions _permissions;
private int _timeSharedMemoryNativeHandle = 0;
private static readonly DateTime StartupDate = DateTime.UtcNow;
public IStaticService(ServiceCtx context, TimePermissions permissions) : this(TimeManager.Instance, permissions) {}
public IStaticService(ServiceCtx context, TimePermissions permissions)
public IStaticService(TimeManager manager, TimePermissions permissions)
{
_permissions = permissions;
_timeManager = manager;
}
[Command(0)]
// GetStandardUserSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
public ResultCode GetStandardUserSystemClock(ServiceCtx context)
{
MakeObject(context, new ISystemClock(StandardUserSystemClockCore.Instance, (_permissions & TimePermissions.UserSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
MakeObject(context, new ISystemClock(_timeManager.StandardUserSystemClock, (_permissions & TimePermissions.UserSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
return ResultCode.Success;
}
@ -42,7 +44,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// GetStandardNetworkSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
public ResultCode GetStandardNetworkSystemClock(ServiceCtx context)
{
MakeObject(context, new ISystemClock(StandardNetworkSystemClockCore.Instance, (_permissions & TimePermissions.NetworkSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
MakeObject(context, new ISystemClock(_timeManager.StandardNetworkSystemClock, (_permissions & TimePermissions.NetworkSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
return ResultCode.Success;
}
@ -51,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// GetStandardSteadyClock() -> object<nn::timesrv::detail::service::ISteadyClock>
public ResultCode GetStandardSteadyClock(ServiceCtx context)
{
MakeObject(context, new ISteadyClock(StandardSteadyClockCore.Instance, (_permissions & TimePermissions.SteadyClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
MakeObject(context, new ISteadyClock(_timeManager.StandardSteadyClock, (_permissions & TimePermissions.SteadyClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
return ResultCode.Success;
}
@ -60,7 +62,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// GetTimeZoneService() -> object<nn::timesrv::detail::service::ITimeZoneService>
public ResultCode GetTimeZoneService(ServiceCtx context)
{
MakeObject(context, new ITimeZoneService());
MakeObject(context, new ITimeZoneService(_timeManager.TimeZone, (_permissions & TimePermissions.TimeZoneWritableMask) != 0));
return ResultCode.Success;
}
@ -69,7 +71,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// GetStandardLocalSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
public ResultCode GetStandardLocalSystemClock(ServiceCtx context)
{
MakeObject(context, new ISystemClock(StandardLocalSystemClockCore.Instance, (_permissions & TimePermissions.LocalSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
MakeObject(context, new ISystemClock(_timeManager.StandardLocalSystemClock, (_permissions & TimePermissions.LocalSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
return ResultCode.Success;
}
@ -78,7 +80,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// GetEphemeralNetworkSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
public ResultCode GetEphemeralNetworkSystemClock(ServiceCtx context)
{
MakeObject(context, new ISystemClock(StandardNetworkSystemClockCore.Instance, (_permissions & TimePermissions.NetworkSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
MakeObject(context, new ISystemClock(_timeManager.StandardNetworkSystemClock, (_permissions & TimePermissions.NetworkSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
return ResultCode.Success;
}
@ -104,7 +106,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// IsStandardUserSystemClockAutomaticCorrectionEnabled() -> bool
public ResultCode IsStandardUserSystemClockAutomaticCorrectionEnabled(ServiceCtx context)
{
StandardUserSystemClockCore userClock = StandardUserSystemClockCore.Instance;
StandardUserSystemClockCore userClock = _timeManager.StandardUserSystemClock;
if (!userClock.IsInitialized())
{
@ -120,8 +122,8 @@ namespace Ryujinx.HLE.HOS.Services.Time
// SetStandardUserSystemClockAutomaticCorrectionEnabled(b8)
public ResultCode SetStandardUserSystemClockAutomaticCorrectionEnabled(ServiceCtx context)
{
SteadyClockCore steadyClock = StandardSteadyClockCore.Instance;
StandardUserSystemClockCore userClock = StandardUserSystemClockCore.Instance;
SteadyClockCore steadyClock = _timeManager.StandardSteadyClock;
StandardUserSystemClockCore userClock = _timeManager.StandardUserSystemClock;
if (!userClock.IsInitialized() || !steadyClock.IsInitialized())
{
@ -135,14 +137,14 @@ namespace Ryujinx.HLE.HOS.Services.Time
bool autoCorrectionEnabled = context.RequestData.ReadBoolean();
return StandardUserSystemClockCore.Instance.SetAutomaticCorrectionEnabled(context.Thread, autoCorrectionEnabled);
return userClock.SetAutomaticCorrectionEnabled(context.Thread, autoCorrectionEnabled);
}
[Command(200)] // 3.0.0+
// IsStandardNetworkSystemClockAccuracySufficient() -> bool
public ResultCode IsStandardNetworkSystemClockAccuracySufficient(ServiceCtx context)
{
context.ResponseData.Write(StandardNetworkSystemClockCore.Instance.IsStandardNetworkSystemClockAccuracySufficient(context.Thread));
context.ResponseData.Write(_timeManager.StandardNetworkSystemClock.IsStandardNetworkSystemClockAccuracySufficient(context.Thread));
return ResultCode.Success;
}
@ -151,7 +153,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
// CalculateMonotonicSystemClockBaseTimePoint(nn::time::SystemClockContext) -> s64
public ResultCode CalculateMonotonicSystemClockBaseTimePoint(ServiceCtx context)
{
SteadyClockCore steadyClock = StandardSteadyClockCore.Instance;
SteadyClockCore steadyClock = _timeManager.StandardSteadyClock;
if (!steadyClock.IsInitialized())
{
@ -182,11 +184,11 @@ namespace Ryujinx.HLE.HOS.Services.Time
{
byte type = context.RequestData.ReadByte();
ResultCode result = StandardUserSystemClockCore.Instance.GetClockContext(context.Thread, out SystemClockContext userContext);
ResultCode result = _timeManager.StandardUserSystemClock.GetClockContext(context.Thread, out SystemClockContext userContext);
if (result == ResultCode.Success)
{
result = StandardNetworkSystemClockCore.Instance.GetClockContext(context.Thread, out SystemClockContext networkContext);
result = _timeManager.StandardNetworkSystemClock.GetClockContext(context.Thread, out SystemClockContext networkContext);
if (result == ResultCode.Success)
{
@ -280,14 +282,14 @@ namespace Ryujinx.HLE.HOS.Services.Time
{
clockSnapshot = new ClockSnapshot();
SteadyClockCore steadyClockCore = StandardSteadyClockCore.Instance;
SteadyClockCore steadyClockCore = _timeManager.StandardSteadyClock;
SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(thread);
clockSnapshot.IsAutomaticCorrectionEnabled = StandardUserSystemClockCore.Instance.IsAutomaticCorrectionEnabled();
clockSnapshot.IsAutomaticCorrectionEnabled = _timeManager.StandardUserSystemClock.IsAutomaticCorrectionEnabled();
clockSnapshot.UserContext = userContext;
clockSnapshot.NetworkContext = networkContext;
char[] tzName = TimeZoneManager.Instance.GetDeviceLocationName().ToCharArray();
char[] tzName = _timeManager.TimeZone.GetDeviceLocationName().ToCharArray();
char[] locationName = new char[0x24];
Array.Copy(tzName, locationName, tzName.Length);
@ -298,7 +300,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
if (result == ResultCode.Success)
{
result = TimeZoneManager.Instance.ToCalendarTimeWithMyRules(clockSnapshot.UserTime, out CalendarInfo userCalendarInfo);
result = _timeManager.TimeZone.ToCalendarTimeWithMyRules(clockSnapshot.UserTime, out CalendarInfo userCalendarInfo);
if (result == ResultCode.Success)
{
@ -310,7 +312,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
clockSnapshot.NetworkTime = 0;
}
result = TimeZoneManager.Instance.ToCalendarTimeWithMyRules(clockSnapshot.NetworkTime, out CalendarInfo networkCalendarInfo);
result = _timeManager.TimeZone.ToCalendarTimeWithMyRules(clockSnapshot.NetworkTime, out CalendarInfo networkCalendarInfo);
if (result == ResultCode.Success)
{

View file

@ -9,13 +9,20 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
{
class ITimeZoneService : IpcService
{
public ITimeZoneService() { }
private TimeZoneManager _timeZoneManager;
private bool _writePermission;
public ITimeZoneService(TimeZoneManager timeZoneManager, bool writePermission)
{
_timeZoneManager = timeZoneManager;
_writePermission = writePermission;
}
[Command(0)]
// GetDeviceLocationName() -> nn::time::LocationName
public ResultCode GetDeviceLocationName(ServiceCtx context)
{
char[] tzName = TimeZoneManager.Instance.GetDeviceLocationName().ToCharArray();
char[] tzName = _timeZoneManager.GetDeviceLocationName().ToCharArray();
int padding = 0x24 - tzName.Length;
@ -38,16 +45,21 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
// SetDeviceLocationName(nn::time::LocationName)
public ResultCode SetDeviceLocationName(ServiceCtx context)
{
if (!_writePermission)
{
return ResultCode.PermissionDenied;
}
string locationName = Encoding.ASCII.GetString(context.RequestData.ReadBytes(0x24)).TrimEnd('\0');
return TimeZoneManager.Instance.SetDeviceLocationName(locationName);
return _timeZoneManager.SetDeviceLocationName(locationName);
}
[Command(2)]
// GetTotalLocationNameCount() -> u32
public ResultCode GetTotalLocationNameCount(ServiceCtx context)
{
context.ResponseData.Write(TimeZoneManager.Instance.GetTotalLocationNameCount());
context.ResponseData.Write(_timeZoneManager.GetTotalLocationNameCount());
return ResultCode.Success;
}
@ -60,7 +72,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
long bufferPosition = context.Request.ReceiveBuff[0].Position;
long bufferSize = context.Request.ReceiveBuff[0].Size;
ResultCode errorCode = TimeZoneManager.Instance.LoadLocationNameList(index, out string[] locationNameArray, (uint)bufferSize / 0x24);
ResultCode errorCode = _timeZoneManager.LoadLocationNameList(index, out string[] locationNameArray, (uint)bufferSize / 0x24);
if (errorCode == 0)
{
@ -105,7 +117,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
string locationName = Encoding.ASCII.GetString(context.RequestData.ReadBytes(0x24)).TrimEnd('\0');
ResultCode resultCode = TimeZoneManager.Instance.LoadTimeZoneRules(out TimeZoneRule rules, locationName);
ResultCode resultCode = _timeZoneManager.LoadTimeZoneRules(out TimeZoneRule rules, locationName);
// Write TimeZoneRule if success
if (resultCode == 0)
@ -150,7 +162,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
{
long posixTime = context.RequestData.ReadInt64();
ResultCode resultCode = TimeZoneManager.Instance.ToCalendarTimeWithMyRules(posixTime, out CalendarInfo calendar);
ResultCode resultCode = _timeZoneManager.ToCalendarTimeWithMyRules(posixTime, out CalendarInfo calendar);
if (resultCode == 0)
{
@ -199,7 +211,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
{
CalendarTime calendarTime = context.RequestData.ReadStruct<CalendarTime>();
ResultCode resultCode = TimeZoneManager.Instance.ToPosixTimeWithMyRules(calendarTime, out long posixTime);
ResultCode resultCode = _timeZoneManager.ToPosixTimeWithMyRules(calendarTime, out long posixTime);
if (resultCode == 0)
{

View file

@ -0,0 +1,47 @@
using Ryujinx.HLE.HOS.Services.Time.Clock;
using Ryujinx.HLE.HOS.Services.Time.TimeZone;
using System;
using System.Collections.Generic;
using System.Text;
namespace Ryujinx.HLE.HOS.Services.Time
{
class TimeManager
{
private static TimeManager _instance;
public static TimeManager Instance
{
get
{
if (_instance == null)
{
_instance = new TimeManager();
}
return _instance;
}
}
public StandardSteadyClockCore StandardSteadyClock { get; private set; }
public TickBasedSteadyClockCore TickBasedSteadyClock { get; private set; }
public StandardLocalSystemClockCore StandardLocalSystemClock { get; private set; }
public StandardNetworkSystemClockCore StandardNetworkSystemClock { get; private set; }
public StandardUserSystemClockCore StandardUserSystemClock { get; private set; }
public TimeZoneManager TimeZone { get; private set; }
public EphemeralNetworkSystemClockCore EphemeralNetworkSystemClock { get; private set; }
// TODO: 9.0.0+ power state, alarms, clock writers
public TimeManager()
{
StandardSteadyClock = new StandardSteadyClockCore();
TickBasedSteadyClock = new TickBasedSteadyClockCore();
StandardLocalSystemClock = new StandardLocalSystemClockCore(StandardSteadyClock);
StandardNetworkSystemClock = new StandardNetworkSystemClockCore(StandardSteadyClock);
StandardUserSystemClock = new StandardUserSystemClockCore(StandardLocalSystemClock, StandardNetworkSystemClock);
TimeZone = new TimeZoneManager();
EphemeralNetworkSystemClock = new EphemeralNetworkSystemClockCore(StandardSteadyClock);
}
}
}

View file

@ -26,23 +26,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
private string _deviceLocationName;
private string[] _locationNameCache;
public static TimeZoneManager Instance
{
get
{
lock (instanceLock)
{
if (instance == null)
{
instance = new TimeZoneManager();
}
return instance;
}
}
}
TimeZoneManager()
public TimeZoneManager()
{
// Empty rules (UTC)
_myRules = new TimeZoneRule