KSharedMemory.cs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. using Ryujinx.Common;
  2. using Ryujinx.HLE.HOS.Kernel.Common;
  3. using Ryujinx.HLE.HOS.Kernel.Process;
  4. using Ryujinx.Horizon.Common;
  5. using Ryujinx.Memory;
  6. namespace Ryujinx.HLE.HOS.Kernel.Memory
  7. {
  8. class KSharedMemory : KAutoObject
  9. {
  10. private readonly KPageList _pageList;
  11. private readonly ulong _ownerPid;
  12. private readonly KMemoryPermission _ownerPermission;
  13. private readonly KMemoryPermission _userPermission;
  14. public KSharedMemory(
  15. KernelContext context,
  16. SharedMemoryStorage storage,
  17. ulong ownerPid,
  18. KMemoryPermission ownerPermission,
  19. KMemoryPermission userPermission) : base(context)
  20. {
  21. _pageList = storage.GetPageList();
  22. _ownerPid = ownerPid;
  23. _ownerPermission = ownerPermission;
  24. _userPermission = userPermission;
  25. }
  26. public Result MapIntoProcess(
  27. KPageTableBase memoryManager,
  28. ulong address,
  29. ulong size,
  30. KProcess process,
  31. KMemoryPermission permission)
  32. {
  33. if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, KPageTableBase.PageSize))
  34. {
  35. return KernelResult.InvalidSize;
  36. }
  37. KMemoryPermission expectedPermission = process.Pid == _ownerPid
  38. ? _ownerPermission
  39. : _userPermission;
  40. if (permission != expectedPermission)
  41. {
  42. return KernelResult.InvalidPermission;
  43. }
  44. // On platforms with page size > 4 KB, this can fail due to the address not being page aligned,
  45. // we can return an error to force the application to retry with a different address.
  46. try
  47. {
  48. return memoryManager.MapPages(address, _pageList, MemoryState.SharedMemory, permission);
  49. }
  50. catch (InvalidMemoryRegionException)
  51. {
  52. return KernelResult.InvalidMemState;
  53. }
  54. }
  55. public Result UnmapFromProcess(KPageTableBase memoryManager, ulong address, ulong size, KProcess process)
  56. {
  57. if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, KPageTableBase.PageSize))
  58. {
  59. return KernelResult.InvalidSize;
  60. }
  61. return memoryManager.UnmapPages(address, _pageList, MemoryState.SharedMemory);
  62. }
  63. }
  64. }