Implement SystemClockContextUpdateCallback and co
This commit is contained in:
parent
9982ea30ff
commit
f0faf9bfe7
13 changed files with 170 additions and 37 deletions
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
|
{
|
||||||
|
class EphemeralNetworkSystemClockContextWriter : SystemClockContextUpdateCallback
|
||||||
|
{
|
||||||
|
protected override ResultCode Update()
|
||||||
|
{
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,10 +3,5 @@
|
||||||
class EphemeralNetworkSystemClockCore : SystemClockCore
|
class EphemeralNetworkSystemClockCore : SystemClockCore
|
||||||
{
|
{
|
||||||
public EphemeralNetworkSystemClockCore(SteadyClockCore steadyClockCore) : base(steadyClockCore) { }
|
public EphemeralNetworkSystemClockCore(SteadyClockCore steadyClockCore) : base(steadyClockCore) { }
|
||||||
|
|
||||||
protected override ResultCode Flush(SystemClockContext context)
|
|
||||||
{
|
|
||||||
return ResultCode.Success;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
|
{
|
||||||
|
class LocalSystemClockContextWriter : SystemClockContextUpdateCallback
|
||||||
|
{
|
||||||
|
private TimeSharedMemory _sharedMemory;
|
||||||
|
|
||||||
|
public LocalSystemClockContextWriter(TimeSharedMemory sharedMemory)
|
||||||
|
{
|
||||||
|
_sharedMemory = sharedMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ResultCode Update()
|
||||||
|
{
|
||||||
|
_sharedMemory.UpdateLocalSystemClockContext(_context);
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
|
{
|
||||||
|
class NetworkSystemClockContextWriter : SystemClockContextUpdateCallback
|
||||||
|
{
|
||||||
|
private TimeSharedMemory _sharedMemory;
|
||||||
|
|
||||||
|
public NetworkSystemClockContextWriter(TimeSharedMemory sharedMemory)
|
||||||
|
{
|
||||||
|
_sharedMemory = sharedMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ResultCode Update()
|
||||||
|
{
|
||||||
|
_sharedMemory.UpdateNetworkSystemClockContext(_context);
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,12 +3,5 @@
|
||||||
class StandardLocalSystemClockCore : SystemClockCore
|
class StandardLocalSystemClockCore : SystemClockCore
|
||||||
{
|
{
|
||||||
public StandardLocalSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore) {}
|
public StandardLocalSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore) {}
|
||||||
|
|
||||||
protected override ResultCode Flush(SystemClockContext context)
|
|
||||||
{
|
|
||||||
// TODO: set:sys SetUserSystemClockContext
|
|
||||||
|
|
||||||
return ResultCode.Success;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
_standardNetworkClockSufficientAccuracy = new TimeSpanType(0);
|
_standardNetworkClockSufficientAccuracy = new TimeSpanType(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override ResultCode Flush(SystemClockContext context)
|
|
||||||
{
|
|
||||||
// TODO: set:sys SetNetworkSystemClockContext
|
|
||||||
|
|
||||||
return ResultCode.Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsStandardNetworkSystemClockAccuracySufficient(KThread thread)
|
public bool IsStandardNetworkSystemClockAccuracySufficient(KThread thread)
|
||||||
{
|
{
|
||||||
SteadyClockCore steadyClockCore = GetSteadyClockCore();
|
SteadyClockCore steadyClockCore = GetSteadyClockCore();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
{
|
{
|
||||||
|
@ -16,13 +17,13 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
_networkSystemClockCore = networkSystemClockCore;
|
_networkSystemClockCore = networkSystemClockCore;
|
||||||
_autoCorrectionEnabled = false;
|
_autoCorrectionEnabled = false;
|
||||||
_autoCorrectionTime = SteadyClockTimePoint.GetRandom();
|
_autoCorrectionTime = SteadyClockTimePoint.GetRandom();
|
||||||
|
_autoCorrectionEvent = null;
|
||||||
_autoCorrectionEvent = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override ResultCode Flush(SystemClockContext context)
|
protected override ResultCode Flush(SystemClockContext context)
|
||||||
{
|
{
|
||||||
return ResultCode.NotImplemented;
|
// As UserSystemClock isn't a real system clock, this shouldn't happens.
|
||||||
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ResultCode GetClockContext(KThread thread, out SystemClockContext context)
|
public override ResultCode GetClockContext(KThread thread, out SystemClockContext context)
|
||||||
|
@ -83,6 +84,11 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
return _autoCorrectionEnabled;
|
return _autoCorrectionEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KReadableEvent GetAutomaticCorrectionReadableEvent()
|
||||||
|
{
|
||||||
|
return _autoCorrectionEvent.ReadableEvent;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetAutomaticCorrectionUpdatedTime(SteadyClockTimePoint steadyClockTimePoint)
|
public void SetAutomaticCorrectionUpdatedTime(SteadyClockTimePoint steadyClockTimePoint)
|
||||||
{
|
{
|
||||||
_autoCorrectionTime = steadyClockTimePoint;
|
_autoCorrectionTime = steadyClockTimePoint;
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
|
{
|
||||||
|
abstract class SystemClockContextUpdateCallback
|
||||||
|
{
|
||||||
|
private List<KEvent> _operationEventList;
|
||||||
|
protected SystemClockContext _context;
|
||||||
|
private bool _hasContext;
|
||||||
|
|
||||||
|
public SystemClockContextUpdateCallback()
|
||||||
|
{
|
||||||
|
_operationEventList = new List<KEvent>();
|
||||||
|
_context = new SystemClockContext();
|
||||||
|
_hasContext = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool NeedUpdate(SystemClockContext context)
|
||||||
|
{
|
||||||
|
if (_hasContext)
|
||||||
|
{
|
||||||
|
return _context.Offset != context.Offset || _context.SteadyTimePoint.ClockSourceId != context.SteadyTimePoint.ClockSourceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BroadcastOperationEvent()
|
||||||
|
{
|
||||||
|
Monitor.Enter(_operationEventList);
|
||||||
|
|
||||||
|
foreach (KEvent e in _operationEventList)
|
||||||
|
{
|
||||||
|
e.WritableEvent.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
Monitor.Exit(_operationEventList);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ResultCode Update();
|
||||||
|
|
||||||
|
public ResultCode Update(SystemClockContext context)
|
||||||
|
{
|
||||||
|
ResultCode result = ResultCode.Success;
|
||||||
|
|
||||||
|
if (NeedUpdate(context))
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
_hasContext = true;
|
||||||
|
|
||||||
|
result = Update();
|
||||||
|
|
||||||
|
if (result == ResultCode.Success)
|
||||||
|
{
|
||||||
|
BroadcastOperationEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,9 +4,10 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
{
|
{
|
||||||
abstract class SystemClockCore
|
abstract class SystemClockCore
|
||||||
{
|
{
|
||||||
private SteadyClockCore _steadyClockCore;
|
private SteadyClockCore _steadyClockCore;
|
||||||
private SystemClockContext _context;
|
private SystemClockContext _context;
|
||||||
private bool _isInitialized;
|
private bool _isInitialized;
|
||||||
|
private SystemClockContextUpdateCallback _systemClockContextUpdateCallback;
|
||||||
|
|
||||||
public SystemClockCore(SteadyClockCore steadyClockCore)
|
public SystemClockCore(SteadyClockCore steadyClockCore)
|
||||||
{
|
{
|
||||||
|
@ -15,6 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
_isInitialized = false;
|
_isInitialized = false;
|
||||||
|
|
||||||
_context.SteadyTimePoint.ClockSourceId = steadyClockCore.GetClockSourceId();
|
_context.SteadyTimePoint.ClockSourceId = steadyClockCore.GetClockSourceId();
|
||||||
|
_systemClockContextUpdateCallback = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual SteadyClockCore GetSteadyClockCore()
|
public virtual SteadyClockCore GetSteadyClockCore()
|
||||||
|
@ -79,7 +81,20 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract ResultCode Flush(SystemClockContext context);
|
protected virtual ResultCode Flush(SystemClockContext context)
|
||||||
|
{
|
||||||
|
if (_systemClockContextUpdateCallback == null)
|
||||||
|
{
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _systemClockContextUpdateCallback.Update(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetUpdateCallbackInstance(SystemClockContextUpdateCallback systemClockContextUpdateCallback)
|
||||||
|
{
|
||||||
|
_systemClockContextUpdateCallback = systemClockContextUpdateCallback;
|
||||||
|
}
|
||||||
|
|
||||||
public ResultCode SetSystemClockContext(SystemClockContext context)
|
public ResultCode SetSystemClockContext(SystemClockContext context)
|
||||||
{
|
{
|
||||||
|
|
|
@ -154,7 +154,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
{
|
{
|
||||||
if (_automaticCorrectionEvent == 0)
|
if (_automaticCorrectionEvent == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_timeManager.SharedMemory.GetSharedMemory(), out _automaticCorrectionEvent) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_timeManager.StandardUserSystemClock.GetAutomaticCorrectionReadableEvent(), out _automaticCorrectionEvent) != KernelResult.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,16 +24,18 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public StandardSteadyClockCore StandardSteadyClock { get; private set; }
|
public StandardSteadyClockCore StandardSteadyClock { get; private set; }
|
||||||
public TickBasedSteadyClockCore TickBasedSteadyClock { get; private set; }
|
public TickBasedSteadyClockCore TickBasedSteadyClock { get; private set; }
|
||||||
public StandardLocalSystemClockCore StandardLocalSystemClock { get; private set; }
|
public StandardLocalSystemClockCore StandardLocalSystemClock { get; private set; }
|
||||||
public StandardNetworkSystemClockCore StandardNetworkSystemClock { get; private set; }
|
public StandardNetworkSystemClockCore StandardNetworkSystemClock { get; private set; }
|
||||||
public StandardUserSystemClockCore StandardUserSystemClock { get; private set; }
|
public StandardUserSystemClockCore StandardUserSystemClock { get; private set; }
|
||||||
public TimeZoneManager TimeZone { get; private set; }
|
public TimeZoneManager TimeZone { get; private set; }
|
||||||
public EphemeralNetworkSystemClockCore EphemeralNetworkSystemClock { get; private set; }
|
public EphemeralNetworkSystemClockCore EphemeralNetworkSystemClock { get; private set; }
|
||||||
public TimeSharedMemory SharedMemory { get; private set; }
|
public TimeSharedMemory SharedMemory { get; private set; }
|
||||||
|
// TODO: 9.0.0+ power states and alarms
|
||||||
// TODO: 9.0.0+ power state, alarms, clock writers
|
public LocalSystemClockContextWriter LocalClockContextWriter { get; private set; }
|
||||||
|
public NetworkSystemClockContextWriter NetworkClockContextWriter { get; private set; }
|
||||||
|
public EphemeralNetworkSystemClockContextWriter EphemeralClockContextWriter { get; private set; }
|
||||||
|
|
||||||
public TimeManager()
|
public TimeManager()
|
||||||
{
|
{
|
||||||
|
@ -45,6 +47,9 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
TimeZone = new TimeZoneManager();
|
TimeZone = new TimeZoneManager();
|
||||||
EphemeralNetworkSystemClock = new EphemeralNetworkSystemClockCore(StandardSteadyClock);
|
EphemeralNetworkSystemClock = new EphemeralNetworkSystemClockCore(StandardSteadyClock);
|
||||||
SharedMemory = new TimeSharedMemory();
|
SharedMemory = new TimeSharedMemory();
|
||||||
|
LocalClockContextWriter = new LocalSystemClockContextWriter(SharedMemory);
|
||||||
|
NetworkClockContextWriter = new NetworkSystemClockContextWriter(SharedMemory);
|
||||||
|
EphemeralClockContextWriter = new EphemeralNetworkSystemClockContextWriter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(Switch device, Horizon system, KSharedMemory sharedMemory, long timeSharedMemoryAddress, int timeSharedMemorySize)
|
public void Initialize(Switch device, Horizon system, KSharedMemory sharedMemory, long timeSharedMemoryAddress, int timeSharedMemorySize)
|
||||||
|
@ -87,6 +92,8 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
|
|
||||||
public void SetupStandardLocalSystemClock(KThread thread, SystemClockContext clockContext, long posixTime)
|
public void SetupStandardLocalSystemClock(KThread thread, SystemClockContext clockContext, long posixTime)
|
||||||
{
|
{
|
||||||
|
StandardLocalSystemClock.SetUpdateCallbackInstance(LocalClockContextWriter);
|
||||||
|
|
||||||
SteadyClockTimePoint currentTimePoint = StandardLocalSystemClock.GetSteadyClockCore().GetCurrentTimePoint(thread);
|
SteadyClockTimePoint currentTimePoint = StandardLocalSystemClock.GetSteadyClockCore().GetCurrentTimePoint(thread);
|
||||||
if (currentTimePoint.ClockSourceId == clockContext.SteadyTimePoint.ClockSourceId)
|
if (currentTimePoint.ClockSourceId == clockContext.SteadyTimePoint.ClockSourceId)
|
||||||
{
|
{
|
||||||
|
@ -106,6 +113,8 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
|
|
||||||
public void SetupStandardNetworkSystemClock(SystemClockContext clockContext, TimeSpanType sufficientAccuracy)
|
public void SetupStandardNetworkSystemClock(SystemClockContext clockContext, TimeSpanType sufficientAccuracy)
|
||||||
{
|
{
|
||||||
|
StandardNetworkSystemClock.SetUpdateCallbackInstance(NetworkClockContextWriter);
|
||||||
|
|
||||||
// TODO: if the result of this is wrong, abort
|
// TODO: if the result of this is wrong, abort
|
||||||
StandardNetworkSystemClock.SetSystemClockContext(clockContext);
|
StandardNetworkSystemClock.SetSystemClockContext(clockContext);
|
||||||
|
|
||||||
|
@ -118,6 +127,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
|
|
||||||
public void SetupEphemeralNetworkSystemClock()
|
public void SetupEphemeralNetworkSystemClock()
|
||||||
{
|
{
|
||||||
|
EphemeralNetworkSystemClock.SetUpdateCallbackInstance(EphemeralClockContextWriter);
|
||||||
EphemeralNetworkSystemClock.MarkInitialized();
|
EphemeralNetworkSystemClock.MarkInitialized();
|
||||||
|
|
||||||
// TODO: propagate IPC late binding of "time:s" and "time:p"
|
// TODO: propagate IPC late binding of "time:s" and "time:p"
|
||||||
|
|
|
@ -42,5 +42,15 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateLocalSystemClockContext(SystemClockContext context)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateNetworkSystemClockContext(SystemClockContext context)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ using static Ryujinx.HLE.HOS.Services.Time.TimeZone.TimeZoneRule;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
{
|
{
|
||||||
|
// TODO: rewrite it for psc/glue changes + readd a correct locking around this
|
||||||
public sealed class TimeZoneManager
|
public sealed class TimeZoneManager
|
||||||
{
|
{
|
||||||
private const long TimeZoneBinaryTitleId = 0x010000000000080E;
|
private const long TimeZoneBinaryTitleId = 0x010000000000080E;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue