diff --git a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
index 1c35b23c50..a154b1c619 100644
--- a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
+++ b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
@@ -1,130 +1,16 @@
 using Ryujinx.Core.Logging;
 using System;
 using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Threading;
 
 namespace Ryujinx.Core.OsHle.Handles
 {
     class KProcessScheduler : IDisposable
     {
-        private const int LowestPriority = 0x40;
-
-        private class SchedulerThread : IDisposable
-        {
-            public KThread Thread { get; private set; }
-
-            public bool IsActive { get; set; }
-
-            public AutoResetEvent   WaitSync     { get; private set; }
-            public ManualResetEvent WaitActivity { get; private set; }
-            public AutoResetEvent   WaitSched    { get; private set; }
-
-            public SchedulerThread(KThread Thread)
-            {
-                this.Thread = Thread;
-
-                IsActive = true;
-
-                WaitSync  = new AutoResetEvent(false);
-
-                WaitActivity = new ManualResetEvent(true);
-
-                WaitSched = new AutoResetEvent(false);
-            }
-
-            public void Dispose()
-            {
-                Dispose(true);
-            }
-
-            protected virtual void Dispose(bool Disposing)
-            {
-                if (Disposing)
-                {
-                    WaitSync.Dispose();
-
-                    WaitActivity.Dispose();
-
-                    WaitSched.Dispose();
-                }
-            }
-        }
-
-        private class ThreadQueue
-        {
-            private List<SchedulerThread> Threads;
-
-            public ThreadQueue()
-            {
-                Threads = new List<SchedulerThread>();
-            }
-
-            public void Push(SchedulerThread Thread)
-            {
-                lock (Threads)
-                {
-                    Threads.Add(Thread);
-                }
-            }
-
-            public SchedulerThread Pop(int MinPriority = LowestPriority)
-            {
-                lock (Threads)
-                {
-                    SchedulerThread SchedThread;
-
-                    int HighestPriority = MinPriority;
-
-                    int HighestPrioIndex = -1;
-
-                    for (int Index = 0; Index < Threads.Count; Index++)
-                    {
-                        SchedThread = Threads[Index];
-
-                        if (HighestPriority > SchedThread.Thread.ActualPriority)
-                        {
-                            HighestPriority = SchedThread.Thread.ActualPriority;
-
-                            HighestPrioIndex = Index;
-                        }
-                    }
-
-                    if (HighestPrioIndex == -1)
-                    {
-                        return null;
-                    }
-
-                    SchedThread = Threads[HighestPrioIndex];
-
-                    Threads.RemoveAt(HighestPrioIndex);
-
-                    return SchedThread;
-                }
-            }
-
-            public bool HasThread(SchedulerThread SchedThread)
-            {
-                lock (Threads)
-                {
-                    return Threads.Contains(SchedThread);
-                }
-            }
-
-            public bool Remove(SchedulerThread SchedThread)
-            {
-                lock (Threads)
-                {
-                    return Threads.Remove(SchedThread);
-                }
-            }
-        }
-
         private ConcurrentDictionary<KThread, SchedulerThread> AllThreads;
 
-        private ThreadQueue[] WaitingToRun;
+        private ThreadQueue WaitingToRun;
 
-        private HashSet<int> ActiveProcessors;
+        private int ActiveCores;
 
         private object SchedLock;
 
@@ -136,14 +22,7 @@ namespace Ryujinx.Core.OsHle.Handles
 
             AllThreads = new ConcurrentDictionary<KThread, SchedulerThread>();
 
-            WaitingToRun = new ThreadQueue[4];
-
-            for (int Index = 0; Index < 4; Index++)
-            {
-                WaitingToRun[Index] = new ThreadQueue();
-            }
-
-            ActiveProcessors = new HashSet<int>();
+            WaitingToRun = new ThreadQueue();
 
             SchedLock = new object();
         }
@@ -159,7 +38,7 @@ namespace Ryujinx.Core.OsHle.Handles
                     return;
                 }
 
