Updated: 2022/Sep/29

Please read Privacy Policy. It's for your privacy.


EXTENT(9)                  Kernel Developer's Manual                 EXTENT(9)

NAME
     extent, extent_create, extent_destroy, extent_alloc,
     extent_alloc_subregion, extent_alloc1, extent_alloc_subregion1,
     extent_alloc_region, 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, 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);

DESCRIPTION
     The NetBSD extent manager provides management of areas of memory or other
     number spaces (such as I/O ports).  An opaque structure called an extent
     map keeps track of allocated regions within the number space.

     extent_create() creates an extent map managing the space from start to
     end inclusive.  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 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 allocation requests to indicate that a fixed
     extent map may be extended using a call to malloc().

     If the flag EX_EARLY is specified, no mutex(9) calls are made in the
     expectation that mutual exclusion is not available or required.

     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    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 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.

LOCKING
     The extent manager performs all necessary locking (unless EX_EARLY is
     specified) on the extent map itself, and any other data structures
     internal to the extent manager.  The locks used by the extent manager are
     simplelocks, and will never sleep (see lock(9)).  This should be taken
     into account when designing the locking protocol for users of the extent
     manager.

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.  Does not apply
                     to extent_free().

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, &region_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.  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.

SEE ALSO
     malloc(9)

HISTORY
     The NetBSD extent manager appeared in NetBSD 1.3.

AUTHORS
     The NetBSD extent manager was architected 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.

NetBSD 10.99                    August 28, 2017                   NetBSD 10.99