| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_VIRTUALIZATION_BIN_VMM_DEV_MEM_H_ |
| #define SRC_VIRTUALIZATION_BIN_VMM_DEV_MEM_H_ |
| |
| #include <zircon/types.h> |
| |
| #include <set> |
| |
| class DevMem { |
| public: |
| struct Range { |
| zx_gpaddr_t addr; |
| size_t size; |
| |
| bool operator<(const Range& r) const { return addr + size <= r.addr; } |
| |
| bool contains(const Range& r) const { return !(r < *this) && !(*this < r); } |
| }; |
| using RangeSet = std::set<Range>; |
| |
| bool AddRange(zx_gpaddr_t addr, size_t size) { |
| if (size == 0) { |
| return false; |
| } |
| return ranges_.emplace(Range{addr, size}).second; |
| } |
| |
| const RangeSet::const_iterator begin() const { return ranges_.begin(); } |
| const RangeSet::const_iterator end() const { return ranges_.end(); } |
| |
| // Generates, by calling the provided functor, all Range's that are in the |
| // provided range, that do not overlap with any internal ranges. This means |
| // the generated set is precisely the inverse of our contained ranges, unioned |
| // with the provided range. |
| template <typename F> |
| void YieldInverseRange(zx_gpaddr_t base, size_t size, F yield) const { |
| zx_gpaddr_t prev = base; |
| for (const auto& range : ranges_) { |
| zx_gpaddr_t next_top = std::min(range.addr, base + size); |
| if (next_top > prev) { |
| yield(prev, next_top - prev); |
| } |
| prev = range.addr + range.size; |
| } |
| zx_gpaddr_t next_top = std::max(prev, base + size); |
| if (next_top > prev) { |
| yield(prev, next_top - prev); |
| } |
| } |
| |
| private: |
| RangeSet ranges_; |
| }; |
| |
| #endif // SRC_VIRTUALIZATION_BIN_VMM_DEV_MEM_H_ |