From babfcde88573153d222dd0fce68e8ffcbea4e186 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 21 Apr 2018 14:15:36 -0300 Subject: [PATCH] Check that the mutex address matches before waking a waiting thread --- Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs | 48 ++++++++++++++-------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs b/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs index f1a1178398..3482ebe0ff 100644 --- a/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs +++ b/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs @@ -187,31 +187,41 @@ namespace Ryujinx.Core.OsHle.Kernel return false; } - KThread OwnerThread = CurrThread.NextMutexThread; - - CurrThread.NextMutexThread = null; - - if (OwnerThread != null) + lock (CurrThread) { - int HasListeners = OwnerThread.NextMutexThread != null ? MutexHasListenersMask : 0; + //This is the new thread that will not own the mutex. + //If no threads are waiting for the lock, then it should be null. + KThread OwnerThread = CurrThread.NextMutexThread; - Process.Memory.WriteInt32(MutexAddress, HasListeners | OwnerThread.WaitHandle); + while (OwnerThread?.NextMutexThread != null && OwnerThread.MutexAddress != MutexAddress) + { + OwnerThread = OwnerThread.NextMutexThread; + } - OwnerThread.WaitHandle = 0; - OwnerThread.MutexAddress = 0; - OwnerThread.CondVarAddress = 0; + CurrThread.NextMutexThread = null; - OwnerThread.ResetPriority(); + if (OwnerThread != null) + { + int HasListeners = OwnerThread.NextMutexThread != null ? MutexHasListenersMask : 0; - Process.Scheduler.WakeUp(OwnerThread); + Process.Memory.WriteInt32(MutexAddress, HasListeners | OwnerThread.WaitHandle); - return true; - } - else - { - Process.Memory.WriteInt32(MutexAddress, 0); + OwnerThread.WaitHandle = 0; + OwnerThread.MutexAddress = 0; + OwnerThread.CondVarAddress = 0; - return false; + OwnerThread.ResetPriority(); + + Process.Scheduler.WakeUp(OwnerThread); + + return true; + } + else + { + Process.Memory.WriteInt32(MutexAddress, 0); + + return false; + } } } @@ -246,6 +256,8 @@ namespace Ryujinx.Core.OsHle.Kernel DoInsert &= CurrThread != WaitThread; } + //Only insert if the node doesn't already exist in the list. + //This prevents circular references. if (DoInsert) { if (WaitThread.NextCondVarThread != null)