VM_MAP_ENTRY_RESIZE_FREE(9freebsd)
π VM_MAP_ENTRY_RESIZE_FREE π
okay bestie, sit down, we're reading a Kernel Developer's Manual page for FreeBSD 9 and honestly? it's giving brainy. this is the vm_map_entry_resize_free situation, section 9, and it's all about the vm map free space algorithm. no cap. π§β¨
πΈ NAME πΈ
vm_map_entry_resize_free β vm map free space algorithm
β¨ SYNOPSIS β¨
like, include these first or nothing works, periodt:
#include <sys/param.h>
#include <vm/vm.h>
#include <vm/vm_map.h>
void
vm_map_entry_resize_free(vm_map_t map, vm_map_entry_t entry);
π¦ DESCRIPTION π¦
so this page is doing three things: it explains the vm_map_entry fields that the VM map free space algorithm uses, how to keep those variables consistent (because inconsistency is not the vibe), and the vm_map_entry_resize_free() function itself. π
VM map entries are organized two ways at once β as a doubly-linked list (the prev and next pointers) and as a binary search tree (the left and right pointers). the search tree is organized as a Sleator and Tarjan splay tree, aka a "self-adjusting tree". main character tree energy fr.
struct vm_map_entry {
struct vm_map_entry *prev;
struct vm_map_entry *next;
struct vm_map_entry *left;
struct vm_map_entry *right;
vm_offset_t start;
vm_offset_t end;
vm_offset_t avail_ssize;
vm_size_t adj_free;
vm_size_t max_free;
...
};
the free space algorithm adds two fields to struct vm_map_entry: adj_free and max_free.
adj_freeis the amount of free address space adjacent to and immediately following (higher address) the map entry. it's unused in the map header. note thatadj_freedepends on the linked list, not the splay tree, and it can be computed as:
entry->adj_free = (entry->next == &map->header ?
map->max_offset : entry->next->start) - entry->end;
max_freeis the maximum amount of contiguous free space in the entry's subtree. note thatmax_freedepends on the splay tree, not the linked list, and it's computed by taking the maximum of its ownadj_freeand themax_freeof its left and right subtrees. again,max_freeis unused in the map header.
these fields are what make an O(log n) implementation of vm_map_findspace() possible. using max_free, we can immediately test for a sufficiently large free region in an entire subtree. that means we can find a first-fit free region of a given size in one pass down the tree, so O(log n) amortized using splay trees. slay. π₯
when a free region changes size, we gotta update adj_free and max_free in the preceding map entry and propagate max_free up the tree. this is handled in vm_map_entry_link() and vm_map_entry_unlink() for the cases of inserting and deleting an entry. heads up:
vm_map_entry_link()updates both the new entry and the previous entry.vm_map_entry_unlink()updates the previous entry.
also note that max_free is not actually propagated up the tree. instead, that entry is first splayed to the root and then the change is made there. this is a common technique in splay trees, and it's also how map entries are linked and unlinked into the tree. iykyk. π
the vm_map_entry_resize_free() function updates the free space variables in the given entry and propagates those values up the tree. call this function whenever a map entry is resized in-place β that is, by modifying its start or end values.
β οΈ okay this part matters: if you changeend, then you should resize that entry. but if you changestart, then you should resize the previous entry. π«Ά
the map must be locked before calling this function. and again, propagating max_free is performed by splaying that entry to the root.
π EXAMPLES π
adding an entry
consider adding a map entry with vm_map_insert():
ret = vm_map_insert(map, object, offset, start, end, prot,
max_prot, cow);
in this case, no further action is required to maintain consistency of the free space variables. vm_map_insert() calls vm_map_entry_link() which updates both the new entry and the previous entry. same deal would be true for vm_map_delete() and for calling vm_map_entry_link() or vm_map_entry_unlink() directly. β¨
resizing start
now consider resizing an entry in-place without a call to vm_map_entry_link() or vm_map_entry_unlink():
entry->start = new_start;
if (entry->prev != &map->header)
vm_map_entry_resize_free(map, entry->prev);
in this case, resetting start changes the amount of free space following the previous entry, so we use vm_map_entry_resize_free() to update the previous entry. π
resizing end
finally, suppose we change an entry's end address:
entry->end = new_end;
vm_map_entry_resize_free(map, entry);
here, we call vm_map_entry_resize_free() on the entry itself.
π SEE ALSO π
Daniel D. Sleator and Robert E. Tarjan, "Self-Adjusting Binary Search Trees", JACM, vol. 32(3), pp. 652-686, July 1985.
π HISTORY π
Splay trees were added to the VM map in FreeBSD 5.0, and the O(log n) tree-based free space algorithm was added in FreeBSD 5.3. glow up era fr. πΈ
π«Ά AUTHORS π«Ά
the tree-based free space algorithm and this manual page were written by Mark W. Krentel <krentel@dreamscape.com>. king behavior. π
and that's the whole page bestie, you ate that π
this was the Debian build from August 17, 2004, VM_MAP_ENTRY_RESIZE_FREE(9) β go lock your map and resize responsibly πβ¨
π¦ where this page comes from
- debian bookworm: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- debian trixie: freebsd-manpages 12.2-2 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu jammy: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu noble: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu questing: freebsd-manpages 12.2-2
- ubuntu resolute: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu stonking: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- Copyright (c) 2004 Mark W. Krentel <krentel@dreamscape.com>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms