SvcThreadSync.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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. ulong Timeout = 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. Process.Scheduler.Suspend(Thread.ProcessorId);
  51. MutualExclusion Mutex = GetMutex(MutexAddress);
  52. Mutex.Unlock();
  53. if (!GetCondVar(CondVarAddress).WaitForSignal(Thread, Timeout))
  54. {
  55. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
  56. return;
  57. }
  58. Mutex.WaitForLock(Thread);
  59. Process.Scheduler.Resume(Thread);
  60. ThreadState.X0 = 0;
  61. }
  62. private void SvcSignalProcessWideKey(AThreadState ThreadState)
  63. {
  64. long CondVarAddress = (long)ThreadState.X0;
  65. int Count = (int)ThreadState.X1;
  66. KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
  67. GetCondVar(CondVarAddress).SetSignal(CurrThread, Count);
  68. ThreadState.X0 = 0;
  69. }
  70. private MutualExclusion GetMutex(long MutexAddress)
  71. {
  72. MutualExclusion MutexFactory(long Key)
  73. {
  74. return new MutualExclusion(Process, MutexAddress);
  75. }
  76. return Mutexes.GetOrAdd(MutexAddress, MutexFactory);
  77. }
  78. private ConditionVariable GetCondVar(long CondVarAddress)
  79. {
  80. ConditionVariable CondVarFactory(long Key)
  81. {
  82. return new ConditionVariable(Process, CondVarAddress);
  83. }
  84. return CondVars.GetOrAdd(CondVarAddress, CondVarFactory);
  85. }
  86. }
  87. }