blob: af501dc9c94de30fa145c3e34dfa403393f5d582 [file] [edit]
// Copyright 2025 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#ifndef ZIRCON_KERNEL_VM_INCLUDE_VM_VM_MAPPING_OBSERVER_H_
#define ZIRCON_KERNEL_VM_INCLUDE_VM_VM_MAPPING_OBSERVER_H_
#include <assert.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <stddef.h>
#include <sys/types.h>
#include <fbl/intrusive_wavl_tree.h>
#include <ktl/algorithm.h>
#include <ktl/declval.h>
#include <ktl/type_traits.h>
#include <lockdep/guard.h>
//
// # VmMapping Augmented Binary Search Tree Support
//
// The following types provide the state and tree maintenance hooks to implement an augmented binary
// search tree for VmMappings. The augmentation maintains information about the largest mapping end
// address in the subregion, allowing for efficiently finding all mappings that overlap with a given
// range.
//
// ## General Approach
//
// VmObject maintains an ordered set of possibly overlapping mappings sorted by base offset, with
// the object heap address used as a secondary sorting key for mappings that share the base offset.
// The mappings, characterized by base offset and size, are instances of a VmMapping. Many different
// mappings might reference the same offset.
//
// The set of mappings is stored in a BTree and the approach described here takes advantage of the
// augmented tree subtree information that can be stored as part of the tree nodes to improve the
// time complexity of finding the set of mappings that might contain a range of offsets.
//
// ### Base Representation
//
// The following diagram is a linear representation of the offsets covering addresses 0 to 20
// with six mappings (small numbers are used for simplicity) across two lines due to overlap. The
// boxes represent mappings labeled <first offset>,<last offset>.
//
// +-------+ +---------------------------+ +-----------------------+
// | [0,1] | | [4,10] | | [15,20] |
// +-------+ +---------------------------+ +-----------------------+
// +-----------+---------------+--------------------------------+
// | [3,5] | [6,8] | [9,17] |
// +-----------+---------------+--------------------------------+
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
//
// The following diagram illustrates the same mappings in a btree representation, sorted by
// <first offset>. The actual structure would vary depending on insertion order of leaf node size.
//
// +-----------+
// | [ ] 9 [ ] |
// +--^-----^--+
// | |
// +------------------------+ +---------------------+
// | |
// +-------+-------+----------+-----+ +--------+---------+
// | [0,1] | [3,5] | [4,10] | [6,8] | | [9,17] | [15,20] |
// +-------+-------+----------+-----+ +--------+---------+
//
// This structure supports efficient searches for mappings that begin at a particular offset in
// O(log n) time. However, finding all mappings that cover a particular offset requires, in the
// worst case, a full tree walk, since no information about the size of the mappings is encoded in
// the tree. Therefore as long as the base offset is below the search offset, any mapping somewhere
// in the subtree could extend into the search offset.
//
// ### Augmented Representation
//
// The augmented representation builds on the base by storing and maintaining the small and largest
// offset of subtree of each node. This allows for skipping subtrees that cannot have a mapping that
// might contain the search offset.
//
// The following diagram illustrates the augmented BTree representation for the same allocated
// regions as the previous illustration.
//
// +-----------------+
// | min: 0, max: 20 |
// | [ ] 9 [ ] |
// +--^-----^--------+
// | |
// +---------------------+ +---------------------+
// | |
// +-------+-------+----------+-----+ +--------+---------+
// | min: 0, max: 11 (exclusive) | | min: 9, max: 21 |
// | [0,1] | [3,5] | [4,10] | [6,8] | | [9,17] | [15,20] |
// +-------+-------+----------+-----+ +--------+---------+
//
// The new row in each node is the minimum start offset and the exclusive end offset (inclusive) for
// that nodes subtree.
struct VmMappingObserver {
struct State {
// Inclusive smallest object offset.
uint64_t min_offset;
// Exclusive largest object offset.
uint64_t max_offset;
bool operator==(const State& other) const {
return min_offset == other.min_offset && max_offset == other.max_offset;
}
bool operator!=(const State& other) const { return !(*this == other); }
};
using AugmentedState = State;
// Implementation of BTree Observer::Calculate. Find the min_offset and max_offset for the
// provided iterator range.
template <typename iterator>
static State Calculate(iterator node_start, iterator node_end) {
uint64_t min_offset = (*node_start).second->object_offset();
uint64_t max_last = (*node_end).second->object_offset() + (*node_end).second->size();
for (; node_start != node_end; node_start++) {
max_last =
ktl::max(max_last, (*node_start).second->object_offset() + (*node_start).second->size());
}
return State{.min_offset = min_offset, .max_offset = max_last};
}
// Implementation of BTree Observer::Fold. Determines the min_offset and max_offset of two
// adjacent subtrees based on their provided State.
static State Fold(State left, State right) {
DEBUG_ASSERT(left.min_offset <= right.min_offset);
return State{.min_offset = left.min_offset,
.max_offset = ktl::max(left.max_offset, right.max_offset)};
}
};
#endif // ZIRCON_KERNEL_VM_INCLUDE_VM_VM_MAPPING_OBSERVER_H_