Example #1
0
        /// <summary>
        /// Signal that a memory action occurred within this handle's virtual regions.
        /// </summary>
        /// <param name="write">Whether the region was written to or read</param>
        internal void Signal(ulong address, ulong size, bool write)
        {
            RegionSignal action = Interlocked.Exchange(ref _preAction, null);

            action?.Invoke(address, size);

            if (write)
            {
                Dirty = true;
                Parent?.SignalWrite();
            }
        }
Example #2
0
        /// <summary>
        /// Signal that a memory action occurred within this handle's virtual regions.
        /// </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>
        internal void Signal(ulong address, ulong size, bool write, ref IList <RegionHandle> handleIterable)
        {
            // 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 (_preAction != null)
            {
                // Copy the handles list in case it changes when we're out of the lock.
                if (handleIterable is List <RegionHandle> )
                {
                    handleIterable = handleIterable.ToArray();
                }

                // Temporarily release the tracking lock while we're running the action.
                Monitor.Exit(_tracking.TrackingLock);

                try
                {
                    lock (_preActionLock)
                    {
                        _preAction?.Invoke(address, size);

                        // The action is removed after it returns, to ensure that the null check above succeeds when
                        // it's still in progress rather than continuing and possibly missing a required data flush.
                        Interlocked.Exchange(ref _preAction, null);
                    }
                }
                finally
                {
                    Monitor.Enter(_tracking.TrackingLock);
                }
            }

            if (write)
            {
                bool oldDirty = Dirty;
                Dirty = true;
                if (!oldDirty)
                {
                    _onDirty?.Invoke();
                }
                Parent?.SignalWrite();
            }
        }