1.\" $OpenBSD: extent.9,v 1.20 2024/01/19 22:12:24 kettenis Exp $ 2.\" $NetBSD: extent.9,v 1.15 1999/03/16 00:40:47 garbled Exp $ 3.\" 4.\" Copyright (c) 1996, 1998 The NetBSD Foundation, Inc. 5.\" All rights reserved. 6.\" 7.\" This code is derived from software contributed to The NetBSD Foundation 8.\" by Jason R. Thorpe and Greg Hudson. 9.\" 10.\" Redistribution and use in source and binary forms, with or without 11.\" modification, are permitted provided that the following conditions 12.\" are met: 13.\" 1. Redistributions of source code must retain the above copyright 14.\" notice, this list of conditions and the following disclaimer. 15.\" 2. Redistributions in binary form must reproduce the above copyright 16.\" notice, this list of conditions and the following disclaimer in the 17.\" documentation and/or other materials provided with the distribution. 18.\" 19.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29.\" POSSIBILITY OF SUCH DAMAGE. 30.\" 31.Dd $Mdocdate: January 19 2024 $ 32.Dt EXTENT 9 33.Os 34.Sh NAME 35.Nm extent_create , 36.Nm extent_destroy , 37.Nm extent_alloc , 38.Nm extent_alloc_with_descr , 39.Nm extent_alloc_subregion , 40.Nm extent_alloc_subregion_with_descr , 41.Nm extent_alloc_region , 42.Nm extent_alloc_region_with_descr , 43.Nm extent_free , 44.Nm extent_print 45.Nd general purpose extent manager 46.Sh SYNOPSIS 47.In sys/malloc.h 48.In sys/extent.h 49.Ft struct extent * 50.Fn extent_create "char *name" "u_long start" "u_long end" "int mtype" "caddr_t storage" "size_t storagesize" "int flags" 51.Ft void 52.Fn extent_destroy "struct extent *ex" 53.Ft int 54.Fn extent_alloc "struct extent *ex" "u_long size" "u_long alignment" "u_long skew" "u_long boundary" "int flags" "u_long *result" 55.Ft int 56.Fn extent_alloc_with_descr "struct extent *ex" "u_long size" "u_long alignment" "u_long skew" "u_long boundary" "int flags" "struct extent_region *rp" "u_long *result" 57.Ft int 58.\" too many arguments for a single .Fn 59.Fo extent_alloc_subregion 60.Fa "struct extent *ex" 61.Fa "u_long substart" 62.Fa "u_long subend" 63.Fa "u_long size" 64.Fa "u_long alignment" 65.Fa "u_long skew" 66.Fa "u_long boundary" 67.Fa "int flags" 68.Fa "u_long *result" 69.Fc 70.Ft int 71.\" way too many arguments for a single .Fn 72.Fo extent_alloc_subregion_with_descr 73.Fa "struct extent *ex" 74.Fa "u_long substart" 75.Fa "u_long subend" 76.Fa "u_long size" 77.Fa "u_long alignment" 78.Fa "u_long skew" 79.Fa "u_long boundary" 80.Fa "int flags" 81.Fa "struct extent_region *rp" 82.Fa "u_long *result" 83.Fc 84.Ft int 85.Fn extent_alloc_region "struct extent *ex" "u_long start" "u_long size" "int flags" 86.Ft int 87.Fn extent_alloc_region_with_descr "struct extent *ex" "u_long start" "u_long size" "int flags" "struct extent_region *rp" 88.Ft int 89.Fn extent_free "struct extent *ex" "u_long start" "u_long size" "int flags" 90.Ft void 91.Fn extent_print "struct extent *ex" 92.Sh DESCRIPTION 93The extent manager provides management of areas of memory or 94other enumerable spaces (such as I/O ports). 95An opaque structure called an 96.Nm extent map 97keeps track of allocated regions within the enumerable space. 98.Pp 99.Fn extent_create 100creates an extent map managing the space from 101.Fa start 102to 103.Fa end 104inclusive. 105All memory allocation will use the memory type 106.Fa mtype 107.Po 108see 109.Xr malloc 9 110.Pc . 111The extent map will have the name 112.Fa name , 113used for identification in case of errors or in 114.Xr ddb 4 115.Ic show extents . 116If the flag 117.Dv EX_NOCOALESCE 118is set, internal coalescing of regions is disabled, 119and only entire regions may be freed within the extent map, so that 120.Fn extent_free 121will never have to allocate a region descriptor. 122If the flag 123.Dv EX_FILLED 124is set, the entire space managed by the extent map will be allocated 125upon creation of the extent map, such that selected regions may be 126made available through calls to 127.Fn extent_free . 128.Pp 129Some applications may want to use an extent map but 130can't use 131.Fn malloc 132and 133.Fn free . 134These applications may provide pre-allocated storage for 135all descriptor overhead with the arguments 136.Fa storage 137and 138.Fa storagesize . 139An extent of this type is called a 140.Nm fixed extent . 141If the application can safely use 142.Fn malloc 143and 144.Fn free , 145.Fa storage 146should be 147.Dv NULL . 148A fixed extent has a fixed number of region descriptors, so care 149should be taken to provide enough storage for them; alternatively, the 150flag 151.Dv EX_MALLOCOK 152may be passed to extent requests to indicate that a fixed extent 153map may be extended using a call to 154.Fn malloc . 155Note that passing the flag 156.Dv EX_FILLED 157to 158.Fn extent_create 159will consume a region descriptor upon creation of the extent map. 160.Pp 161The caller should pass the flag 162.Dv EX_WAITOK 163or 164.Dv EX_NOWAIT 165to extent functions that have a memory overhead, to specify whether 166it is okay to wait. 167These functions are 168.Fn extent_create 169(non fixed extents), 170.Fn extent_free 171(unless 172.Dv EX_NOCOALESCE 173is set), 174.Fn extent_alloc , 175.Fn extent_alloc_subregion 176and 177.Fn extent_alloc_region . 178.Pp 179.Fn extent_destroy 180destroys the extent map 181.Fa ex , 182freeing all allocated regions. 183If the extent is not a fixed extent, 184the region and internal extent descriptors themselves are freed. 185This function always succeeds. 186.Pp 187.Fn extent_alloc 188allocates a region in the extent map 189.Fa ex 190of size 191.Fa size 192that fits the provided parameters. 193There are two distinct allocation policies, which are selected by the 194.Fa flags 195argument: 196.Bl -tag -offset indent -width "XXXXXXXXX" 197.It Dv EX_FAST 198Allocate the first region that fits the provided parameters, regardless 199of resulting extent fragmentation. 200.It default 201Allocate the smallest region that is capable of holding the request, 202thus minimizing fragmentation of the extent. 203.El 204.Pp 205The caller may specify that it is okay to wait for space to become free in the 206extent by setting the flag 207.Dv EX_WAITSPACE . 208If 209.Dv EX_WAITSPACE 210is not set, the allocation will fail if the request cannot be 211satisfied without sleeping. 212.Pp 213The request will be aligned to a multiple of 214.Fa alignment . 215That value must be a power of 2. 216If no alignment is necessary, the value 217.Dv EX_NOALIGN 218should be specified. 219If 220.Fa skew 221is non-zero, it modifies the requested alignment result in the following way: 222the value 223.Pq Fa result No - Fa skew 224is aligned to 225.Fa alignment 226boundaries. 227.Fa skew 228must be a smaller number than 229.Fa alignment . 230If 231.Fa boundary 232is not 233.Dv EX_NOBOUNDARY , 234the allocated region will not cross any boundary lines, spaced 235.Fa boundary 236apart. 237If the caller specifies the 238.Dv EX_BOUNDZERO 239flag, boundary lines begin at zero. 240Otherwise, boundary lines begin at the beginning of the extent. 241The allocated region may begin on a 242boundary line, but the end of the region will not touch nor cross a 243boundary line. 244A 245.Fa boundary 246argument smaller than the sum of the requested skew and the size of 247the request is invalid. 248Upon successful completion, 249.Fa *result 250will contain the start of the allocated region. 251.Pp 252.Fn extent_alloc_with_descr 253is similar to 254.Fn extent_alloc 255but allows the caller to provide a pre-allocated region descriptor instead 256of having the function allocate one. 257This function can only be used with extents that have the 258.Dv EX_NOCOALESCE 259property. 260.Pp 261.Fn extent_alloc_subregion 262and 263.Fn extent_alloc_subregion_with_descr 264are generalized versions of 265.Fn extent_alloc 266and 267.Fn extent_alloc_with_descr 268that allow the caller to specify that the allocated region must fall 269within the subregion from 270.Fa substart 271to 272.Fa subend 273inclusive. 274.Pp 275.Fn extent_alloc_region 276allocates the specific region in the extent map 277.Fa ex 278beginning at 279.Fa start 280with the size 281.Fa size . 282If the caller specifies the 283.Dv EX_CONFLICTOK 284flag, the allocation will succeed even if part of the requested region 285has already been allocated. 286The caller may specify that it is okay to wait for the indicated 287region to be free by setting the flag 288.Dv EX_WAITSPACE . 289If neither 290.Dv EX_WAITSPACE 291nor 292.Dv EX_CONFLICTOK 293is set, the allocation will fail if the request cannot be 294satisfied without sleeping. 295.Pp 296.Fn extent_alloc_region_with_descr 297is similar to 298.Fn extent_alloc_region 299but allows the caller to provide a pre-allocated region descriptor instead 300of having the function allocate one. 301This function can only be used with extents that have the 302.Dv EX_NOCOALESCE 303property. 304.Pp 305.Fn extent_free 306frees a region of 307.Fa size 308bytes starting at 309.Fa start 310in the extent map 311.Fa ex . 312If the extent has the 313.Dv EX_NOCOALESCE 314property, only entire regions may be freed. 315If the extent has the 316.Dv EX_NOCOALESCE 317property and the caller attempts to free a partial region, behavior is 318undefined. 319If called on an extent without the 320.Dv EX_NOCOALESCE 321property, this function can fail with error codes listed below, otherwise 322this function will always succeed. 323.Pp 324.Fn extent_print 325Prints out information about extent 326.Fa ex . 327This function always succeeds. 328.Sh RETURN VALUES 329The behavior of all extent manager functions is undefined if given 330invalid arguments. 331.Fn extent_create 332returns the extent map on success, or 333.Dv NULL 334if it fails to allocate storage for the extent map. 335It always succeeds when creating a fixed extent or when given the flag 336.Dv EX_WAITOK . 337.Fn extent_alloc , 338.Fn extent_alloc_region , 339.Fn extent_alloc_subregion , 340and 341.Fn extent_free 342return one of the following values: 343.Bl -tag -offset indent -width "XXXXXXXX" 344.It Dv 0 345Operation was successful. 346.It Dv ENOMEM 347If 348.Dv EX_NOWAIT 349is specified, the extent manager was not able to allocate a region 350descriptor for the new region or to split a region when freeing a 351partial region. 352.It Dv EAGAIN 353Requested region is not available and 354.Dv EX_WAITSPACE 355was not specified. 356.It Dv EINTR 357Process received a signal while waiting for the requested region to 358become available in the extent. 359.El 360.Sh EXAMPLES 361Here is an example of a (useless) function that uses several of the 362extent manager routines. 363.Bd -literal 364void 365func() 366{ 367 struct extent *foo_ex; 368 u_long region_start; 369 int error; 370 371 /* 372 * Extent "foo" manages a 256k region starting at 0x0 and 373 * only allows complete regions to be freed so that 374 * extent_free() never needs to allocate memory. 375 */ 376 foo_ex = extent_create("foo", 0x0, 0x3ffff, M_DEVBUF, 377 NULL, 0, EX_WAITOK | EX_NOCOALESCE); 378 379 /* 380 * Allocate an 8k region, aligned to a 4k boundary, which 381 * does not cross any of the 3 64k boundaries (at 64k, 382 * 128k, and 192k) within the extent. 383 */ 384 error = extent_alloc(foo_ex, 0x2000, 0x1000, 0x10000, 385 EX_NOWAIT, ®ion_start); 386 if (error) 387 panic("you lose"); 388 389 /* 390 * Give up the extent. 391 */ 392 extent_destroy(foo_ex); 393} 394.Ed 395.\" 396.\" Yeah, right... document EX_CATCH first... 397.\" 398.\" .Sh LIMITATIONS 399.\" The flag 400.\" .Dv EX_CATCH 401.\" cannot be used to catch signals in all circumstances since 402.\" .Xr malloc 9 403.\" does not provide such a functionality. 404.Sh CODE REFERENCES 405The extent manager itself is implemented within the file 406.Pa sys/kern/subr_extent.c . 407.Pp 408The i386 bus management code uses the extent manager for managing I/O 409ports and I/O memory. 410See 411.Pa sys/arch/i386/i386/machdep.c . 412.Sh SEE ALSO 413.Xr ddb 4 , 414.Xr malloc 9 415.Sh HISTORY 416The extent manager appeared in 417.Nx 1.3 . 418.Sh AUTHORS 419.An -nosplit 420The extent manager was designed and implemented by 421.An Jason R. Thorpe Aq Mt thorpej@NetBSD.ORG . 422.An Matthias Drochner Aq Mt drochner@zelux6.zel.kfa-juelich.de 423contributed to the initial testing and optimization of the implementation. 424.An Chris Demetriou Aq Mt cgd@NetBSD.ORG 425contributed many architectural suggestions. 426