struct
extent
*
extent_create(
char *name
, u_long start
, u_long end
, int mtype
, void *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 boundary
, int flags
, u_long *result
)
int
extent_alloc_subregion(
struct extent *ex
, u_long substart
, u_long subend
, u_long size
, u_long alignment
, u_long boundary
, u_long flags
, u_long *result
)
int
extent_alloc1(
struct extent *ex
, u_long size
, u_long alignment
, u_long skew
, u_long boundary
, int flags
, u_long *result
)
int
extent_alloc_subregion1(
struct extent *ex
u_long substart
u_long subend
u_long size
u_long alignment
u_long skew
u_long boundary
u_long flags
u_long *result
)
int
extent_alloc_region(
struct extent *ex
, u_long start
, u_long size
, int flags
)
int
extent_free(
struct extent *ex
, u_long start
, u_long size
, int flags
)
void
extent_print(
struct extent *ex
)
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 an error.
If the flag
EX_NOCOALESCE
is specified, only entire regions may be freed within the extent map,
but internal coalescing of regions is disabled so that
extent_free()
will never have to allocate a region descriptor and therefore will
never fail.
The caller must specify one of the flags
EX_NOWAIT
or
EX_WAITOK
,
specifying whether it is okay to wait for memory allocated for
extent map overhead.
There are some applications which 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
fixedextent.
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 allocation requests to indicate that a fixed extent
map may be extended using a call to
malloc().
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 extent
ex
of size
size
that fits the provided parameters.
There are two distinct allocation policies, which are selected by the
flags
argument:
EX_FAST
The caller must specify if waiting for space in the extent is allowed
using the flag
EX_WAITSPACE
.
If
EX_WAITSPACE
is not specified, the allocation will fail if the request can not be
satisfied without sleeping.
The caller must also specify, using the
EX_NOWAIT
or
EX_WAITOK
flags, if waiting for overhead allocation is allowed.
The request will be aligned to
alignment
boundaries.
Alignment values must be a power of 2.
If no alignment is necessary, the value 1 should be specified.
If
boundary
is nonzero, the allocated region will not cross any of the numbers
which are a multiple of
boundary
.
If the caller specifies the
EX_BOUNDZERO
flag, the boundary lines begin at zero.
Otherwise, the boundary lines begin at the beginning of the extent.
The allocated region may begin on a boundary address, but the end of
the region will not touch nor cross it.
A boundary argument smaller than the size of the request is invalid.
Upon successful completion,
*result
will contain the start of the allocated region.
extent_alloc_subregion()
is similar to
extent_alloc(
),
but it allows the caller to specify that the allocated region must
fall within the subregion from
substart
to
subend
inclusive.
The other arguments and the return values of
extent_alloc_subregion()
are otherwise the same as those of
extent_alloc(
).
extent_alloc_region()
allocates the specific region in the extent map
ex
beginning at
start
with the size
size
.
The caller must specify whether it is okay to wait for the indicated
region to be free using the flag
EX_WAITSPACE
.
If
EX_WAITSPACE
is not specified, the allocation will fail if the request can not be
satisfied without sleeping.
The caller must also specify, using the
EX_NOWAIT
or
EX_WAITOK
flags, if waiting for overhead allocation is allowed.
The
extent_alloc1()
and
extent_alloc_subregion1(
)
functions are extensions that take one additional argument,
skew
,
that 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
.
Also, a boundary argument smaller than the sum of the requested skew
and the size of the request is invalid.
extent_free()
frees a region of
size
bytes in extent
ex
starting at
start
.
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.
The caller must specify one of the flags
EX_NOWAIT
or
EX_WAITOK
to specify whether waiting for memory is okay; these flags have
meaning in the event that allocation of a region descriptor is
required during the freeing process.
This situation occurs only when a partial region that begins and ends
in the middle of another region is freed.
Behavior is undefined if invalid arguments are provided.
extent_print()
Print out information about extent
ex
.
This function always succeeds.
Behavior is undefined if invalid arguments are provided.
)
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
ENOMEM
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
EX_WAITSPACE
was not specified.
EINTR
).
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);
}
/usr/src
.
The extent manager itself is implemented within the file
sys/kern/subr_extent.c
.
Function prototypes for the framework are located in
sys/sys/extent.h
.
The i386 bus management code uses the extent manager for managing I/O
ports and I/O memory.
This code is in the file
sys/arch/i386/i386/machdep.c
.