NAME
extent_create
,
extent_destroy
,
extent_alloc
,
extent_alloc_with_descr
,
extent_alloc_subregion
,
extent_alloc_subregion_with_descr
,
extent_alloc_region
,
extent_alloc_region_with_descr
,
extent_free
, extent_print
— general purpose extent
manager
SYNOPSIS
#include
<sys/malloc.h>
#include <sys/extent.h>
struct extent *
extent_create
(char
*name, u_long
start, u_long end,
int mtype,
caddr_t storage,
size_t storagesize,
int flags);
void
extent_destroy
(struct
extent *ex);
int
extent_alloc
(struct
extent *ex, u_long
size, u_long
alignment, u_long
skew, u_long
boundary, int
flags, u_long
*result);
int
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);
int
extent_alloc_subregion
(struct extent
*ex, u_long substart, u_long
subend, u_long size, u_long
alignment, u_long skew, u_long
boundary, int flags, u_long
*result);
int
extent_alloc_subregion_with_descr
(struct
extent *ex, u_long substart,
u_long subend, u_long size,
u_long alignment, u_long skew,
u_long boundary, int flags,
struct extent_region *rp, u_long
*result);
int
extent_alloc_region
(struct
extent *ex, u_long
start, u_long size,
int flags);
int
extent_alloc_region_with_descr
(struct
extent *ex, u_long
start, u_long size,
int flags,
struct extent_region
*rp);
int
extent_free
(struct
extent *ex, u_long
start, u_long size,
int flags);
void
extent_print
(struct
extent *ex);
DESCRIPTION
The extent manager provides management of areas of memory or other
enumerable spaces (such as I/O ports). An opaque structure called an
extent map
keeps track of allocated regions within
the enumerable space.
extent_create
()
creates an extent map managing the space from start to
end inclusive. All memory allocation will use the
memory type mtype (see
malloc(9)). The extent map will have the name
name, used for identification in case of errors or in
ddb(4)
show extents
. If the flag
EX_NOCOALESCE
is set, internal coalescing of regions
is disabled, and only entire regions may be freed within the extent map, so
that extent_free
() will never have to allocate a
region descriptor. If the flag EX_FILLED
is set, the
entire space managed by the extent map will be allocated upon creation of
the extent map, such that selected regions may be made available through
calls to extent_free
().
Some applications may want to use an extent map but
can't use
malloc
() and
free
().
These applications may provide pre-allocated storage for all descriptor
overhead with the arguments storage and
storagesize. An extent of this type is called a
fixed extent
. If the application can safely use
malloc
() and free
(),
storage should be NULL
. A
fixed extent has a fixed number of region descriptors, so care should be
taken to provide enough storage for them; alternatively, the flag
EX_MALLOCOK
may be passed to extent requests to
indicate that a fixed extent map may be extended using a call to
malloc
(). Note that passing the flag
EX_FILLED
to extent_create
()
will consume a region descriptor upon creation of the extent map.
The caller should pass the flag
EX_WAITOK
or EX_NOWAIT
to
extent functions that have a memory overhead, to specify whether it is okay
to wait. These functions are
extent_create
()
(non fixed extents), extent_free
() (unless
EX_NOCOALESCE
is set),
extent_alloc
(),
extent_alloc_subregion
() and
extent_alloc_region
().
extent_destroy
()
destroys the extent map ex, freeing all allocated
regions. If the extent is not a fixed extent, the region and internal extent
descriptors themselves are freed. This function always succeeds.
extent_alloc
()
allocates a region in the extent map ex of size
size that fits the provided parameters. There are two
distinct allocation policies, which are selected by the
flags argument:
EX_FAST
- Allocate the first region that fits the provided parameters, regardless of resulting extent fragmentation.
- default
- Allocate the smallest region that is capable of holding the request, thus minimizing fragmentation of the extent.
The caller may specify that it is okay to wait for space to become
free in the extent by setting the flag EX_WAITSPACE
.
If EX_WAITSPACE
is not set, the allocation will fail
if the request cannot be satisfied without sleeping.
The request will be aligned to a multiple of
alignment. That value must be a power of 2. If no
alignment is necessary, the value EX_NOALIGN
should
be specified. If skew is non-zero, it modifies the
requested alignment result in the following way: the value
(result -
skew) is aligned to alignment
boundaries. skew must be a smaller number than
alignment. If boundary is not
EX_NOBOUNDARY
, the allocated region will not cross
any boundary lines, spaced boundary apart. If the
caller specifies the EX_BOUNDZERO
flag, boundary
lines begin at zero. Otherwise, boundary lines begin at the beginning of the
extent. The allocated region may begin on a boundary line, but the end of
the region will not touch nor cross a boundary line. A
boundary argument smaller than the sum of the
requested skew and the size of the request is invalid. Upon successful
completion, *result will contain the start of the
allocated region.
extent_alloc_with_descr
()
is similar to extent_alloc
() but allows the caller
to provide a pre-allocated region descriptor instead of having the function
allocate one. This function can only be used with extents that have the
EX_NOCOALESCE
property.
extent_alloc_subregion
()
and
extent_alloc_subregion_with_descr
()
are generalized versions of extent_alloc
() and
extent_alloc_with_descr
() that allow the caller to
specify that the allocated region must fall within the subregion from
substart to subend
inclusive.
extent_alloc_region
()
allocates the specific region in the extent map ex
beginning at start with the size
size. If the caller specifies the
EX_CONFLICTOK
flag, the allocation will succeed even
if part of the requested region has already been allocated. The caller may
specify that it is okay to wait for the indicated region to be free by
setting the flag EX_WAITSPACE
. If neither
EX_WAITSPACE
nor
EX_CONFLICTOK
is set, the allocation will fail if
the request cannot be satisfied without sleeping.
extent_alloc_region_with_descr
()
is similar to extent_alloc_region
() but allows the
caller to provide a pre-allocated region descriptor instead of having the
function allocate one. This function can only be used with extents that have
the EX_NOCOALESCE
property.
extent_free
()
frees a region of size bytes starting at
start in the extent map ex. If
the extent has the EX_NOCOALESCE
property, only
entire regions may be freed. If the extent has the
EX_NOCOALESCE
property and the caller attempts to
free a partial region, behavior is undefined. If called on an extent without
the EX_NOCOALESCE
property, this function can fail
with error codes listed below, otherwise this function will always
succeed.
extent_print
()
Prints out information about extent ex. This function
always succeeds.
RETURN VALUES
The behavior of all extent manager functions is undefined if given
invalid arguments. extent_create
() returns the
extent map on success, or NULL
if it fails to
allocate storage for the extent map. It always succeeds when creating a
fixed extent or when given the flag EX_WAITOK
.
extent_alloc
(),
extent_alloc_region
(),
extent_alloc_subregion
(), and
extent_free
() return one of the following
values:
0
- Operation was successful.
ENOMEM
- If
EX_NOWAIT
is specified, the extent manager was not able to allocate a region descriptor for the new region or to split a region when freeing a partial region. EAGAIN
- Requested region is not available and
EX_WAITSPACE
was not specified. EINTR
- Process received a signal while waiting for the requested region to become available in the extent.
EXAMPLES
Here is an example of a (useless) function that uses several of the extent manager routines.
void func() { struct extent *foo_ex; u_long region_start; int error; /* * Extent "foo" manages a 256k region starting at 0x0 and * only allows complete regions to be freed so that * extent_free() never needs to allocate memory. */ foo_ex = extent_create("foo", 0x0, 0x3ffff, M_DEVBUF, NULL, 0, EX_WAITOK | EX_NOCOALESCE); /* * Allocate an 8k region, aligned to a 4k boundary, which * does not cross any of the 3 64k boundaries (at 64k, * 128k, and 192k) within the extent. */ error = extent_alloc(foo_ex, 0x2000, 0x1000, 0x10000, EX_NOWAIT, ®ion_start); if (error) panic("you lose"); /* * Give up the extent. */ extent_destroy(foo_ex); }
CODE REFERENCES
The extent manager itself is implemented within the file sys/kern/subr_extent.c.
The i386 bus management code uses the extent manager for managing I/O ports and I/O memory. See sys/arch/i386/i386/machdep.c.
SEE ALSO
HISTORY
The extent manager appeared in NetBSD 1.3.
AUTHORS
The extent manager was designed and implemented by Jason R. Thorpe <thorpej@NetBSD.ORG>. Matthias Drochner <drochner@zelux6.zel.kfa-juelich.de> contributed to the initial testing and optimization of the implementation. Chris Demetriou <cgd@NetBSD.ORG> contributed many architectural suggestions.