1fe267a55SPedro F. Giffuni /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3fe267a55SPedro F. Giffuni * 4774d251dSAttilio Rao * Copyright (c) 2013 EMC Corp. 5774d251dSAttilio Rao * Copyright (c) 2011 Jeffrey Roberson <jeff@freebsd.org> 6774d251dSAttilio Rao * Copyright (c) 2008 Mayur Shardul <mayur.shardul@gmail.com> 7774d251dSAttilio Rao * All rights reserved. 8774d251dSAttilio Rao * 9774d251dSAttilio Rao * Redistribution and use in source and binary forms, with or without 10774d251dSAttilio Rao * modification, are permitted provided that the following conditions 11774d251dSAttilio Rao * are met: 12774d251dSAttilio Rao * 1. Redistributions of source code must retain the above copyright 13774d251dSAttilio Rao * notice, this list of conditions and the following disclaimer. 14774d251dSAttilio Rao * 2. Redistributions in binary form must reproduce the above copyright 15774d251dSAttilio Rao * notice, this list of conditions and the following disclaimer in the 16774d251dSAttilio Rao * documentation and/or other materials provided with the distribution. 17774d251dSAttilio Rao * 18774d251dSAttilio Rao * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19774d251dSAttilio Rao * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20774d251dSAttilio Rao * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21774d251dSAttilio Rao * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22774d251dSAttilio Rao * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23774d251dSAttilio Rao * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24774d251dSAttilio Rao * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25774d251dSAttilio Rao * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26774d251dSAttilio Rao * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27774d251dSAttilio Rao * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28774d251dSAttilio Rao * SUCH DAMAGE. 29774d251dSAttilio Rao */ 30774d251dSAttilio Rao 31774d251dSAttilio Rao #ifndef _VM_RADIX_H_ 32774d251dSAttilio Rao #define _VM_RADIX_H_ 33774d251dSAttilio Rao 34774d251dSAttilio Rao #include <vm/_vm_radix.h> 35774d251dSAttilio Rao 36774d251dSAttilio Rao #ifdef _KERNEL 37429c871dSDoug Moore #include <sys/pctrie.h> 38429c871dSDoug Moore #include <vm/vm_page.h> 39429c871dSDoug Moore #include <vm/vm.h> 40774d251dSAttilio Rao 418d6fbbb8SJeff Roberson void vm_radix_wait(void); 42cd1241fbSKonstantin Belousov void vm_radix_zinit(void); 43429c871dSDoug Moore void *vm_radix_node_alloc(struct pctrie *ptree); 44429c871dSDoug Moore void vm_radix_node_free(struct pctrie *ptree, void *node); 45429c871dSDoug Moore extern smr_t vm_radix_smr; 462d2bcba7SDoug Moore 47cd1241fbSKonstantin Belousov static __inline void 48cd1241fbSKonstantin Belousov vm_radix_init(struct vm_radix *rtree) 49cd1241fbSKonstantin Belousov { 50429c871dSDoug Moore pctrie_init(&rtree->rt_trie); 51cd1241fbSKonstantin Belousov } 52cd1241fbSKonstantin Belousov 531efa7dbcSDoug Moore static __inline bool 54cd1241fbSKonstantin Belousov vm_radix_is_empty(struct vm_radix *rtree) 55cd1241fbSKonstantin Belousov { 56429c871dSDoug Moore return (pctrie_is_empty(&rtree->rt_trie)); 57429c871dSDoug Moore } 58429c871dSDoug Moore 59450a6690SDoug Moore PCTRIE_DEFINE_SMR(VM_RADIX, vm_page, pindex, vm_radix_node_alloc, 60450a6690SDoug Moore vm_radix_node_free, vm_radix_smr); 61429c871dSDoug Moore 62429c871dSDoug Moore /* 63c71c41daSDoug Moore * Inserts the key-value pair into the trie, starting search from root. 64429c871dSDoug Moore * Panics if the key already exists. 65429c871dSDoug Moore */ 66429c871dSDoug Moore static __inline int 67429c871dSDoug Moore vm_radix_insert(struct vm_radix *rtree, vm_page_t page) 68429c871dSDoug Moore { 69429c871dSDoug Moore return (VM_RADIX_PCTRIE_INSERT(&rtree->rt_trie, page)); 70429c871dSDoug Moore } 71429c871dSDoug Moore 72429c871dSDoug Moore /* 73c71c41daSDoug Moore * Inserts the key-value pair into the trie, starting search from iterator. 74c71c41daSDoug Moore * Panics if the key already exists. 75c71c41daSDoug Moore */ 76c71c41daSDoug Moore static __inline int 77c71c41daSDoug Moore vm_radix_iter_insert(struct pctrie_iter *pages, vm_page_t page) 78c71c41daSDoug Moore { 79c71c41daSDoug Moore return (VM_RADIX_PCTRIE_ITER_INSERT(pages, page)); 80c71c41daSDoug Moore } 81c71c41daSDoug Moore 82c71c41daSDoug Moore /* 837658d153SRyan Libby * Insert the page into the vm_radix tree with its pindex as the key. Panic if 847658d153SRyan Libby * the pindex already exists. Return zero on success or a non-zero error on 857658d153SRyan Libby * memory allocation failure. Set the out parameter mpred to the previous page 867658d153SRyan Libby * in the tree as if found by a previous call to vm_radix_lookup_le with the 877658d153SRyan Libby * new page pindex. 887658d153SRyan Libby */ 897658d153SRyan Libby static __inline int 907658d153SRyan Libby vm_radix_insert_lookup_lt(struct vm_radix *rtree, vm_page_t page, 917658d153SRyan Libby vm_page_t *mpred) 927658d153SRyan Libby { 937658d153SRyan Libby int error; 947658d153SRyan Libby 957658d153SRyan Libby error = VM_RADIX_PCTRIE_INSERT_LOOKUP_LE(&rtree->rt_trie, page, mpred); 967658d153SRyan Libby if (__predict_false(error == EEXIST)) 977658d153SRyan Libby panic("vm_radix_insert_lookup_lt: page already present, %p", 987658d153SRyan Libby *mpred); 997658d153SRyan Libby return (error); 1007658d153SRyan Libby } 1017658d153SRyan Libby 1027658d153SRyan Libby /* 103429c871dSDoug Moore * Returns the value stored at the index assuming there is an external lock. 104429c871dSDoug Moore * 105429c871dSDoug Moore * If the index is not present, NULL is returned. 106429c871dSDoug Moore */ 107429c871dSDoug Moore static __inline vm_page_t 108429c871dSDoug Moore vm_radix_lookup(struct vm_radix *rtree, vm_pindex_t index) 109429c871dSDoug Moore { 110429c871dSDoug Moore return (VM_RADIX_PCTRIE_LOOKUP(&rtree->rt_trie, index)); 111429c871dSDoug Moore } 112429c871dSDoug Moore 113429c871dSDoug Moore /* 114429c871dSDoug Moore * Returns the value stored at the index without requiring an external lock. 115429c871dSDoug Moore * 116429c871dSDoug Moore * If the index is not present, NULL is returned. 117429c871dSDoug Moore */ 118429c871dSDoug Moore static __inline vm_page_t 119429c871dSDoug Moore vm_radix_lookup_unlocked(struct vm_radix *rtree, vm_pindex_t index) 120429c871dSDoug Moore { 121429c871dSDoug Moore return (VM_RADIX_PCTRIE_LOOKUP_UNLOCKED(&rtree->rt_trie, index)); 122429c871dSDoug Moore } 123429c871dSDoug Moore 124429c871dSDoug Moore /* 125450a6690SDoug Moore * Initialize an iterator for vm_radix. 126450a6690SDoug Moore */ 127450a6690SDoug Moore static __inline void 128450a6690SDoug Moore vm_radix_iter_init(struct pctrie_iter *pages, struct vm_radix *rtree) 129450a6690SDoug Moore { 130450a6690SDoug Moore pctrie_iter_init(pages, &rtree->rt_trie); 131450a6690SDoug Moore } 132450a6690SDoug Moore 133450a6690SDoug Moore /* 134450a6690SDoug Moore * Initialize an iterator for vm_radix. 135450a6690SDoug Moore */ 136450a6690SDoug Moore static __inline void 137450a6690SDoug Moore vm_radix_iter_limit_init(struct pctrie_iter *pages, struct vm_radix *rtree, 138450a6690SDoug Moore vm_pindex_t limit) 139450a6690SDoug Moore { 140450a6690SDoug Moore pctrie_iter_limit_init(pages, &rtree->rt_trie, limit); 141450a6690SDoug Moore } 142450a6690SDoug Moore 143450a6690SDoug Moore /* 144450a6690SDoug Moore * Returns the value stored at the index. 145450a6690SDoug Moore * Requires that access be externally synchronized by a lock. 146450a6690SDoug Moore * 147450a6690SDoug Moore * If the index is not present, NULL is returned. 148450a6690SDoug Moore */ 149450a6690SDoug Moore static __inline vm_page_t 150450a6690SDoug Moore vm_radix_iter_lookup(struct pctrie_iter *pages, vm_pindex_t index) 151450a6690SDoug Moore { 152450a6690SDoug Moore return (VM_RADIX_PCTRIE_ITER_LOOKUP(pages, index)); 153450a6690SDoug Moore } 154450a6690SDoug Moore 155450a6690SDoug Moore /* 156450a6690SDoug Moore * Returns the value stored 'stride' steps beyond the current position. 157450a6690SDoug Moore * Requires that access be externally synchronized by a lock. 158450a6690SDoug Moore * 159450a6690SDoug Moore * If the index is not present, NULL is returned. 160450a6690SDoug Moore */ 161450a6690SDoug Moore static __inline vm_page_t 162450a6690SDoug Moore vm_radix_iter_stride(struct pctrie_iter *pages, int stride) 163450a6690SDoug Moore { 164450a6690SDoug Moore return (VM_RADIX_PCTRIE_ITER_STRIDE(pages, stride)); 165450a6690SDoug Moore } 166450a6690SDoug Moore 167450a6690SDoug Moore /* 168429c871dSDoug Moore * Returns the page with the least pindex that is greater than or equal to the 169429c871dSDoug Moore * specified pindex, or NULL if there are no such pages. 170429c871dSDoug Moore * 171429c871dSDoug Moore * Requires that access be externally synchronized by a lock. 172429c871dSDoug Moore */ 173429c871dSDoug Moore static __inline vm_page_t 174429c871dSDoug Moore vm_radix_lookup_ge(struct vm_radix *rtree, vm_pindex_t index) 175429c871dSDoug Moore { 176429c871dSDoug Moore return (VM_RADIX_PCTRIE_LOOKUP_GE(&rtree->rt_trie, index)); 177429c871dSDoug Moore } 178429c871dSDoug Moore 179429c871dSDoug Moore /* 180429c871dSDoug Moore * Returns the page with the greatest pindex that is less than or equal to the 181429c871dSDoug Moore * specified pindex, or NULL if there are no such pages. 182429c871dSDoug Moore * 183429c871dSDoug Moore * Requires that access be externally synchronized by a lock. 184429c871dSDoug Moore */ 185429c871dSDoug Moore static __inline vm_page_t 186429c871dSDoug Moore vm_radix_lookup_le(struct vm_radix *rtree, vm_pindex_t index) 187429c871dSDoug Moore { 188429c871dSDoug Moore return (VM_RADIX_PCTRIE_LOOKUP_LE(&rtree->rt_trie, index)); 189429c871dSDoug Moore } 190429c871dSDoug Moore 191429c871dSDoug Moore /* 192429c871dSDoug Moore * Remove the specified index from the trie, and return the value stored at 193429c871dSDoug Moore * that index. If the index is not present, return NULL. 194429c871dSDoug Moore */ 195429c871dSDoug Moore static __inline vm_page_t 196429c871dSDoug Moore vm_radix_remove(struct vm_radix *rtree, vm_pindex_t index) 197429c871dSDoug Moore { 198429c871dSDoug Moore return (VM_RADIX_PCTRIE_REMOVE_LOOKUP(&rtree->rt_trie, index)); 199429c871dSDoug Moore } 200429c871dSDoug Moore 201429c871dSDoug Moore /* 202c71c41daSDoug Moore * Remove the current page from the trie. 203c71c41daSDoug Moore */ 204c71c41daSDoug Moore static __inline void 205c71c41daSDoug Moore vm_radix_iter_remove(struct pctrie_iter *pages) 206c71c41daSDoug Moore { 207c71c41daSDoug Moore VM_RADIX_PCTRIE_ITER_REMOVE(pages); 208c71c41daSDoug Moore } 209c71c41daSDoug Moore 210c71c41daSDoug Moore /* 211c3d743a6SDoug Moore * Reclaim all the interior nodes of the trie, and invoke the callback 212c3d743a6SDoug Moore * on all the pages, in order. 213429c871dSDoug Moore */ 214429c871dSDoug Moore static __inline void 215c3d743a6SDoug Moore vm_radix_reclaim_callback(struct vm_radix *rtree, 216c3d743a6SDoug Moore void (*page_cb)(vm_page_t, void *), void *arg) 217429c871dSDoug Moore { 218c3d743a6SDoug Moore VM_RADIX_PCTRIE_RECLAIM_CALLBACK(&rtree->rt_trie, page_cb, arg); 219429c871dSDoug Moore } 220429c871dSDoug Moore 221429c871dSDoug Moore /* 222450a6690SDoug Moore * Initialize an iterator pointing to the page with the least pindex that is 223450a6690SDoug Moore * greater than or equal to the specified pindex, or NULL if there are no such 224450a6690SDoug Moore * pages. Return the page. 225450a6690SDoug Moore * 226450a6690SDoug Moore * Requires that access be externally synchronized by a lock. 227450a6690SDoug Moore */ 228450a6690SDoug Moore static __inline vm_page_t 229450a6690SDoug Moore vm_radix_iter_lookup_ge(struct pctrie_iter *pages, vm_pindex_t index) 230450a6690SDoug Moore { 231450a6690SDoug Moore return (VM_RADIX_PCTRIE_ITER_LOOKUP_GE(pages, index)); 232450a6690SDoug Moore } 233450a6690SDoug Moore 234450a6690SDoug Moore /* 235450a6690SDoug Moore * Update the iterator to point to the page with the least pindex that is 'jump' 236450a6690SDoug Moore * or more greater than or equal to the current pindex, or NULL if there are no 237450a6690SDoug Moore * such pages. Return the page. 238450a6690SDoug Moore * 239450a6690SDoug Moore * Requires that access be externally synchronized by a lock. 240450a6690SDoug Moore */ 241450a6690SDoug Moore static __inline vm_page_t 242450a6690SDoug Moore vm_radix_iter_jump(struct pctrie_iter *pages, vm_pindex_t jump) 243450a6690SDoug Moore { 244450a6690SDoug Moore return (VM_RADIX_PCTRIE_ITER_JUMP_GE(pages, jump)); 245450a6690SDoug Moore } 246450a6690SDoug Moore 247450a6690SDoug Moore /* 248450a6690SDoug Moore * Update the iterator to point to the page with the least pindex that is one or 249450a6690SDoug Moore * more greater than the current pindex, or NULL if there are no such pages. 250450a6690SDoug Moore * Return the page. 251450a6690SDoug Moore * 252450a6690SDoug Moore * Requires that access be externally synchronized by a lock. 253450a6690SDoug Moore */ 254450a6690SDoug Moore static __inline vm_page_t 255450a6690SDoug Moore vm_radix_iter_step(struct pctrie_iter *pages) 256450a6690SDoug Moore { 257450a6690SDoug Moore return (VM_RADIX_PCTRIE_ITER_STEP_GE(pages)); 258450a6690SDoug Moore } 259450a6690SDoug Moore 260450a6690SDoug Moore /* 261*f3895e98SDoug Moore * Initialize an iterator pointing to the page with the greatest pindex that is 262*f3895e98SDoug Moore * less than or equal to the specified pindex, or NULL if there are no such 263*f3895e98SDoug Moore * pages. Return the page. 264*f3895e98SDoug Moore * 265*f3895e98SDoug Moore * Requires that access be externally synchronized by a lock. 266*f3895e98SDoug Moore */ 267*f3895e98SDoug Moore static __inline vm_page_t 268*f3895e98SDoug Moore vm_radix_iter_lookup_le(struct pctrie_iter *pages, vm_pindex_t index) 269*f3895e98SDoug Moore { 270*f3895e98SDoug Moore return (VM_RADIX_PCTRIE_ITER_LOOKUP_LE(pages, index)); 271*f3895e98SDoug Moore } 272*f3895e98SDoug Moore 273*f3895e98SDoug Moore /* 274450a6690SDoug Moore * Update the iterator to point to the page with the pindex that is one greater 275450a6690SDoug Moore * than the current pindex, or NULL if there is no such page. Return the page. 276450a6690SDoug Moore * 277450a6690SDoug Moore * Requires that access be externally synchronized by a lock. 278450a6690SDoug Moore */ 279450a6690SDoug Moore static __inline vm_page_t 280450a6690SDoug Moore vm_radix_iter_next(struct pctrie_iter *pages) 281450a6690SDoug Moore { 282450a6690SDoug Moore return (VM_RADIX_PCTRIE_ITER_NEXT(pages)); 283450a6690SDoug Moore } 284450a6690SDoug Moore 285450a6690SDoug Moore /* 286450a6690SDoug Moore * Update the iterator to point to the page with the pindex that is one less 287450a6690SDoug Moore * than the current pindex, or NULL if there is no such page. Return the page. 288450a6690SDoug Moore * 289450a6690SDoug Moore * Requires that access be externally synchronized by a lock. 290450a6690SDoug Moore */ 291450a6690SDoug Moore static __inline vm_page_t 292450a6690SDoug Moore vm_radix_iter_prev(struct pctrie_iter *pages) 293450a6690SDoug Moore { 294450a6690SDoug Moore return (VM_RADIX_PCTRIE_ITER_PREV(pages)); 295450a6690SDoug Moore } 296450a6690SDoug Moore 297450a6690SDoug Moore /* 298450a6690SDoug Moore * Return the current page. 299450a6690SDoug Moore * 300450a6690SDoug Moore * Requires that access be externally synchronized by a lock. 301450a6690SDoug Moore */ 302450a6690SDoug Moore static __inline vm_page_t 303450a6690SDoug Moore vm_radix_iter_page(struct pctrie_iter *pages) 304450a6690SDoug Moore { 305450a6690SDoug Moore return (VM_RADIX_PCTRIE_ITER_VALUE(pages)); 306450a6690SDoug Moore } 307450a6690SDoug Moore 308450a6690SDoug Moore /* 309429c871dSDoug Moore * Replace an existing page in the trie with another one. 310429c871dSDoug Moore * Panics if there is not an old page in the trie at the new page's index. 311429c871dSDoug Moore */ 312429c871dSDoug Moore static __inline vm_page_t 313429c871dSDoug Moore vm_radix_replace(struct vm_radix *rtree, vm_page_t newpage) 314429c871dSDoug Moore { 315429c871dSDoug Moore return (VM_RADIX_PCTRIE_REPLACE(&rtree->rt_trie, newpage)); 316cd1241fbSKonstantin Belousov } 317774d251dSAttilio Rao 318774d251dSAttilio Rao #endif /* _KERNEL */ 319774d251dSAttilio Rao #endif /* !_VM_RADIX_H_ */ 320