Do not dirty memory tracking region handles if they are partially unmapped (#2536)

This commit is contained in:
gdkchan 2021-08-11 16:50:33 -03:00 committed by GitHub
parent 0f6ec446ea
commit bb8a920b63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -43,7 +43,26 @@ namespace Ryujinx.Memory.Tracking
private int _volatileCount = 0; private int _volatileCount = 0;
private bool _volatile; private bool _volatile;
internal MemoryPermission RequiredPermission => _preAction != null ? MemoryPermission.None : (Dirty ? MemoryPermission.ReadAndWrite : MemoryPermission.Read); internal MemoryPermission RequiredPermission
{
get
{
// If this is unmapped, allow reprotecting as RW as it can't be dirtied.
// This is required for the partial unmap cases where part of the data are still being accessed.
if (Unmapped)
{
return MemoryPermission.ReadAndWrite;
}
if (_preAction != null)
{
return MemoryPermission.None;
}
return Dirty ? MemoryPermission.ReadAndWrite : MemoryPermission.Read;
}
}
internal RegionSignal PreAction => _preAction; internal RegionSignal PreAction => _preAction;
/// <summary> /// <summary>
@ -96,6 +115,15 @@ namespace Ryujinx.Memory.Tracking
internal void Signal(ulong address, ulong size, bool write) internal void Signal(ulong address, ulong size, bool write)
{ {
RegionSignal action = Interlocked.Exchange(ref _preAction, null); RegionSignal action = Interlocked.Exchange(ref _preAction, null);
// If this handle was already unmapped (even if just partially),
// then we have nothing to do until it is mapped again.
// The pre-action should be still consumed to avoid flushing on remap.
if (Unmapped)
{
return;
}
action?.Invoke(address, size); action?.Invoke(address, size);
if (write) if (write)