extent_create, extent_destroy, extent_alloc,
extent_alloc_region, extent_free, extent_print - general
struct extent *
extent_create(char *name, u_long start, u_long end, int
caddr_t storage, size_t storagesize, int flags);
extent_destroy(struct extent *ex);
extent_alloc(struct extent *ex, u_long size, u_long
u_long skew, u_long boundary, int flags, u_long
extent_alloc_subregion(struct extent *ex, u_long substart,
u_long size, u_long alignment, u_long skew, u_long
int flags, u_long *result);
extent_alloc_region(struct extent *ex, u_long start, u_long
extent_free(struct extent *ex, u_long start, u_long size,
extent_print(struct extent *ex);
The extent manager provides management of areas of memory or
spaces (such as I/O ports). An opaque structure
called an extent
map keeps track of allocated regions within the enumerable
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
in case of errors or in ddb(4) show extents. If the
EX_NOCOALESCE is set, internal coalescing of regions is disabled, and only
entire regions may be freed within the extent map, so
extent_free() will never have to allocate a region descriptor.
Some applications may want to use an extent map but can't
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
enough storage for them; alternatively, the flag EX_MALLOCOK
passed to extent requests to indicate that a fixed extent
map may be extended
using a call to malloc().
The caller should pass the flag EX_WAITOK or EX_NOWAIT to
that have a memory overhead, to specify whether it is
okay to wait.
These functions are extent_create() (non fixed extents),
(unless EX_NOCOALESCE is set), extent_alloc(),
extent_destroy() destroys the extent map ex, freeing all allocated regions.
If the extent is not a fixed extent, the region and
descriptors themselves are freed. This function always
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
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
in the extent by setting the flag EX_WAITSPACE. If EX_WAITSPACE is not
set, the allocation will fail if the request can not be satisfied without
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
should be specified. If skew is non-zero, it modifies the
alignment result in the following way: the value (result -
aligned to alignment boundaries. skew must be a smaller
alignment. If boundary is not EX_NOBOUNDARY, the allocated
not cross any boundary lines, spaced boundary apart. If the
the EX_BOUNDZERO flag, boundary lines begin at zero.
boundary lines begin at the beginning of the extent. The
may begin on a boundary line, but the end of the region
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
extent_alloc_subregion() is a generalized version of
also allows the caller to specify that the allocated region
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. The caller may specify that it is
okay to wait for the indicated region to be free by setting
EX_WAITSPACE. If EX_WAITSPACE is not set, the allocation
will fail if
the request can not be satisfied without sleeping.
extent_free() frees a region of size bytes starting at start
in the extent
map ex. If the extent has the EX_NOCOALESCE property,
regions may be freed. If the extent has the EX_NOCOALESCE
the caller attempts to free a partial region, behavior is
called on an extent without the EX_NOCOALESCE property, this
fail with error codes listed below, otherwise this function
extent_print() Prints out information about extent ex. This
The behavior of all extent manager functions is undefined if
arguments. extent_create() returns the extent map on
NULL if it fails to allocate storage for the extent map. It
when creating a fixed extent or when given the flag
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
or to split a region when freeing a partial
EAGAIN Requested region is not available and
EINTR Process received a signal while waiting for
region to become available in the extent.
Here is an example of a (useless) function that uses several
of the extent
struct extent *foo_ex;
* Extent "foo" manages a 256k region starting at
* 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,
* does not cross any of the 3 64k boundaries (at
* 128k, and 192k) within the extent.
error = extent_alloc(foo_ex, 0x2000, 0x1000,
* Give up the extent.
The extent manager itself is implemented within the file
The i386 bus management code uses the extent manager for
ports and I/O memory. See sys/arch/i386/i386/machdep.c.
The extent manager appeared in NetBSD 1.3.
The extent manager was designed and implemented by Jason R.
Matthias Drochner <firstname.lastname@example.org> contributed to the
initial testing and optimization of the implementation.
Chris Demetriou <cgd@NetBSD.ORG> contributed many architectural suggestions.
OpenBSD 3.6 September 23, 1996
[ Back ]