Implement SystemClockContextUpdateCallback and co

This commit is contained in:
Thog 2019-09-29 13:30:09 +02:00
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 class EphemeralNetworkSystemClockCore : SystemClockCore
{ {
public EphemeralNetworkSystemClockCore(SteadyClockCore steadyClockCore) : base(steadyClockCore) { } 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 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;
}
} }
} }

View file

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

View file

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

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

View file

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

View file

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

View file

@ -42,5 +42,15 @@ namespace Ryujinx.HLE.HOS.Services.Time
{ {
// TODO // 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 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;