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
|
||||
{
|
||||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
protected override ResultCode Flush(SystemClockContext context)
|
||||
{
|
||||
// TODO: set:sys SetNetworkSystemClockContext
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
public bool IsStandardNetworkSystemClockAccuracySufficient(KThread thread)
|
||||
{
|
||||
SteadyClockCore steadyClockCore = GetSteadyClockCore();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||
{
|
||||
|
@ -16,13 +17,13 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
_networkSystemClockCore = networkSystemClockCore;
|
||||
_autoCorrectionEnabled = false;
|
||||
_autoCorrectionTime = SteadyClockTimePoint.GetRandom();
|
||||
|
||||
_autoCorrectionEvent = null;
|
||||
_autoCorrectionEvent = null;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -83,6 +84,11 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
return _autoCorrectionEnabled;
|
||||
}
|
||||
|
||||
public KReadableEvent GetAutomaticCorrectionReadableEvent()
|
||||
{
|
||||
return _autoCorrectionEvent.ReadableEvent;
|
||||
}
|
||||
|
||||
public void SetAutomaticCorrectionUpdatedTime(SteadyClockTimePoint 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
|
||||
{
|
||||
private SteadyClockCore _steadyClockCore;
|
||||
private SystemClockContext _context;
|
||||
private bool _isInitialized;
|
||||
private SteadyClockCore _steadyClockCore;
|
||||
private SystemClockContext _context;
|
||||
private bool _isInitialized;
|
||||
private SystemClockContextUpdateCallback _systemClockContextUpdateCallback;
|
||||
|
||||
public SystemClockCore(SteadyClockCore steadyClockCore)
|
||||
{
|
||||
|
@ -15,6 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
_isInitialized = false;
|
||||
|
||||
_context.SteadyTimePoint.ClockSourceId = steadyClockCore.GetClockSourceId();
|
||||
_systemClockContextUpdateCallback = null;
|
||||
}
|
||||
|
||||
public virtual SteadyClockCore GetSteadyClockCore()
|
||||
|
@ -79,7 +81,20 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -154,7 +154,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
{
|
||||
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!");
|
||||
}
|
||||
|
|
|
@ -24,16 +24,18 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
}
|
||||
}
|
||||
|
||||
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; }
|
||||
public TimeSharedMemory SharedMemory { get; private set; }
|
||||
|
||||
// TODO: 9.0.0+ power state, alarms, clock writers
|
||||
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; }
|
||||
public TimeSharedMemory SharedMemory { get; private set; }
|
||||
// TODO: 9.0.0+ power states and alarms
|
||||
public LocalSystemClockContextWriter LocalClockContextWriter { get; private set; }
|
||||
public NetworkSystemClockContextWriter NetworkClockContextWriter { get; private set; }
|
||||
public EphemeralNetworkSystemClockContextWriter EphemeralClockContextWriter { get; private set; }
|
||||
|
||||
public TimeManager()
|
||||
{
|
||||
|
@ -45,6 +47,9 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
TimeZone = new TimeZoneManager();
|
||||
EphemeralNetworkSystemClock = new EphemeralNetworkSystemClockCore(StandardSteadyClock);
|
||||
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)
|
||||
|
@ -87,6 +92,8 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
|
||||
public void SetupStandardLocalSystemClock(KThread thread, SystemClockContext clockContext, long posixTime)
|
||||
{
|
||||
StandardLocalSystemClock.SetUpdateCallbackInstance(LocalClockContextWriter);
|
||||
|
||||
SteadyClockTimePoint currentTimePoint = StandardLocalSystemClock.GetSteadyClockCore().GetCurrentTimePoint(thread);
|
||||
if (currentTimePoint.ClockSourceId == clockContext.SteadyTimePoint.ClockSourceId)
|
||||
{
|
||||
|
@ -106,6 +113,8 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
|
||||
public void SetupStandardNetworkSystemClock(SystemClockContext clockContext, TimeSpanType sufficientAccuracy)
|
||||
{
|
||||
StandardNetworkSystemClock.SetUpdateCallbackInstance(NetworkClockContextWriter);
|
||||
|
||||
// TODO: if the result of this is wrong, abort
|
||||
StandardNetworkSystemClock.SetSystemClockContext(clockContext);
|
||||
|
||||
|
@ -118,6 +127,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
|
||||
public void SetupEphemeralNetworkSystemClock()
|
||||
{
|
||||
EphemeralNetworkSystemClock.SetUpdateCallbackInstance(EphemeralClockContextWriter);
|
||||
EphemeralNetworkSystemClock.MarkInitialized();
|
||||
|
||||
// TODO: propagate IPC late binding of "time:s" and "time:p"
|
||||
|
|
|
@ -42,5 +42,15 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
|||
{
|
||||
// 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
|
||||
{
|
||||
// TODO: rewrite it for psc/glue changes + readd a correct locking around this
|
||||
public sealed class TimeZoneManager
|
||||
{
|
||||
private const long TimeZoneBinaryTitleId = 0x010000000000080E;
|
||||
|
|
Loading…
Add table
Reference in a new issue