예제 #1
0
        public void QueryModified(ulong address, ulong size, Action <ulong, ulong> modifiedAction)
        {
            int startHandle = (int)((address - Address) / Granularity);
            int lastHandle  = (int)((address + (size - 1) - Address) / Granularity);

            ulong rgStart = _handles[startHandle].Address;
            ulong rgSize  = 0;

            for (int i = startHandle; i <= lastHandle; i++)
            {
                RegionHandle handle = _handles[i];

                if (handle.Dirty)
                {
                    rgSize += handle.Size;
                    handle.Reprotect();
                }
                else
                {
                    // Submit the region scanned so far as dirty
                    if (rgSize != 0)
                    {
                        modifiedAction(rgStart, rgSize);
                        rgSize = 0;
                    }
                    rgStart = handle.EndAddress;
                }
            }

            if (rgSize != 0)
            {
                modifiedAction(rgStart, rgSize);
            }
        }
예제 #2
0
        private void SplitHandle(int handleIndex, int splitIndex)
        {
            RegionHandle handle  = _handles[handleIndex];
            ulong        address = _address + HandlesToBytes(handleIndex);
            ulong        size    = HandlesToBytes(splitIndex - handleIndex);

            // First, the target handle must be removed. Its data can still be used to determine the new handles.
            RegionSignal signal = handle.PreAction;

            handle.Dispose();

            RegionHandle splitLow = _tracking.BeginTracking(address, size);

            splitLow.Parent = this;
            if (signal != null)
            {
                splitLow.RegisterAction(signal);
            }
            _handles[handleIndex] = splitLow;

            RegionHandle splitHigh = _tracking.BeginTracking(address + size, handle.Size - size);

            splitHigh.Parent = this;
            if (signal != null)
            {
                splitHigh.RegisterAction(signal);
            }
            _handles[splitIndex] = splitHigh;
        }
예제 #3
0
        /// <summary>
        /// Removes a handle from this virtual region. If there are no handles left, this virtual region is removed.
        /// </summary>
        /// <param name="handle">Handle to remove</param>
        public void RemoveHandle(RegionHandle handle)
        {
            bool removedRegions = false;

            lock (_tracking.TrackingLock)
            {
                Handles.Remove(handle);
                UpdateProtection();
                if (Handles.Count == 0)
                {
                    _tracking.RemoveVirtual(this);
                    foreach (var child in _physicalChildren)
                    {
                        removedRegions |= child.RemoveParent(this);
                    }
                }
            }

            if (removedRegions)
            {
                // The first lock will unprotect any regions that have been removed. This second lock will remove them.
                lock (_tracking.TrackingLock)
                {
                    foreach (var child in _physicalChildren)
                    {
                        child.TryDelete();
                    }
                }
            }
        }
예제 #4
0
        public void QueryModified(ulong address, ulong size, Action <ulong, ulong> modifiedAction, int sequenceNumber)
        {
            int startHandle = (int)((address - _address) / _granularity);
            int lastHandle  = (int)((address + (size - 1) - _address) / _granularity);

            ulong rgStart = _address + (ulong)startHandle * _granularity;
            ulong rgSize  = 0;

            ulong endAddress = _address + ((ulong)lastHandle + 1) * _granularity;

            int i = startHandle;

            while (i <= lastHandle)
            {
                RegionHandle handle = _handles[i];
                if (handle == null)
                {
                    // Missing handle. A new handle must be created.
                    CreateHandle(i, lastHandle);
                    handle = _handles[i];
                }

                if (handle.EndAddress > endAddress)
                {
                    // End address of handle is beyond the end of the search. Force a split.
                    SplitHandle(i, lastHandle + 1);
                    handle = _handles[i];
                }

                if (handle.Dirty && sequenceNumber != handle.SequenceNumber)
                {
                    rgSize += handle.Size;
                    handle.Reprotect();
                }
                else
                {
                    // Submit the region scanned so far as dirty
                    if (rgSize != 0)
                    {
                        modifiedAction(rgStart, rgSize);
                        rgSize = 0;
                    }
                    rgStart = handle.EndAddress;
                }

                handle.SequenceNumber = sequenceNumber;

                i += (int)(handle.Size / _granularity);
            }

            if (rgSize != 0)
            {
                modifiedAction(rgStart, rgSize);
            }
        }
