Initial work to support changing thread core on the scheduler, also some cond var priority fixes

This commit is contained in:
gdkchan 2018-05-13 00:22:42 -03:00
parent 3603497a13
commit 4546d1b9be
9 changed files with 442 additions and 199 deletions

View file

@ -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;
}
}
}