Пример #1
0
            public INonOverlappingRange Split(ulong splitAddress)
            {
                SharedMemoryMapping newRegion = new SharedMemoryMapping(splitAddress, EndAddress - splitAddress);

                int end   = (int)((EndAddress + MappingMask) >> MappingBits);
                int start = (int)(Address >> MappingBits);

                Size       = splitAddress - Address;
                EndAddress = splitAddress;

                int splitEndBlock   = (int)((splitAddress + MappingMask) >> MappingBits);
                int splitStartBlock = (int)(splitAddress >> MappingBits);

                newRegion.AddBlocks(Blocks.Skip(splitStartBlock - start));
                Blocks.RemoveRange(splitEndBlock - start, end - splitEndBlock);

                return(newRegion);
            }
Пример #2
0
        private void Commit(ulong address, ulong size)
        {
            (ulong granularStart, ulong granularEnd) = GetAlignedRange(address, size);

            ulong endAddress = address + size;

            lock (_lock)
            {
                // Search a bit before and after the new mapping.
                // When adding our new mapping, we may need to join an existing mapping into our new mapping (or in some cases, to the other side!)
                ulong searchStart  = granularStart == 0 ? 0 : (granularStart - 1);
                int   mappingCount = _mappings.FindOverlapsNonOverlapping(searchStart, (granularEnd - searchStart) + 1, ref _foundMappings);

                int first = -1;
                int last  = -1;
                SharedMemoryMapping startOverlap = null;
                SharedMemoryMapping endOverlap   = null;

                int lastIndex  = (int)(address >> MappingBits);
                int endIndex   = (int)((endAddress + MappingMask) >> MappingBits);
                int firstBlock = -1;
                int endBlock   = -1;

                for (int i = 0; i < mappingCount; i++)
                {
                    SharedMemoryMapping mapping = _foundMappings[i];

                    if (mapping.Address < address)
                    {
                        if (mapping.EndAddress >= address)
                        {
                            startOverlap = mapping;
                        }

                        if ((int)((mapping.EndAddress - 1) >> MappingBits) == lastIndex)
                        {
                            lastIndex  = (int)((mapping.EndAddress + MappingMask) >> MappingBits);
                            firstBlock = mapping.Blocks.Last();
                        }
                    }

                    if (mapping.EndAddress > endAddress)
                    {
                        if (mapping.Address <= endAddress)
                        {
                            endOverlap = mapping;
                        }

                        if ((int)((mapping.Address) >> MappingBits) + 1 == endIndex)
                        {
                            endIndex = (int)((mapping.Address) >> MappingBits);
                            endBlock = mapping.Blocks.First();
                        }
                    }

                    if (mapping.OverlapsWith(address, size))
                    {
                        if (first == -1)
                        {
                            first = i;
                        }

                        last = i;
                    }
                }

                if (startOverlap == endOverlap && startOverlap != null)
                {
                    // Already fully committed.
                    return;
                }

                var blocks    = new List <int>();
                int lastBlock = -1;

                if (firstBlock != -1)
                {
                    blocks.Add(firstBlock);
                    lastBlock = firstBlock;
                }

                bool   hasMapped = false;
                Action map       = () =>
                {
                    if (!hasMapped)
                    {
                        _placeholders.EnsurePlaceholders(address >> MappingBits, (granularEnd - granularStart) >> MappingBits, SplitPlaceholder);
                        hasMapped = true;
                    }

                    // There's a gap between this index and the last. Allocate blocks to fill it.
                    blocks.Add(MapBackingBlock(MappingGranularity * (ulong)lastIndex++));
                };

                if (first != -1)
                {
                    for (int i = first; i <= last; i++)
                    {
                        SharedMemoryMapping mapping = _foundMappings[i];
                        int mapIndex = (int)(mapping.Address >> MappingBits);

                        while (lastIndex < mapIndex)
                        {
                            map();
                        }

                        if (lastBlock == mapping.Blocks[0])
                        {
                            blocks.AddRange(mapping.Blocks.Skip(1));
                        }
                        else
                        {
                            blocks.AddRange(mapping.Blocks);
                        }

                        lastIndex = (int)((mapping.EndAddress - 1) >> MappingBits) + 1;
                    }
                }

                while (lastIndex < endIndex)
                {
                    map();
                }

                if (endBlock != -1 && endBlock != lastBlock)
                {
                    blocks.Add(endBlock);
                }

                if (startOverlap != null && endOverlap != null)
                {
                    // Both sides should be coalesced. Extend the start overlap to contain the end overlap, and add together their blocks.

                    _mappings.Remove(endOverlap);

                    startOverlap.ExtendTo(endOverlap.EndAddress, _mappings);

                    startOverlap.AddBlocks(blocks);
                    startOverlap.AddBlocks(endOverlap.Blocks);
                }
                else if (startOverlap != null)
                {
                    startOverlap.ExtendTo(endAddress, _mappings);

                    startOverlap.AddBlocks(blocks);
                }
                else
                {
                    var mapping = new SharedMemoryMapping(address, size, blocks);

                    if (endOverlap != null)
                    {
                        mapping.ExtendTo(endOverlap.EndAddress, _mappings);

                        mapping.AddBlocks(endOverlap.Blocks);

                        _mappings.Remove(endOverlap);
                    }

                    _mappings.Add(mapping);
                }
            }
        }