-                if (ActiveProcessors.Add(Thread.ProcessorId))
+                if (AddActiveCore(Thread))
                 {
                     Thread.Thread.Execute();
 
@@ -167,7 +46,7 @@ namespace Ryujinx.Core.OsHle.Handles
                 }
                 else
                 {
-                    WaitingToRun[Thread.ProcessorId].Push(SchedThread);
+                    WaitingToRun.Push(SchedThread);
 
                     PrintDbgThreadInfo(Thread, "waiting to run.");
                 }
@@ -182,18 +61,18 @@ namespace Ryujinx.Core.OsHle.Handles
             {
                 if (AllThreads.TryRemove(Thread, out SchedulerThread SchedThread))
                 {
-                    WaitingToRun[Thread.ProcessorId].Remove(SchedThread);
+                    WaitingToRun.Remove(SchedThread);
 
                     SchedThread.Dispose();
                 }
 
-                SchedulerThread NewThread = WaitingToRun[Thread.ProcessorId].Pop();
+                SchedulerThread NewThread = WaitingToRun.Pop(Thread.ActualCore);
 
                 if (NewThread == null)
                 {
-                    Log.PrintDebug(LogClass.KernelScheduler, $"Nothing to run on core {Thread.ProcessorId}!");
+                    Log.PrintDebug(LogClass.KernelScheduler, $"Nothing to run on core {Thread.ActualCore}!");
 
-                    ActiveProcessors.Remove(Thread.ProcessorId);
+                    RemoveActiveCore(Thread.ActualCore);
 
                     return;
                 }
@@ -228,7 +107,7 @@ namespace Ryujinx.Core.OsHle.Handles
                 throw new InvalidOperationException();
             }
 
-            Suspend(Thread.ProcessorId);
+            Suspend(Thread);
 
             SchedThread.WaitSync.WaitOne();
 
@@ -242,7 +121,7 @@ namespace Ryujinx.Core.OsHle.Handles
                 throw new InvalidOperationException();
             }
 
-            Suspend(Thread.ProcessorId);
+            Suspend(Thread);
 
             bool Result = SchedThread.WaitSync.WaitOne(Timeout);
 
@@ -261,11 +140,13 @@ namespace Ryujinx.Core.OsHle.Handles
             SchedThread.WaitSync.Set();
         }
 
-        public void Suspend(int ProcessorId)
+        public void Suspend(KThread Thread)
         {
             lock (SchedLock)
             {
-                SchedulerThread SchedThread = WaitingToRun[ProcessorId].Pop();
+                PrintDbgThreadInfo(Thread, "suspended.");
+
+                SchedulerThread SchedThread = WaitingToRun.Pop(Thread.ActualCore);
 
                 if (SchedThread != null)
                 {
@@ -273,9 +154,9 @@ namespace Ryujinx.Core.OsHle.Handles
                 }
                 else
                 {
-                    Log.PrintDebug(LogClass.KernelScheduler, $"Nothing to run on core {ProcessorId}!");
+                    Log.PrintDebug(LogClass.KernelScheduler, $"Nothing to run on core {Thread.ActualCore}!");
 
-                    ActiveProcessors.Remove(ProcessorId);
+                    RemoveActiveCore(Thread.ActualCore);
                 }
             }
         }