예제 #5
0
        /// <summary>
        /// Obtains a memory tracking handle for the given virtual region. This should be disposed when finished with.
        /// </summary>
        /// <param name="address">CPU virtual address of the region</param>
        /// <param name="size">Size of the region</param>
        /// <returns>The memory tracking handle</returns>
        public RegionHandle BeginTracking(ulong address, ulong size)
        {
            (address, size) = PageAlign(address, size);

            lock (TrackingLock)
            {
                RegionHandle handle = new RegionHandle(this, address, size, _memoryManager.IsRangeMapped(address, size));

                return(handle);
            }
        }
예제 #6
0
 /// <summary>
 /// Removes a handle from this virtual region. If there are no handles left, this virtual region is removed.
 /// </summary>
 /// <param name="handle">Handle to remove</param>
 public void RemoveHandle(RegionHandle handle)
 {
     lock (_tracking.TrackingLock)
     {
         Handles.Remove(handle);
         UpdateProtection();
         if (Handles.Count == 0)
         {
             _tracking.RemoveVirtual(this);
         }
     }
 }
예제 #7
0
        internal MultiRegionHandle(MemoryTracking tracking, ulong address, ulong size, ulong granularity)
        {
            _handles    = new RegionHandle[size / granularity];
            Granularity = granularity;

            for (int i = 0; i < _handles.Length; i++)
            {
                RegionHandle handle = tracking.BeginTracking(address + (ulong)i * granularity, granularity);
                handle.Parent = this;
                _handles[i]   = handle;
            }

            Address = address;
            Size    = size;
        }
예제 #8
0
        private void CreateHandle(int startHandle, int lastHandle)
        {
            ulong startAddress = _address + HandlesToBytes(startHandle);

            // Scan for the first handle before us. If it's overlapping us, it must be split.
            for (int i = startHandle - 1; i >= 0; i--)
            {
                RegionHandle handle = _handles[i];
                if (handle != null)
                {
                    if (handle.EndAddress > startAddress)
                    {
                        SplitHandle(i, startHandle);
                        return; // The remainer of this handle should be filled in later on.
                    }
                    break;
                }
            }

            // Scan for handles after us. We should create a handle that goes up to this handle's start point, if present.
            for (int i = startHandle + 1; i <= lastHandle; i++)
            {
                RegionHandle handle = _handles[i];
                if (handle != null)
                {
                    // Fill up to the found handle.
                    handle                = _tracking.BeginTracking(startAddress, HandlesToBytes(i - startHandle));
                    handle.Parent         = this;
                    _handles[startHandle] = handle;
                    return;
                }
            }

            // Can fill the whole range.
            _handles[startHandle]        = _tracking.BeginTracking(startAddress, HandlesToBytes(1 + lastHandle - startHandle));
            _handles[startHandle].Parent = this;
        }
예제 #9
0
        internal MultiRegionHandle(MemoryTracking tracking, ulong address, ulong size, IEnumerable <IRegionHandle> handles, ulong granularity)
        {
            _handles    = new RegionHandle[size / granularity];
            Granularity = granularity;

            int i = 0;

            if (handles != null)
            {
                // Inherit from the handles we were given. Any gaps must be filled with new handles,
                // and old handles larger than our granularity must copy their state onto new granular handles and dispose.
                // It is assumed that the provided handles do not overlap, in order, are on page boundaries,
                // and don't extend past the requested range.

                foreach (RegionHandle handle in handles)
                {
                    int startIndex = (int)((handle.Address - address) / granularity);

                    // Fill any gap left before this handle.
                    while (i < startIndex)
                    {
                        RegionHandle fillHandle = tracking.BeginTracking(address + (ulong)i * granularity, granularity);
                        fillHandle.Parent = this;
                        _handles[i++]     = fillHandle;
                    }

                    if (handle.Size == granularity)
                    {
                        handle.Parent = this;
                        _handles[i++] = handle;
                    }
                    else
                    {
                        int endIndex = (int)((handle.EndAddress - address) / granularity);

                        while (i < endIndex)
                        {
                            RegionHandle splitHandle = tracking.BeginTracking(address + (ulong)i * granularity, granularity);
                            splitHandle.Parent = this;

                            splitHandle.Reprotect(handle.Dirty);

                            RegionSignal signal = handle.PreAction;
                            if (signal != null)
                            {
                                splitHandle.RegisterAction(signal);
                            }

                            _handles[i++] = splitHandle;
                        }

                        handle.Dispose();
                    }
                }
            }

            // Fill any remaining space with new handles.
            while (i < _handles.Length)
            {
                RegionHandle handle = tracking.BeginTracking(address + (ulong)i * granularity, granularity);
                handle.Parent = this;
                _handles[i++] = handle;
            }

            Address = address;
            Size    = size;
        }