1.\" 2.\" Copyright (c) 2004 Mark W. Krentel <krentel@dreamscape.com> 3.\" All rights reserved. 4.\" 5.\" Redistribution and use in source and binary forms, with or without 6.\" modification, are permitted provided that the following conditions 7.\" are met: 8.\" 1. Redistributions of source code must retain the above copyright 9.\" notice, this list of conditions and the following disclaimer. 10.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" notice, this list of conditions and the following disclaimer in the 12.\" documentation and/or other materials provided with the distribution. 13.\" 14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24.\" SUCH DAMAGE. 25.\" 26.Dd August 17, 2004 27.Dt VM_MAP_ENTRY_RESIZE_FREE 9 28.Os 29.Sh NAME 30.Nm vm_map_entry_resize_free 31.Nd "vm map free space algorithm" 32.Sh SYNOPSIS 33.In sys/param.h 34.In vm/vm.h 35.In vm/vm_map.h 36.Ft void 37.Fn vm_map_entry_resize_free "vm_map_t map" "vm_map_entry_t entry" 38.Sh DESCRIPTION 39This manual page describes the 40.Vt vm_map_entry 41fields used in the VM map free space algorithm, how to maintain 42consistency of these variables, and the 43.Fn vm_map_entry_resize_free 44function. 45.Pp 46VM map entries are organized as both a doubly-linked list 47.Va ( prev 48and 49.Va next 50pointers) and as a binary search tree 51.Va ( left 52and 53.Va right 54pointers). 55The search tree is organized as a Sleator and Tarjan splay tree, 56also known as a 57.Dq "self-adjusting tree" . 58.Bd -literal -offset indent 59struct vm_map_entry { 60 struct vm_map_entry *prev; 61 struct vm_map_entry *next; 62 struct vm_map_entry *left; 63 struct vm_map_entry *right; 64 vm_offset_t start; 65 vm_offset_t end; 66 vm_offset_t avail_ssize; 67 vm_size_t adj_free; 68 vm_size_t max_free; 69 ... 70}; 71.Ed 72.Pp 73The free space algorithm adds two fields to 74.Vt "struct vm_map_entry" : 75.Va adj_free 76and 77.Va max_free . 78The 79.Va adj_free 80field 81is the amount of free address space adjacent to and immediately 82following (higher address) the map entry. 83This field is unused in the map header. 84Note that 85.Va adj_free 86depends on the linked list, not the splay tree and that 87.Va adj_free 88can be computed as: 89.Bd -literal -offset indent 90entry->adj_free = (entry->next == &map->header ? 91 map->max_offset : entry->next->start) - entry->end; 92.Ed 93.Pp 94The 95.Va max_free 96field 97is the maximum amount of contiguous free space in the entry's subtree. 98Note that 99.Va max_free 100depends on the splay tree, not the linked list and that 101.Va max_free 102is computed by taking the maximum of its own 103.Va adj_free 104and the 105.Va max_free 106of its left and right subtrees. 107Again, 108.Va max_free 109is unused in the map header. 110.Pp 111These fields allow for an 112.Fn O "log n" 113implementation of 114.Fn vm_map_findspace . 115Using 116.Va max_free , 117we can immediately test for a sufficiently large free region 118in an entire subtree. 119This makes it possible to find a first-fit free region of a given size 120in one pass down the tree, so 121.Fn O "log n" 122amortized using splay trees. 123.Pp 124When a free region changes size, we must update 125.Va adj_free 126and 127.Va max_free 128in the preceding map entry and propagate 129.Va max_free 130up the tree. 131This is handled in 132.Fn vm_map_entry_link 133and 134.Fn vm_map_entry_unlink 135for the cases of inserting and deleting an entry. 136Note that 137.Fn vm_map_entry_link 138updates both the new entry and the previous entry, and that 139.Fn vm_map_entry_unlink 140updates the previous entry. 141Also note that 142.Va max_free 143is not actually propagated up the tree. 144Instead, that entry is first splayed to the root and 145then the change is made there. 146This is a common technique in splay trees and is also 147how map entries are linked and unlinked into the tree. 148.Pp 149The 150.Fn vm_map_entry_resize_free 151function updates the free space variables in the given 152.Fa entry 153and propagates those values up the tree. 154This function should be called whenever a map entry is resized 155in-place, that is, by modifying its 156.Va start 157or 158.Va end 159values. 160Note that if you change 161.Va end , 162then you should resize that entry, but if you change 163.Va start , 164then you should resize the previous entry. 165The map must be locked before calling this function, 166and again, propagating 167.Va max_free 168is performed by splaying that entry to the root. 169.Sh EXAMPLES 170Consider adding a map entry with 171.Fn vm_map_insert . 172.Bd -literal -offset indent 173ret = vm_map_insert(map, object, offset, start, end, prot, 174 max_prot, cow); 175.Ed 176.Pp 177In this case, no further action is required to maintain 178consistency of the free space variables. 179The 180.Fn vm_map_insert 181function calls 182.Fn vm_map_entry_link 183which updates both the new entry and the previous entry. 184The same would be true for 185.Fn vm_map_delete 186and for calling 187.Fn vm_map_entry_link 188or 189.Fn vm_map_entry_unlink 190directly. 191.Pp 192Now consider resizing an entry in-place without a call to 193.Fn vm_map_entry_link 194or 195.Fn vm_map_entry_unlink . 196.Bd -literal -offset indent 197entry->start = new_start; 198if (entry->prev != &map->header) 199 vm_map_entry_resize_free(map, entry->prev); 200.Ed 201.Pp 202In this case, resetting 203.Va start 204changes the amount of free space following the previous entry, 205so we use 206.Fn vm_map_entry_resize_free 207to update the previous entry. 208.Pp 209Finally, suppose we change an entry's 210.Va end 211address. 212.Bd -literal -offset indent 213entry->end = new_end; 214vm_map_entry_resize_free(map, entry); 215.Ed 216.Pp 217Here, we call 218.Fn vm_map_entry_resize_free 219on the entry itself. 220.Sh SEE ALSO 221.Xr vm_map 9 , 222.Xr vm_map_findspace 9 223.Rs 224.%A Daniel D. Sleator 225.%A Robert E. Tarjan 226.%T Self-Adjusting Binary Search Trees 227.%J JACM 228.%V vol. 32(3) 229.%P pp. 652-686 230.%D July 1985 231.Re 232.Sh HISTORY 233Splay trees were added to the VM map in 234.Fx 5.0 , 235and the 236.Fn O "log n" 237tree-based free space algorithm was added in 238.Fx 5.3 . 239.Sh AUTHORS 240The tree-based free space algorithm and this manual page were written by 241.An Mark W. Krentel Aq Mt krentel@dreamscape.com . 242