@@ -288,7 +169,9 @@ namespace Ryujinx.Core.OsHle.Handles
             {
                 lock (SchedLock)
                 {
-                    SchedulerThread SchedThread = WaitingToRun[Thread.ProcessorId].Pop(Thread.ActualPriority);
+                    SchedulerThread SchedThread = WaitingToRun.Pop(
+                        Thread.ActualCore,
+                        Thread.ActualPriority);
 
                     if (SchedThread == null)
                     {
@@ -307,7 +190,7 @@ namespace Ryujinx.Core.OsHle.Handles
             {
                 //Just stop running the thread if it's not active,
                 //and run whatever is waiting to run with the higuest priority.
-                Suspend(Thread.ProcessorId);
+                Suspend(Thread);
             }
 
             Resume(Thread);
@@ -333,14 +216,14 @@ namespace Ryujinx.Core.OsHle.Handles
 
             lock (SchedLock)
             {
-                if (ActiveProcessors.Add(Thread.ProcessorId))
+                if (AddActiveCore(Thread))
                 {
                     PrintDbgThreadInfo(Thread, "resuming execution...");
 
                     return;
                 }
 
-                WaitingToRun[Thread.ProcessorId].Push(SchedThread);
+                WaitingToRun.Push(SchedThread);
 
                 PrintDbgThreadInfo(Thread, "entering wait state...");
             }
@@ -354,6 +237,8 @@ namespace Ryujinx.Core.OsHle.Handles
         {
             if (!SchedThread.Thread.Thread.Execute())
             {
+                PrintDbgThreadInfo(SchedThread.Thread, "waked.");
+
                 SchedThread.WaitSched.Set();
             }
             else
@@ -362,6 +247,14 @@ namespace Ryujinx.Core.OsHle.Handles
             }
         }
 
+        public void Resort(KThread Thread)
+        {
+            if (AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
+            {
+                WaitingToRun.Resort(SchedThread);
+            }
+        }
+
         private bool IsActive(KThread Thread)
         {
             if (!AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
@@ -372,11 +265,62 @@ namespace Ryujinx.Core.OsHle.Handles
             return SchedThread.IsActive;
         }
 
+        private bool AddActiveCore(KThread Thread)
+        {
+            lock (SchedLock)
+            {
+                //First, try running it on Ideal Core.
+                int CoreMask = 1 << Thread.IdealCore;
+
+                if ((ActiveCores & CoreMask) == 0)
+                {
+                    ActiveCores |= CoreMask;
+
+                    Thread.ActualCore = Thread.IdealCore;
+
+                    return true;
+                }
+
+                //If that fails, then try running on any core allowed by Core Mask.
+                CoreMask = Thread.CoreMask & ~ActiveCores;
+
+                if (CoreMask != 0)
+                {
+                    CoreMask &= -CoreMask;
+
+                    ActiveCores |= CoreMask;
+
+                    for (int Bit = 0; Bit < 32; Bit++)
+                    {
+                        if (((CoreMask >> Bit) & 1) != 0)
+                        {
+                            Thread.ActualCore = Bit;
+
+                            return true;
+                        }
+                    }
+
+                    throw new InvalidOperationException();
+                }
+
+                return false;
+            }
+        }
+
+        private void RemoveActiveCore(int Core)
+        {
+            lock (SchedLock)
+            {
+                ActiveCores &= ~(1 << Core);
+            }
+        }
+
         private void PrintDbgThreadInfo(KThread Thread, string Message)
         {
             Log.PrintDebug(LogClass.KernelScheduler, "(" +
                 "ThreadId = "       + Thread.ThreadId       + ", " +
-                "ProcessorId = "    + Thread.ProcessorId    + ", " +
+                "ActualCore = "     + Thread.ActualCore     + ", " +
+                "IdealCore = "      + Thread.IdealCore      + ", " +
                 "ActualPriority = " + Thread.ActualPriority + ", " +
                 "WantedPriority = " + Thread.WantedPriority + ") " + Message);
         }
diff --git a/Ryujinx.Core/OsHle/Handles/KThread.cs b/Ryujinx.Core/OsHle/Handles/KThread.cs
index 2084c2ba01..1a044665a3 100644
--- a/Ryujinx.Core/OsHle/Handles/KThread.cs
+++ b/Ryujinx.Core/OsHle/Handles/KThread.cs
@@ -7,9 +7,13 @@ namespace Ryujinx.Core.OsHle.Handles
     {
         public AThread Thread { get; private set; }
 
+        public int CoreMask { get; set; }
+
         public long MutexAddress   { get; set; }
         public long CondVarAddress { get; set; }
 
+        private Process Process;
+
         public KThread NextMutexThread   { get; set; }
         public KThread NextCondVarThread { get; set; }
 
@@ -18,16 +22,24 @@ namespace Ryujinx.Core.OsHle.Handles
         public int ActualPriority { get; private set; }
         public int WantedPriority { get; private set; }
 
-        public int ProcessorId  { get; private set; }
+        public int IdealCore  { get; private set; }
+        public int ActualCore { get; set; }
 
         public int WaitHandle { get; set; }
 
         public int ThreadId => Thread.ThreadId;
 
-        public KThread(AThread Thread, int ProcessorId, int Priority)
+        public KThread(
+            AThread Thread,
+            Process Process,
+            int     IdealCore,
+            int     Priority)
         {
-            this.Thread      = Thread;
-            this.ProcessorId = ProcessorId;
+            this.Thread    = Thread;
+            this.Process   = Process;
+            this.IdealCore = IdealCore;
+
+            CoreMask = 1 << IdealCore;
 
             ActualPriority = WantedPriority = Priority;
         }
@@ -54,59 +66,138 @@ namespace Ryujinx.Core.OsHle.Handles
             {
                 ActualPriority = CurrPriority;
 
-                UpdateWaitList();
+                UpdateWaitLists();
 
                 MutexOwner?.UpdatePriority();
             }
         }
 
-        private void UpdateWaitList()
+        private void UpdateWaitLists()
+        {
+            UpdateMutexList();
+            UpdateCondVarList();
+
+            Process.Scheduler.Resort(this);
+        }
+
+        private void UpdateMutexList()
         {
             KThread OwnerThread = MutexOwner;
 
-            if (OwnerThread != null)
+            if (OwnerThread == null)
             {
-                //The MutexOwner field should only be non null when the thread is
-                //waiting for the lock, and the lock belongs to another thread.
-                if (OwnerThread == this)
+                return;
+            }
+
+            //The MutexOwner field should only be non-null when the thread is
+            //waiting for the lock, and the lock belongs to another thread.
+            if (OwnerThread == this)
+            {
+                throw new InvalidOperationException();
+            }
+
+            lock (OwnerThread)
+            {
+                //Remove itself from the list.
+                KThread CurrThread = OwnerThread;
+
+                while (CurrThread.NextMutexThread != null)
                 {
-                    throw new InvalidOperationException();
+                    if (CurrThread.NextMutexThread == this)
+                    {
+                        CurrThread.NextMutexThread = NextMutexThread;
+
+                        break;
+                    }
+
+                    CurrThread = CurrThread.NextMutexThread;
                 }
 
-                lock (OwnerThread)
-                {
-                    //Remove itself from the list.
-                    KThread CurrThread = OwnerThread;
+                //Re-add taking new priority into account.
+                CurrThread = OwnerThread;
 
-                    while (CurrThread.NextMutexThread != null)
+                while (CurrThread.NextMutexThread != null)
+                {
+                    if (CurrThread.NextMutexThread.ActualPriority > ActualPriority)
                     {
-                        if (CurrThread.NextMutexThread == this)
+                        break;
+                    }
+
+                    CurrThread = CurrThread.NextMutexThread;
+                }
+
+                NextMutexThread = CurrThread.NextMutexThread;
+
+                CurrThread.NextMutexThread = this;
+            }
+        }
+
+        private void UpdateCondVarList()
+        {
+            lock (Process.ThreadArbiterListLock)
+            {
+                if (Process.ThreadArbiterListHead == null)
+                {
+                    return;
+                }
+
+                //Remove itself from the list.
+                bool Found;
+
+                KThread CurrThread = Process.ThreadArbiterListHead;
+
+                if (Found = (Process.ThreadArbiterListHead == this))
+                {
+                    Process.ThreadArbiterListHead = Process.ThreadArbiterListHead.NextCondVarThread;
+                }
+                else
+                {
+                    while (CurrThread.NextCondVarThread != null)
+                    {
+                        if (CurrThread.NextCondVarThread == this)
                         {
-                            CurrThread.NextMutexThread = NextMutexThread;
+                            CurrThread.NextCondVarThread = NextCondVarThread;
+
+                            Found = true;
 
                             break;
                         }
 
-                        CurrThread = CurrThread.NextMutexThread;
+                        CurrThread = CurrThread.NextCondVarThread;
                     }
-
-                    //Re-add taking new priority into account.
-                    CurrThread = OwnerThread;
-
-                    while (CurrThread.NextMutexThread != null)
-                    {
-                        if (CurrThread.NextMutexThread.ActualPriority < ActualPriority)
-                        {
-                            break;
-                        }
-
-                        CurrThread = CurrThread.NextMutexThread;
-                    }
-
-                    NextMutexThread = CurrThread.NextMutexThread;
-
-                    CurrThread.NextMutexThread = this;
                 }
+
+                if (!Found)
+                {
+                    return;
+                }
+
+                //Re-add taking new priority into account.
+                if (Process.ThreadArbiterListHead == null ||
+                    Process.ThreadArbiterListHead.ActualPriority > ActualPriority)
+                {
+                    NextCondVarThread = Process.ThreadArbiterListHead;
+
+                    Process.ThreadArbiterListHead = this;
+
+                    return;
+                }
+
+                CurrThread = Process.ThreadArbiterListHead;
+
+                while (CurrThread.NextCondVarThread != null)
+                {
+                    if (CurrThread.NextCondVarThread.ActualPriority > ActualPriority)
+                    {
+                        break;
+                    }
+
+                    CurrThread = CurrThread.NextCondVarThread;
+                }
+
+                NextCondVarThread = CurrThread.NextCondVarThread;
+
+                CurrThread.NextCondVarThread = this;
             }
         }
     }
diff --git a/Ryujinx.Core/OsHle/Handles/SchedulerThread.cs b/Ryujinx.Core/OsHle/Handles/SchedulerThread.cs
new file mode 100644
index 0000000000..4a8b4c09ef
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Handles/SchedulerThread.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Threading;
+
+namespace Ryujinx.Core.OsHle.Handles
+{
+    class SchedulerThread : IDisposable
+    {
+        public KThread Thread { get; private set; }
+
+        public SchedulerThread Next { get; set; }
+
+        public bool IsActive { get; set; }
+
+        public AutoResetEvent   WaitSync     { get; private set; }
+        public ManualResetEvent WaitActivity { get; private set; }
+        public AutoResetEvent   WaitSched    { get; private set; }
+
+        public SchedulerThread(KThread Thread)
+        {
+            this.Thread = Thread;
+
+            IsActive = true;
+
+            WaitSync  = new AutoResetEvent(false);
+
+            WaitActivity = new ManualResetEvent(true);
+
+            WaitSched = new AutoResetEvent(false);
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+        }
+
+        protected virtual void Dispose(bool Disposing)
+        {
+            if (Disposing)
+            {
+                WaitSync.Dispose();
+
+                WaitActivity.Dispose();
+
+                WaitSched.Dispose();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Handles/ThreadQueue.cs b/Ryujinx.Core/OsHle/Handles/ThreadQueue.cs
new file mode 100644
index 0000000000..41fbd81e1d
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Handles/ThreadQueue.cs
@@ -0,0 +1,158 @@
+namespace Ryujinx.Core.OsHle.Handles
+{
+    class ThreadQueue
+    {
+        private const int LowestPriority = 0x40;
+
+        private SchedulerThread Head;
+
+        private object ListLock;
+
+        public ThreadQueue()
+        {
+            ListLock = new object();
+        }
+
+        public void Push(SchedulerThread Wait)
+        {
+            lock (ListLock)
+            {
+                //Ensure that we're not creating circular references
+                //by adding a thread that is already on the list.
+                if (HasThread(Wait))
+                {
+                    return;
+                }
+
+                if (Head == null || Head.Thread.ActualPriority > Wait.Thread.ActualPriority)
+                {
+                    Wait.Next = Head;
+
+                    Head = Wait;
+
+                    return;
+                }
+
+                SchedulerThread Curr = Head;
+
+                while (Curr.Next != null)
+                {
+                    if (Curr.Next.Thread.ActualPriority > Wait.Thread.ActualPriority)
+                    {
+                        break;
+                    }
+
+                    Curr = Curr.Next;
+                }
+
+                Wait.Next = Curr.Next;
+                Curr.Next = Wait;
+            }
+        }
+
+        public SchedulerThread Pop(int Core, int MinPriority = LowestPriority)
+        {
+            lock (ListLock)
+            {
+                int CoreMask = 1 << Core;
+
+                SchedulerThread Prev = null;
+                SchedulerThread Curr = Head;
+
+                while (Curr != null)
+                {
+                    KThread Thread = Curr.Thread;
+
+                    if (Thread.ActualPriority <= MinPriority && (Thread.CoreMask & CoreMask) != 0)
+                    {
+                        if (Prev != null)
+                        {
+                            Prev.Next = Curr.Next;
+                        }
+                        else
+                        {
+                            Head = Head.Next;
+                        }
+
+                        break;
+                    }
+
+                    Prev = Curr;
+                    Curr = Curr.Next;
+                }
+
+                return Curr;
+            }
+        }
+
+        public bool Remove(SchedulerThread Thread)
+        {
+            lock (ListLock)
+            {
+                if (Head == null)
+                {
+                    return false;
+                }
+                else if (Head == Thread)
+                {
+                    Head = Head.Next;
+
+                    return true;
+                }
+
+                SchedulerThread Prev = Head;
+                SchedulerThread Curr = Head.Next;
+
+                while (Curr != null)
+                {
+                    if (Curr == Thread)
+                    {
+                        Prev.Next = Curr.Next;
+
+                        return true;
+                    }
+
+                    Prev = Curr;
+                    Curr = Curr.Next;
+                }
+
+                return false;
+            }
+        }
+
+        public bool Resort(SchedulerThread Thread)
+        {
+            lock (ListLock)
+            {
+                if (Remove(Thread))
+                {
+                    Push(Thread);
+
+                    return true;
+                }
+
+                return false;
+            }
+        }
+
+        public bool HasThread(SchedulerThread Thread)
+        {
+            lock (ListLock)
+            {
+                SchedulerThread Curr = Head;
+
+                while (Curr != null)
+                {
+                    if (Curr == Thread)
+                    {
+                        return true;
+                    }
+
+                    Curr = Curr.Next;
+                }
+
+                return false;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs b/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
index be394c4bbe..bbbd0fb0e0 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
@@ -22,8 +22,6 @@ namespace Ryujinx.Core.OsHle.Kernel
 
         private ConcurrentDictionary<KThread, AutoResetEvent> SyncWaits;
 
-        private object CondVarLock;
-
         private HashSet<(HSharedMem, long)> MappedSharedMems;
 
         private ulong CurrentHeapSize;
@@ -80,8 +78,6 @@ namespace Ryujinx.Core.OsHle.Kernel
 
             SyncWaits = new ConcurrentDictionary<KThread, AutoResetEvent>();
 
-            CondVarLock = new object();
-
             MappedSharedMems = new HashSet<(HSharedMem, long)>();
         }
 
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs b/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
index e5b080a88f..24317bdf05 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
@@ -131,7 +131,7 @@ namespace Ryujinx.Core.OsHle.Kernel
 
                 Handles[HandlesCount] = WaitEvent;
 
-                Process.Scheduler.Suspend(CurrThread.ProcessorId);
+                Process.Scheduler.Suspend(CurrThread);
 
                 int HandleIndex;
 
@@ -237,7 +237,7 @@ namespace Ryujinx.Core.OsHle.Kernel
 
             if (Session != null)
             {
-                Process.Scheduler.Suspend(CurrThread.ProcessorId);
+                Process.Scheduler.Suspend(CurrThread);
 
                 IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr);
 
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcThread.cs b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
index ee45c02c7e..71f3347a3c 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
@@ -75,7 +75,7 @@ namespace Ryujinx.Core.OsHle.Kernel
             }
             else
             {
-                Process.Scheduler.Suspend(CurrThread.ProcessorId);
+                Process.Scheduler.Suspend(CurrThread);
 
                 Thread.Sleep(NsTimeConverter.GetTimeMs(Ns));
 
@@ -132,7 +132,7 @@ namespace Ryujinx.Core.OsHle.Kernel
 
         private void SvcGetCurrentProcessorNumber(AThreadState ThreadState)
         {
-            ThreadState.X0 = (ulong)Process.GetThread(ThreadState.Tpidr).ProcessorId;
+            ThreadState.X0 = (ulong)Process.GetThread(ThreadState.Tpidr).ActualCore;
         }
 
         private void SvcGetThreadId(AThreadState ThreadState)
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs b/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs
index 57608cda43..0ca2a5f928 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs
@@ -260,17 +260,23 @@ namespace Ryujinx.Core.OsHle.Kernel
             WaitThread.MutexAddress   = MutexAddress;
             WaitThread.CondVarAddress = CondVarAddress;
 
-            lock (CondVarLock)
+            lock (Process.ThreadArbiterListLock)
             {
-                KThread CurrThread = Process.ThreadArbiterList;
+                KThread CurrThread = Process.ThreadArbiterListHead;
 
-                if (CurrThread != null)
+                if (CurrThread == null || CurrThread.ActualPriority > WaitThread.ActualPriority)
+                {
+                    WaitThread.NextCondVarThread = Process.ThreadArbiterListHead;
+
+                    Process.ThreadArbiterListHead = WaitThread;
+                }
+                else
                 {
                     bool DoInsert = CurrThread != WaitThread;
 
                     while (CurrThread.NextCondVarThread != null)
                     {
-                        if (CurrThread.NextCondVarThread.ActualPriority < WaitThread.ActualPriority)
+                        if (CurrThread.NextCondVarThread.ActualPriority > WaitThread.ActualPriority)
                         {
                             break;
                         }
@@ -293,10 +299,6 @@ namespace Ryujinx.Core.OsHle.Kernel
                         CurrThread.NextCondVarThread = WaitThread;
                     }
                 }
-                else
-                {
-                    Process.ThreadArbiterList = WaitThread;
-                }
             }
 
             Ns.Log.PrintDebug(LogClass.KernelSvc, "Entering wait state...");
@@ -315,10 +317,10 @@ namespace Ryujinx.Core.OsHle.Kernel
 
         private void CondVarSignal(long CondVarAddress, int Count)
         {
-            lock (CondVarLock)
+            lock (Process.ThreadArbiterListLock)
             {
                 KThread PrevThread = null;
-                KThread CurrThread = Process.ThreadArbiterList;
+                KThread CurrThread = Process.ThreadArbiterListHead;
 
                 while (CurrThread != null && (Count == -1 || Count > 0))
                 {
@@ -330,7 +332,7 @@ namespace Ryujinx.Core.OsHle.Kernel
                         }
                         else
                         {
-                            Process.ThreadArbiterList = CurrThread.NextCondVarThread;
+                            Process.ThreadArbiterListHead = CurrThread.NextCondVarThread;
                         }
 
                         CurrThread.NextCondVarThread = null;
@@ -401,7 +403,7 @@ namespace Ryujinx.Core.OsHle.Kernel
                         return;
                     }
 
-                    if (CurrThread.NextMutexThread.ActualPriority < WaitThread.ActualPriority)
+                    if (CurrThread.NextMutexThread.ActualPriority > WaitThread.ActualPriority)
                     {
                         break;
                     }
diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs
index 3ccbc01692..8520b9ad93 100644
--- a/Ryujinx.Core/OsHle/Process.cs
+++ b/Ryujinx.Core/OsHle/Process.cs
@@ -38,7 +38,9 @@ namespace Ryujinx.Core.OsHle
 
         public KProcessScheduler Scheduler { get; private set; }
 
-        public KThread ThreadArbiterList { get; set; }
+        public KThread ThreadArbiterListHead { get; set; }
+
+        public object ThreadArbiterListLock { get; private set; }
 
         public KProcessHandleTable HandleTable { get; private set; }
 
@@ -70,6 +72,8 @@ namespace Ryujinx.Core.OsHle
 
             Memory = new AMemory();
 
+            ThreadArbiterListLock = new object();
+
             HandleTable = new KProcessHandleTable();
 
             AppletState = new AppletStateMgr();
@@ -196,7 +200,7 @@ namespace Ryujinx.Core.OsHle
 
             AThread CpuThread = new AThread(GetTranslator(), Memory, EntryPoint);
 
-            KThread Thread = new KThread(CpuThread, ProcessorId, Priority);
+            KThread Thread = new KThread(CpuThread, this, ProcessorId, Priority);
 
             int Handle = HandleTable.OpenHandle(Thread);