MacOSSystemInfo.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using System.Runtime.InteropServices;
  4. using System.Runtime.Versioning;
  5. using System.Text;
  6. using Ryujinx.Common.Logging;
  7. namespace Ryujinx.Common.SystemInfo
  8. {
  9. [SupportedOSPlatform("macos")]
  10. partial class MacOSSystemInfo : SystemInfo
  11. {
  12. internal MacOSSystemInfo()
  13. {
  14. string cpuName = GetCpuidCpuName();
  15. if (cpuName == null && sysctlbyname("machdep.cpu.brand_string", out cpuName) != 0)
  16. {
  17. cpuName = "Unknown";
  18. }
  19. ulong totalRAM = 0;
  20. if (sysctlbyname("hw.memsize", ref totalRAM) != 0) // Bytes
  21. {
  22. totalRAM = 0;
  23. }
  24. CpuName = $"{cpuName} ; {LogicalCoreCount} logical";
  25. RamTotal = totalRAM;
  26. RamAvailable = GetVMInfoAvailableMemory();
  27. }
  28. static ulong GetVMInfoAvailableMemory()
  29. {
  30. var port = mach_host_self();
  31. uint pageSize = 0;
  32. var result = host_page_size(port, ref pageSize);
  33. if (result != 0)
  34. {
  35. Logger.Error?.Print(LogClass.Application, $"Failed to query Available RAM. host_page_size() error = {result}");
  36. return 0;
  37. }
  38. const int flavor = 4; // HOST_VM_INFO64
  39. uint count = (uint)(Marshal.SizeOf<VMStatistics64>() / sizeof(int)); // HOST_VM_INFO64_COUNT
  40. VMStatistics64 stats = new();
  41. result = host_statistics64(port, flavor, ref stats, ref count);
  42. if (result != 0)
  43. {
  44. Logger.Error?.Print(LogClass.Application, $"Failed to query Available RAM. host_statistics64() error = {result}");
  45. return 0;
  46. }
  47. return (ulong)(stats.FreeCount + stats.InactiveCount) * pageSize;
  48. }
  49. private const string SystemLibraryName = "libSystem.dylib";
  50. [LibraryImport(SystemLibraryName, SetLastError = true)]
  51. private static partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, IntPtr oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
  52. private static int sysctlbyname(string name, IntPtr oldValue, ref ulong oldSize)
  53. {
  54. if (sysctlbyname(name, oldValue, ref oldSize, IntPtr.Zero, 0) == -1)
  55. {
  56. int err = Marshal.GetLastWin32Error();
  57. Logger.Error?.Print(LogClass.Application, $"Cannot retrieve '{name}'. Error Code {err}");
  58. return err;
  59. }
  60. return 0;
  61. }
  62. private static int sysctlbyname<T>(string name, ref T oldValue)
  63. {
  64. unsafe
  65. {
  66. ulong oldValueSize = (ulong)Unsafe.SizeOf<T>();
  67. return sysctlbyname(name, (IntPtr)Unsafe.AsPointer(ref oldValue), ref oldValueSize);
  68. }
  69. }
  70. private static int sysctlbyname(string name, out string oldValue)
  71. {
  72. oldValue = default;
  73. ulong strSize = 0;
  74. int res = sysctlbyname(name, IntPtr.Zero, ref strSize);
  75. if (res == 0)
  76. {
  77. byte[] rawData = new byte[strSize];
  78. unsafe
  79. {
  80. fixed (byte* rawDataPtr = rawData)
  81. {
  82. res = sysctlbyname(name, (IntPtr)rawDataPtr, ref strSize);
  83. }
  84. if (res == 0)
  85. {
  86. oldValue = Encoding.ASCII.GetString(rawData);
  87. }
  88. }
  89. }
  90. return res;
  91. }
  92. [LibraryImport(SystemLibraryName, SetLastError = true)]
  93. private static partial uint mach_host_self();
  94. [LibraryImport(SystemLibraryName, SetLastError = true)]
  95. private static partial int host_page_size(uint host, ref uint out_page_size);
  96. [StructLayout(LayoutKind.Sequential, Pack = 8)]
  97. struct VMStatistics64
  98. {
  99. public uint FreeCount;
  100. public uint ActiveCount;
  101. public uint InactiveCount;
  102. public uint WireCount;
  103. public ulong ZeroFillCount;
  104. public ulong Reactivations;
  105. public ulong Pageins;
  106. public ulong Pageouts;
  107. public ulong Faults;
  108. public ulong CowFaults;
  109. public ulong Lookups;
  110. public ulong Hits;
  111. public ulong Purges;
  112. public uint PurgeableCount;
  113. public uint SpeculativeCount;
  114. public ulong Decompressions;
  115. public ulong Compressions;
  116. public ulong Swapins;
  117. public ulong Swapouts;
  118. public uint CompressorPageCount;
  119. public uint ThrottledCount;
  120. public uint ExternalPageCount;
  121. public uint InternalPageCount;
  122. public ulong TotalUncompressedPagesInCompressor;
  123. }
  124. [LibraryImport(SystemLibraryName, SetLastError = true)]
  125. private static partial int host_statistics64(uint host_priv, int host_flavor, ref VMStatistics64 host_info64_out, ref uint host_info64_outCnt);
  126. }
  127. }