|
@@ -37,6 +37,7 @@ namespace Ryujinx.Memory.Tracking
|
|
|
|
|
|
|
|
private object _preActionLock = new object();
|
|
private object _preActionLock = new object();
|
|
|
private RegionSignal _preAction; // Action to perform before a read or write. This will block the memory access.
|
|
private RegionSignal _preAction; // Action to perform before a read or write. This will block the memory access.
|
|
|
|
|
+ private PreciseRegionSignal _preciseAction; // Action to perform on a precise read or write.
|
|
|
private readonly List<VirtualRegion> _regions;
|
|
private readonly List<VirtualRegion> _regions;
|
|
|
private readonly MemoryTracking _tracking;
|
|
private readonly MemoryTracking _tracking;
|
|
|
private bool _disposed;
|
|
private bool _disposed;
|
|
@@ -113,7 +114,10 @@ namespace Ryujinx.Memory.Tracking
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Signal that a memory action occurred within this handle's virtual regions.
|
|
/// Signal that a memory action occurred within this handle's virtual regions.
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
|
|
+ /// <param name="address">Address accessed</param>
|
|
|
|
|
+ /// <param name="size">Size of the region affected in bytes</param>
|
|
|
/// <param name="write">Whether the region was written to or read</param>
|
|
/// <param name="write">Whether the region was written to or read</param>
|
|
|
|
|
+ /// <param name="handleIterable">Reference to the handles being iterated, in case the list needs to be copied</param>
|
|
|
internal void Signal(ulong address, ulong size, bool write, ref IList<RegionHandle> handleIterable)
|
|
internal void Signal(ulong address, ulong size, bool write, ref IList<RegionHandle> handleIterable)
|
|
|
{
|
|
{
|
|
|
// If this handle was already unmapped (even if just partially),
|
|
// If this handle was already unmapped (even if just partially),
|
|
@@ -163,6 +167,27 @@ namespace Ryujinx.Memory.Tracking
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Signal that a precise memory action occurred within this handle's virtual regions.
|
|
|
|
|
+ /// If there is no precise action, or the action returns false, the normal signal handler will be called.
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ /// <param name="address">Address accessed</param>
|
|
|
|
|
+ /// <param name="size">Size of the region affected in bytes</param>
|
|
|
|
|
+ /// <param name="write">Whether the region was written to or read</param>
|
|
|
|
|
+ /// <param name="handleIterable">Reference to the handles being iterated, in case the list needs to be copied</param>
|
|
|
|
|
+ /// <returns>True if a precise action was performed and returned true, false otherwise</returns>
|
|
|
|
|
+ internal bool SignalPrecise(ulong address, ulong size, bool write, ref IList<RegionHandle> handleIterable)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!Unmapped && _preciseAction != null && _preciseAction(address, size, write))
|
|
|
|
|
+ {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Signal(address, size, write, ref handleIterable);
|
|
|
|
|
+
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Force this handle to be dirty, without reprotecting.
|
|
/// Force this handle to be dirty, without reprotecting.
|
|
|
/// </summary>
|
|
/// </summary>
|
|
@@ -243,6 +268,16 @@ namespace Ryujinx.Memory.Tracking
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Register an action to perform when a precise access occurs (one with exact address and size).
|
|
|
|
|
+ /// If the action returns true, read/write tracking are skipped.
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ /// <param name="action">Action to call on read or write</param>
|
|
|
|
|
+ public void RegisterPreciseAction(PreciseRegionSignal action)
|
|
|
|
|
+ {
|
|
|
|
|
+ _preciseAction = action;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Register an action to perform when the region is written to.
|
|
/// Register an action to perform when the region is written to.
|
|
|
/// This action will not be removed when it is called - it is called each time the dirty flag is set.
|
|
/// This action will not be removed when it is called - it is called each time the dirty flag is set.
|