Ensure that all threads wait for a read tracking action to complete. (#2597)
* Lock around tracking action consume + execute. Not particularly fast. * Lock around preaction registration and use * Create a lock object * Nit
This commit is contained in:
parent
76e8f9ac87
commit
54adc5f9fb
1 changed files with 19 additions and 9 deletions
|
@ -35,6 +35,7 @@ namespace Ryujinx.Memory.Tracking
|
|||
|
||||
private event Action _onDirty;
|
||||
|
||||
private object _preActionLock = new object();
|
||||
private RegionSignal _preAction; // Action to perform before a read or write. This will block the memory access.
|
||||
private readonly List<VirtualRegion> _regions;
|
||||
private readonly MemoryTracking _tracking;
|
||||
|
@ -115,17 +116,16 @@ namespace Ryujinx.Memory.Tracking
|
|||
/// <param name="write">Whether the region was written to or read</param>
|
||||
internal void Signal(ulong address, ulong size, bool write, ref IList<RegionHandle> handleIterable)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Interlocked.Exchange(ref _preAction, null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (action != null)
|
||||
if (_preAction != null)
|
||||
{
|
||||
// Copy the handles list in case it changes when we're out of the lock.
|
||||
if (handleIterable is List<RegionHandle>)
|
||||
|
@ -138,7 +138,12 @@ namespace Ryujinx.Memory.Tracking
|
|||
|
||||
try
|
||||
{
|
||||
action.Invoke(address, size);
|
||||
lock (_preActionLock)
|
||||
{
|
||||
_preAction?.Invoke(address, size);
|
||||
|
||||
_preAction = null;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -220,14 +225,19 @@ namespace Ryujinx.Memory.Tracking
|
|||
{
|
||||
ClearVolatile();
|
||||
|
||||
RegionSignal lastAction = Interlocked.Exchange(ref _preAction, action);
|
||||
if (lastAction == null && action != lastAction)
|
||||
lock (_preActionLock)
|
||||
{
|
||||
lock (_tracking.TrackingLock)
|
||||
RegionSignal lastAction = _preAction;
|
||||
_preAction = action;
|
||||
|
||||
if (lastAction == null && action != lastAction)
|
||||
{
|
||||
foreach (VirtualRegion region in _regions)
|
||||
lock (_tracking.TrackingLock)
|
||||
{
|
||||
region.UpdateProtection();
|
||||
foreach (VirtualRegion region in _regions)
|
||||
{
|
||||
region.UpdateProtection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue