TimeSharedMemory.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. using Ryujinx.Cpu;
  2. using Ryujinx.HLE.HOS.Kernel.Memory;
  3. using Ryujinx.HLE.HOS.Services.Time.Clock;
  4. using Ryujinx.HLE.HOS.Services.Time.Types;
  5. using Ryujinx.HLE.Utilities;
  6. using System;
  7. using System.Runtime.CompilerServices;
  8. using System.Threading;
  9. namespace Ryujinx.HLE.HOS.Services.Time
  10. {
  11. class TimeSharedMemory
  12. {
  13. private Switch _device;
  14. private KSharedMemory _sharedMemory;
  15. private SharedMemoryStorage _timeSharedMemoryStorage;
  16. private int _timeSharedMemorySize;
  17. private const uint SteadyClockContextOffset = 0x00;
  18. private const uint LocalSystemClockContextOffset = 0x38;
  19. private const uint NetworkSystemClockContextOffset = 0x80;
  20. private const uint AutomaticCorrectionEnabledOffset = 0xC8;
  21. public void Initialize(Switch device, KSharedMemory sharedMemory, SharedMemoryStorage timeSharedMemoryStorage, int timeSharedMemorySize)
  22. {
  23. _device = device;
  24. _sharedMemory = sharedMemory;
  25. _timeSharedMemoryStorage = timeSharedMemoryStorage;
  26. _timeSharedMemorySize = timeSharedMemorySize;
  27. // Clean the shared memory
  28. timeSharedMemoryStorage.ZeroFill();
  29. }
  30. public KSharedMemory GetSharedMemory()
  31. {
  32. return _sharedMemory;
  33. }
  34. public void SetupStandardSteadyClock(ITickSource tickSource, UInt128 clockSourceId, TimeSpanType currentTimePoint)
  35. {
  36. TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(tickSource.Counter, tickSource.Frequency);
  37. SteadyClockContext context = new SteadyClockContext
  38. {
  39. InternalOffset = (ulong)(currentTimePoint.NanoSeconds - ticksTimeSpan.NanoSeconds),
  40. ClockSourceId = clockSourceId
  41. };
  42. WriteObjectToSharedMemory(SteadyClockContextOffset, 4, context);
  43. }
  44. public void SetAutomaticCorrectionEnabled(bool isAutomaticCorrectionEnabled)
  45. {
  46. // We convert the bool to byte here as a bool in C# takes 4 bytes...
  47. WriteObjectToSharedMemory(AutomaticCorrectionEnabledOffset, 0, Convert.ToByte(isAutomaticCorrectionEnabled));
  48. }
  49. public void SetSteadyClockRawTimePoint(ITickSource tickSource, TimeSpanType currentTimePoint)
  50. {
  51. SteadyClockContext context = ReadObjectFromSharedMemory<SteadyClockContext>(SteadyClockContextOffset, 4);
  52. TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(tickSource.Counter, tickSource.Frequency);
  53. context.InternalOffset = (ulong)(currentTimePoint.NanoSeconds - ticksTimeSpan.NanoSeconds);
  54. WriteObjectToSharedMemory(SteadyClockContextOffset, 4, context);
  55. }
  56. public void UpdateLocalSystemClockContext(SystemClockContext context)
  57. {
  58. WriteObjectToSharedMemory(LocalSystemClockContextOffset, 4, context);
  59. }
  60. public void UpdateNetworkSystemClockContext(SystemClockContext context)
  61. {
  62. WriteObjectToSharedMemory(NetworkSystemClockContextOffset, 4, context);
  63. }
  64. private T ReadObjectFromSharedMemory<T>(ulong offset, ulong padding) where T : unmanaged
  65. {
  66. T result;
  67. uint index;
  68. uint possiblyNewIndex;
  69. do
  70. {
  71. index = _timeSharedMemoryStorage.GetRef<uint>(offset);
  72. ulong objectOffset = offset + 4 + padding + (ulong)((index & 1) * Unsafe.SizeOf<T>());
  73. result = _timeSharedMemoryStorage.GetRef<T>(objectOffset);
  74. Thread.MemoryBarrier();
  75. possiblyNewIndex = _device.Memory.Read<uint>(offset);
  76. } while (index != possiblyNewIndex);
  77. return result;
  78. }
  79. private void WriteObjectToSharedMemory<T>(ulong offset, ulong padding, T value) where T : unmanaged
  80. {
  81. uint newIndex = _timeSharedMemoryStorage.GetRef<uint>(offset) + 1;
  82. ulong objectOffset = offset + 4 + padding + (ulong)((newIndex & 1) * Unsafe.SizeOf<T>());
  83. _timeSharedMemoryStorage.GetRef<T>(objectOffset) = value;
  84. Thread.MemoryBarrier();
  85. _timeSharedMemoryStorage.GetRef<uint>(offset) = newIndex;
  86. }
  87. }
  88. }