1.\" $NetBSD: vmem.9,v 1.22 2023/12/02 21:02:12 thorpej Exp $ 2.\" 3.\" Copyright (c)2006 YAMAMOTO Takashi, 4.\" All rights reserved. 5.\" 6.\" Redistribution and use in source and binary forms, with or without 7.\" modification, are permitted provided that the following conditions 8.\" are met: 9.\" 1. Redistributions of source code must retain the above copyright 10.\" notice, this list of conditions and the following disclaimer. 11.\" 2. Redistributions in binary form must reproduce the above copyright 12.\" notice, this list of conditions and the following disclaimer in the 13.\" documentation and/or other materials provided with the distribution. 14.\" 15.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25.\" SUCH DAMAGE. 26.\" 27.\" ------------------------------------------------------------ 28.Dd December 2, 2023 29.Dt VMEM 9 30.Os 31.\" ------------------------------------------------------------ 32.Sh NAME 33.Nm vmem 34.Nd virtual memory allocator 35.\" ------------------------------------------------------------ 36.Sh SYNOPSIS 37.In sys/vmem.h 38.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 39.Ft vmem_t * 40.Fn vmem_create \ 41"const char *name" "vmem_addr_t base" "vmem_size_t size" "vmem_size_t quantum" \ 42"int (*allocfn)(void *, vmem_size_t, vm_flag_t, vmem_addr_t *)" \ 43"void (*freefn)(void *, vmem_addr_t, vmem_size_t)" \ 44"void *arg" "vmem_size_t qcache_max" "vm_flag_t flags" "int ipl" 45.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 46.Ft vmem_t * 47.Fn vmem_xcreate \ 48"const char *name" "vmem_addr_t base" "vmem_size_t size" "vmem_size_t quantum" \ 49"int (*allocfn)(void *, vmem_size_t, vmem_size_t *, vm_flag_t, vmem_addr_t *)" \ 50"void (*freefn)(void *, vmem_addr_t, vmem_size_t)" \ 51"void *arg" "vmem_size_t qcache_max" "vm_flag_t flags" "int ipl" 52.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 53.Ft int 54.Fn vmem_add \ 55"vmem_t *vm" "vmem_addr_t addr" "vmem_size_t size" "vm_flag_t flags" 56.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 57.Ft int 58.Fn vmem_xalloc \ 59"vmem_t *vm" "vmem_size_t size" "vmem_size_t align" \ 60"vmem_size_t phase" "vmem_size_t nocross" "vmem_addr_t minaddr" \ 61"vmem_addr_t maxaddr" "vm_flag_t flags" "vmem_addr_t *addrp" 62.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 63.Ft int 64.Fn vmem_xalloc_addr \ 65"vmem_t *vm" "vmem_addr_t addr" "vmem_size_t size" "vm_flag_t flags" 66.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 67.Ft void 68.Fn vmem_xfree "vmem_t *vm" "vmem_addr_t addr" "vmem_size_t size" 69.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 70.Ft void 71.Fn vmem_xfreeall "vmem_t *vm" 72.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 73.Ft int 74.Fn vmem_alloc "vmem_t *vm" "vmem_size_t size" "vm_flag_t flags" "vmem_addr_t *addrp" 75.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 76.Ft void 77.Fn vmem_free "vmem_t *vm" "vmem_addr_t addr" "vmem_size_t size" 78.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 79.Ft void 80.Fn vmem_destroy "vmem_t *vm" 81.\" ------------------------------------------------------------ 82.Sh DESCRIPTION 83The 84.Nm 85is a general purpose resource allocator. 86Despite its name, it can be used for arbitrary resources 87other than virtual memory. 88.Pp 89.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 90.Fn vmem_create 91creates a new vmem arena. 92.Bl -tag -offset indent -width qcache_max 93.It Fa name 94The string to describe the vmem. 95.It Fa base 96The start address of the initial span. 97Pass 98.Dv 0 99if no initial span is required. 100.It Fa size 101The size of the initial span. 102Pass 103.Dv 0 104if no initial span is required. 105.It Fa quantum 106The smallest unit of allocation. 107.It Fa allocfn 108The callback function used to import spans from the backend arena. 109Set both 110.Fa allocfn 111and 112.Fa freefn 113to 114.Dv NULL 115to disable automatic imports. 116.Nm 117calls 118.Fo "(*allocfn)" 119.Fa arg 120.Fa size 121.Fa flags 122.Fa "&addrp" 123.Fc 124to import a span of size at least 125.Fa size . 126.Fa allocfn 127must accept the same 128.Fa flags 129as 130.Fn vmem_alloc . 131.Fa allocfn 132must return 133.Dv ENOMEM 134to indicate failure, or 0 on success. 135If 136.Fa allocfn 137succeeds, it must write the starting address of the imported span to 138.Fa addrp . 139.It Fa freefn 140The callback function used to free spans to the backend arena. 141.Fa freefn 142may be 143.Dv NULL 144even if 145.Fa allocfn 146is not 147.Dv NULL . 148.Nm 149calls 150.Fn "(*freefn)" arg addr size 151to return to 152.Fa arg 153a span of size 154.Fa size , 155starting at 156.Fa addr , 157that was previously allocated by 158.Fa allocfn . 159.It Fa arg 160The backend arena. 161.Fa arg 162may be 163.Dv NULL . 164.Nm 165passes 166.Fa arg 167as the first argument of 168.Fa allocfn 169and 170.Fa freefn . 171.It Fa qcache_max 172The largest size of allocations which can be served by quantum cache. 173It is merely a hint and can be ignored. 174.It Fa flags 175Either of: 176.Bl -tag -width VM_NOSLEEP 177.It Dv VM_SLEEP 178If the allocation cannot be satisfied immediately, sleep until enough 179resources are available. 180.It Dv VM_NOSLEEP 181Don't sleep. 182Immediately return 183.Dv NULL 184if there are not enough resources available. 185.El 186.It Fa ipl 187Interrupt level to be blocked for allocating from vmem. 188.El 189.Pp 190.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 191.Fn vmem_xcreate 192creates a new vmem arena. 193.Bl -tag -offset indent -width qcache_max 194.It Fa name 195The string to describe the vmem. 196.It Fa base 197The start address of the initial span. 198Pass 199.Dv 0 200if no initial span is required. 201.It Fa size 202The size of the initial span. 203Pass 204.Dv 0 205if no initial span is required. 206.It Fa quantum 207The smallest unit of allocation. 208.It Fa allocfn 209The callback function used to import spans from the backend arena. 210Set both 211.Fa allocfn 212and 213.Fa freefn 214to 215.Dv NULL 216to disable automatic imports. 217.Nm 218calls 219.Fo "(*allocfn)" 220.Fa arg 221.Fa size 222.Fa "&actualsize" 223.Fa flags 224.Fa "&addrp" 225.Fc 226to import a span of size at least 227.Fa size . 228.Fa allocfn 229must accept the same 230.Fa flags 231as 232.Fn vmem_alloc . 233.Fa allocfn 234must return 235.Dv ENOMEM 236to indicate failure, or 0 on success. 237If 238.Fa allocfn 239succeeds, it must write the actual size of the allocation to 240.Fa actualsize 241and the starting address of the imported span to 242.Fa addrp . 243The actual size will always be greater than or equal to the requested size. 244.It Fa freefn 245The callback function used to free spans to the backend arena. 246.Fa freefn 247may be 248.Dv NULL 249even if 250.Fa allocfn 251is not 252.Dv NULL . 253.Nm 254calls 255.Fn "(*freefn)" arg addr size 256to return to 257.Fa arg 258a span of size 259.Fa size , 260starting at 261.Fa addr , 262that was previously allocated by 263.Fa allocfn . 264.It Fa arg 265The backend arena. 266.Fa arg 267may be 268.Dv NULL . 269.Nm 270passes 271.Fa arg 272as the first argument of 273.Fa allocfn 274and 275.Fa freefn . 276.It Fa qcache_max 277The largest size of allocations which can be served by quantum cache. 278It is merely a hint and can be ignored. 279.It Fa flags 280Either of: 281.Bl -tag -width VM_NOSLEEP 282.It Dv VM_SLEEP 283If the allocation cannot be satisfied immediately, sleep until enough 284resources are available. 285.It Dv VM_NOSLEEP 286Don't sleep. 287Immediately return 288.Dv NULL 289if there are not enough resources available. 290.El 291.It Fa ipl 292Interrupt level to be blocked for allocating from vmem. 293.El 294.Pp 295.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 296.Fn vmem_add 297adds a span of size 298.Fa size 299starting at 300.Fa addr 301to the arena. 302Returns 3030 304on success, 305.Dv ENOMEM 306on failure. 307.Bl -tag -offset indent -width flags 308.It Fa flags 309Either of: 310.Bl -tag -width VM_NOSLEEP 311.It Dv VM_SLEEP 312If the allocation cannot be satisfied immediately, sleep until enough 313resources are available. 314.It Dv VM_NOSLEEP 315Don't sleep. 316Immediately return 317.Dv ENOMEM 318if there are not enough resources available. 319.El 320.El 321.Pp 322.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 323.Fn vmem_xalloc 324allocates a resource from the arena. 325.Bl -tag -offset indent -width nocross 326.It Fa vm 327The arena which we allocate from. 328.It Fa size 329Specify the size of the allocation. 330.It Fa align 331If zero, don't care about the alignment of the allocation. 332Otherwise, request a resource segment starting at 333offset 334.Fa phase 335from an 336.Fa align 337aligned boundary. 338.It Fa phase 339See the above description of 340.Fa align . 341If 342.Fa align 343is zero, 344.Fa phase 345must be zero. 346Otherwise, 347.Fa phase 348must be smaller than 349.Fa align . 350.It Fa nocross 351Request a resource which doesn't cross 352.Fa nocross 353aligned boundary. 354.It Fa minaddr 355Specify the minimum address which can be allocated, or 356.Dv VMEM_ADDR_MIN 357if the caller does not care. 358.It Fa maxaddr 359Specify the maximum address which can be allocated, or 360.Dv VMEM_ADDR_MAX 361if the caller does not care. 362.It Fa flags 363A bitwise OR of an allocation strategy and a sleep flag. 364.Pp 365The allocation strategy must be one of: 366.Bl -tag -width VM_INSTANTFIT 367.It Dv VM_BESTFIT 368Prefer space efficiency. 369.It Dv VM_INSTANTFIT 370Prefer performance. 371.El 372.Pp 373The sleep flag must be one of: 374.Bl -tag -width VM_NOSLEEP 375.It Dv VM_SLEEP 376If the allocation cannot be satisfied immediately, sleep until enough 377resources are available. 378.It Dv VM_NOSLEEP 379Don't sleep. 380Immediately return 381.Dv ENOMEM 382if there are not enough resources available. 383.El 384.It Fa addrp 385On success, if 386.Fa addrp 387is not 388.Dv NULL , 389.Fn vmem_xalloc 390overwrites it with the start address of the allocated span. 391.El 392.Pp 393.\" ------------------------------------------------------------ 394.Fn vmem_xalloc_addr 395allocates a specific address from the arena. 396The requested address must be aligned with the arena's quantum. 397.Bl -tag -offset indent -width flags 398.It Fa vm 399The arena which we allocate from. 400.It Fa addr 401The address to allocate. 402.It Fa size 403Specify the size of the allocation. 404.It Fa flags 405A sleep flag. 406Because a specific address is being allocated, any specified allocation 407strategy is ignored. 408.Pp 409The sleep flag must be one of: 410.Bl -tag -width VM_NOSLEEP 411.It Dv VM_SLEEP 412If the allocation cannot be satisfied immediately, sleep until the 413requested range can be allocated. 414.It Dv VM_NOSLEEP 415Don't sleep. 416Immediately return 417.Dv ENOMEM 418if the requested range is not available. 419.El 420.El 421.Pp 422.\" ------------------------------------------------------------ 423.Fn vmem_xfree 424frees resource allocated by 425.Fn vmem_xalloc 426or 427.Fn vmem_xalloc_addr 428to the arena. 429.Bl -tag -offset indent -width addr 430.It Fa vm 431The arena which we free to. 432.It Fa addr 433The resource being freed. 434It must have been allocated via 435.Fn vmem_xalloc 436or 437.Fn vmem_xalloc_addr . 438Notably, it must not have been allocated via 439.Fn vmem_alloc , 440otherwise, the behaviour is undefined. 441.It Fa size 442The size of the resource being freed. 443It must be the same as the 444.Fa size 445argument used for 446.Fn vmem_xalloc 447or 448.Fn vmem_xalloc_addr . 449.El 450.Pp 451.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 452.Fn vmem_xfreeall 453frees all resources that have been allocated by 454.Fn vmem_xalloc 455to the arena. 456.Bl -tag -offset indent -width addr 457.It Fa vm 458The arena which we free to. 459Note that this function is may not be used on arenas 460where resources have been allocated using 461.Fn vmem_alloc 462or arenas that have a quantum cache 463.Po 464i.e. were created with a non-zero 465.Fa qcache_max 466.Pc . 467.El 468.Pp 469.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 470.Fn vmem_alloc 471allocates a resource from the arena. 472.Bl -tag -offset indent -width flags 473.It Fa vm 474The arena which we allocate from. 475.It Fa size 476Specify the size of the allocation. 477.It Fa flags 478A bitwise OR of an allocation strategy and a sleep flag. 479.Pp 480The allocation strategy must be one of: 481.Bl -tag -width VM_INSTANTFIT 482.It Dv VM_BESTFIT 483Prefer space efficiency. 484.It Dv VM_INSTANTFIT 485Prefer performance. 486.El 487.Pp 488The sleep flag must be one of: 489.Bl -tag -width VM_NOSLEEP 490.It Dv VM_SLEEP 491If the allocation cannot be satisfied immediately, sleep until enough 492resources are available. 493.It Dv VM_NOSLEEP 494Don't sleep. 495Immediately return 496.Dv ENOMEM 497if there are not enough resources available. 498.El 499.It Fa addrp 500On success, if 501.Fa addrp 502is not 503.Dv NULL , 504.Fn vmem_alloc 505overwrites it with the start address of the allocated span. 506.El 507.Pp 508.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 509.Fn vmem_free 510frees resource allocated by 511.Fn vmem_alloc 512to the arena. 513.Bl -tag -offset indent -width addr 514.It Fa vm 515The arena which we free to. 516.It Fa addr 517The resource being freed. 518It must have been allocated via 519.Fn vmem_alloc . 520Notably, it must not have been allocated via 521.Fn vmem_xalloc 522or 523.Fn vmem_xalloc addr , 524otherwise, the behaviour is undefined. 525.It Fa size 526The size of the resource being freed. 527It must be the same as the 528.Fa size 529argument used for 530.Fn vmem_alloc . 531.El 532.Pp 533.\" ------------------------------------------------------------ 534.Fn vmem_destroy 535destroys a vmem arena. 536.Bl -tag -offset indent -width vm 537.It Fa vm 538The vmem arena being destroyed. 539The caller must ensure that no one will use it anymore. 540.El 541.\" ------------------------------------------------------------ 542.Sh RETURN VALUES 543.Fn vmem_create 544and 545.Fn vmem_xcreate 546return a pointer to the newly allocated vmem_t on success, or 547.Dv NULL 548if 549.Dv VM_NOSLEEP 550was specified and memory could not be allocated immediately. 551.Pp 552.Fn vmem_add 553returns 0 on success, or 554.Er ENOMEM 555if 556.Dv VM_NOSLEEP 557was specified and memory could not be allocated immediately to record 558the region. 559.Pp 560.Fn vmem_alloc 561and 562.Fn vmem_xalloc 563return 0 on success, or 564.Er ENOMEM 565if either: 566.Bl -dash 567.It 568.Dv VM_NOSLEEP 569was specified and a matching region could not be allocated immediately; 570or 571.It 572non-default 573.Fa align , 574.Fa phase , 575or 576.Fa nocross 577parameters were specified, and a matching region could not be allocated 578without calling the backing 579.Fa allocfn 580passed to 581.Fn vmem_create . 582.El 583.\" ------------------------------------------------------------ 584.Sh CODE REFERENCES 585The 586.Nm 587subsystem is implemented within the file 588.Pa sys/kern/subr_vmem.c . 589.\" ------------------------------------------------------------ 590.Sh SEE ALSO 591.Xr intro 9 , 592.Xr kmem 9 , 593.Xr memoryallocators 9 , 594.Xr uvm 9 595.Rs 596.%A Jeff Bonwick 597.%A Jonathan Adams 598.%T "Magazines and Vmem: Extending the Slab Allocator to Many CPUs and Arbitrary Resources" 599.%J "2001 USENIX Annual Technical Conference" 600.%D 2001 601.Re 602.\" ------------------------------------------------------------ 603.Sh AUTHORS 604This implementation of 605.Nm 606was written by 607.An YAMAMOTO Takashi . 608.Sh BUGS 609.Nm 610relies on 611.Xr malloc 9 , 612.Xr pool 9 , 613and 614.Xr RUN_ONCE 9 , 615so it cannot be used as early during system bootstrap as 616.Xr extent 9 . 617.Pp 618.Nm 619has no way to pass 620.Fa align , 621.Fa phase , 622.Fa nocross , 623.Fa minaddr , 624or 625.Fa maxaddr 626constraints into the backing allocator 627.Fa allocfn , 628so even if 629.Dv VM_SLEEP 630is specified, 631.Fn vmem_alloc 632and 633.Fn vmem_xalloc 634may spuriously fail immediately with 635.Fa align , 636.Fa phase , 637or 638.Fa nocross , 639or sleep forever with 640.Fa minaddr 641or 642.Fa maxaddr . 643