Implement SystemClockContextUpdateCallback and co

This commit is contained in:
Thog 2019-09-29 13:30:09 +02:00
parent 9982ea30ff
commit f0faf9bfe7
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
13 changed files with 170 additions and 37 deletions

View file

@ -0,0 +1,10 @@
namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
class EphemeralNetworkSystemClockContextWriter : SystemClockContextUpdateCallback
{
protected override ResultCode Update()
{
return ResultCode.Success;
}
}
}

View file

@ -3,10 +3,5 @@
class EphemeralNetworkSystemClockCore : SystemClockCore
{
public EphemeralNetworkSystemClockCore(SteadyClockCore steadyClockCore) : base(steadyClockCore) { }
protected override ResultCode Flush(SystemClockContext context)
{
return ResultCode.Success;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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();

View file

@ -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;

View file

@ -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;
}
}
}

View file

@ -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)
{

View file

@ -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!");
}

View file

@ -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"

View file

@ -42,5 +42,15 @@ namespace Ryujinx.HLE.HOS.Services.Time
{
// TODO
}
public void UpdateLocalSystemClockContext(SystemClockContext context)
{
// TODO
}
public void UpdateNetworkSystemClockContext(SystemClockContext context)
{
// TODO
}
}
}

View file

@ -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;