SvcThreadSync.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. using ChocolArm64.State;
  2. using Ryujinx.Core.OsHle.Handles;
  3. using static Ryujinx.Core.OsHle.ErrorCode;
  4. namespace Ryujinx.Core.OsHle.Kernel
  5. {
  6. partial class SvcHandler
  7. {
  8. private void SvcArbitrateLock(AThreadState ThreadState)
  9. {
  10. int OwnerThreadHandle = (int)ThreadState.X0;
  11. long MutexAddress = (long)ThreadState.X1;
  12. int RequestingThreadHandle = (int)ThreadState.X2;
  13. KThread OwnerThread = Process.HandleTable.GetData<KThread>(OwnerThreadHandle);
  14. if (OwnerThread == null)
  15. {
  16. Logging.Warn(LogClass.KernelSvc, $"Invalid owner thread handle 0x{OwnerThreadHandle:x8}!");
  17. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  18. return;
  19. }
  20. KThread RequestingThread = Process.HandleTable.GetData<KThread>(RequestingThreadHandle);
  21. if (RequestingThread == null)
  22. {
  23. Logging.Warn(LogClass.KernelSvc, $"Invalid requesting thread handle 0x{RequestingThreadHandle:x8}!");
  24. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  25. return;
  26. }
  27. MutualExclusion Mutex = GetMutex(MutexAddress);
  28. Mutex.WaitForLock(RequestingThread, OwnerThreadHandle);
  29. ThreadState.X0 = 0;
  30. }
  31. private void SvcArbitrateUnlock(AThreadState ThreadState)
  32. {
  33. long MutexAddress = (long)ThreadState.X0;
  34. GetMutex(MutexAddress).Unlock();
  35. Process.Scheduler.Yield(Process.GetThread(ThreadState.Tpidr));
  36. ThreadState.X0 = 0;
  37. }
  38. private void SvcWaitProcessWideKeyAtomic(AThreadState ThreadState)
  39. {
  40. long MutexAddress = (long)ThreadState.X0;
  41. long CondVarAddress = (long)ThreadState.X1;
  42. int ThreadHandle = (int)ThreadState.X2;
  43. long Timeout = (long)ThreadState.X3;
  44. KThread Thread = Process.HandleTable.GetData<KThread>(ThreadHandle);
  45. if (Thread == null)
  46. {
  47. Logging.Warn(LogClass.KernelSvc, $"Invalid thread handle 0x{ThreadHandle:x8}!");
  48. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  49. }
  50. MutualExclusion Mutex = GetMutex(MutexAddress);
  51. Mutex.Unlock();
  52. if (!GetCondVar(CondVarAddress).WaitForSignal(Thread, Timeout))
  53. {
  54. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
  55. return;
  56. }
  57. Mutex.WaitForLock(Thread);
  58. ThreadState.X0 = 0;
  59. }
  60. private void SvcSignalProcessWideKey(AThreadState ThreadState)
  61. {
  62. long CondVarAddress = (long)ThreadState.X0;
  63. int Count = (int)ThreadState.X1;
  64. KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
  65. GetCondVar(CondVarAddress).SetSignal(CurrThread, Count);
  66. ThreadState.X0 = 0;
  67. }
  68. private MutualExclusion GetMutex(long MutexAddress)
  69. {
  70. MutualExclusion MutexFactory(long Key)
  71. {
  72. return new MutualExclusion(Process, MutexAddress);
  73. }
  74. return Mutexes.GetOrAdd(MutexAddress, MutexFactory);
  75. }
  76. private ConditionVariable GetCondVar(long CondVarAddress)
  77. {
  78. ConditionVariable CondVarFactory(long Key)
  79. {
  80. return new ConditionVariable(Process, CondVarAddress);
  81. }
  82. return CondVars.GetOrAdd(CondVarAddress, CondVarFactory);
  83. }
  84. }
  85. }