class RegionAllocator

Defined at line 137 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

RegionAllocator

== Overview ==

A RegionAllocator is a utility class designed to help with the bookkeeping

involved in managing the allocation/partitioning of a 64-bit space into

non-overlapping "Regions". In addition to the RegionAllocator, there are two

other classes involved in the use of a RegionAllcator;

RegionAllocator::Region and RegionAllocator::RegionPool.

A Region consists of an unsigned 64-bit base address and an unsigned 64-bit

size. A Region is considered valid iff its size is non-zero, and it does not

wrap its 64-bit space.

See the "Memory Allocation" section for a discussion of the RegionPool.

RegionAllocator users can create an allocator and then add any number of

non-overlapping Regions to its pool of regions available for allocation.

They may then request that regions be allocated from the pool either by

requesting that a region be allocated with a particular size/alignment, or

by asking for a specific base/size. The RegionAllocator will manage all of

the bookkeeping involved in breaking available regions into smaller chunks,

tracking allocated regions, and re-merging regions when they are returned to

the allocator.

== Memory Allocaion ==

RegionAllocators require dynamically allocated memory in order to store the

bookkeeping required for managing available regions. In order to control

heap fragmentation and the frequency of heap interaction, A RegionPool object

may be used to allocate bookkeeping overhead in larger slabs which are carved up

and placed on a free list to be used by a RegionAllocator. RegionPools are

created with a defined slab size as well as a maximum memory limit. The pool

will initially allocate a single slab, but will attempt to grow any time

bookkeeping is needed but the free list is empty and the allocation of

another slab would not push the allocator over its maximum memory limit.

RegionPools are ref-counted objects that may be shared by multiple

RegionAllocators. This allows sub-systems which use multiple allocators to

impose system-wide limits on bookkeeping overhead. If a RegionPool allocator

is to be used, it must be assigned to the RegionAllocator before any regions

can be added or allocated, and the pool may not be re-assigned while the

allocator is using any bookkeeping from the pool.

== APIs and Object lifecycle management ==

The API makes use of fbl managed pointer types in order to simplify lifecycle

management. RegionPools are managed with fbl::RefPtr while Regions are handed

out via std::unique_ptr. RegionAllocators themselves impose no lifecycle

restrictions and may be heap allocated, stack allocated, or embedded directly

in objects as the user sees fit. It is an error to allow a RegionAllocator

to destruct while there are allocations in flight.

== Dependencies ==

The RegionAllocator depends only on malloc/free and fbl. new/delete

implementations are provided internally, no global new/delete behavior needs

to be defined by the user.

== Thread Safety ==

RegionAllocator and RegionPools use fbl::Mutex objects to provide thread

safety in multi-threaded environments. As such, RegionAllocators are not

currently suitable for use in code which may run at IRQ context, or which

must never block.

Each RegionAllocator has its own mutex allowing for concurrent access across

multiple allocators, even when the allocators share the same RegionPool.

RegionPools also hold their own mutex which may be obtained by an Allocator

while holding the Allocator's Mutex.

== Simple Usage Example ==

/* Create a pool and assign it to a stack allocated allocator. Limit the

* bookkeeping memory to 32KB allocated from a single slab. This will ensure

* that no heap interactions take place after startup (during operation).

*/

RegionAllocator alloc(

RegionAllocator::RegionPool::Create(32

<

<

10, 32

<

<

10));

/* Add regions to the pool which can be allocated from */

alloc.AddRegion({ .base = 0xC0000000, .size = 0x40000000 }); // [3GB, 4GB)

alloc.AddRegion({ .base = 0x4000000000, .size = 0x40000000 }); // [256GB, 257GB)

/* Grab some specific regions out of the available regions.

* Note: auto here will expand to RegionAllocator::Region::UPtr. Feel free

* to add your own using statement to lessen the C++ naming pain.

*/

auto r1 = alloc.GetRegion({ 0xC0100000, 0x100000 }); // [3GB + 1MB, 3GB + 2MB)

auto r2 = alloc.GetRegion({ 0x4000100000, 0x100000 }); // [256GB + 1MB, 256GB + 2MB)

/* Grab some pointer aligned regions of various sizes */

auto r3 = alloc.GetRegion(1024);

auto r4 = alloc.GetRegion(75);

auto r5 = alloc.GetRegion(80000);

/* Grab some page aligned regions of various sizes */

auto r6 = alloc.GetRegion(1024, 4

<

<

10);

auto r7 = alloc.GetRegion(75, 4

<

<

10);

auto r8 = alloc.GetRegion(80000, 4

<

<

10);

/* Print some stuff about some of the allocations */

ZX_DEBUG_ASSERT(r3 != nullptr);

printf("R3 base %llx size %llx\n", r3->base, r3->size)

ZX_DEBUG_ASSERT(r8 != nullptr);

printf("R8 base %llx size %llx\n", r8->base, r8->size)

/* No need to clean up. Regions will automatically be returned to the

* allocator as they go out of scope. Then the allocator will return all of

* its available regions to the pool when it goes out of scope. Finally, the

* pool will free all of its memory as the allocator releases it reference

* to the pool.

*/

Public Members

static const uint64_t kRegionPoolSlabSize

Public Methods

void ~RegionAllocator ()

Defined at line 30 of file ../../zircon/system/ulib/region-alloc/region-alloc.cc

zx_status_t SetRegionPool (const RegionPool::RefPtr & region_pool)

Set the RegionPool this RegionAllocator will obtain bookkeeping structures from.

Possible return values

++ ZX_ERR_BAD_STATE : The RegionAllocator already has bookkeeping

allocations. All allocated regions must be returned to the pool and the

pool Reset before the allocator may be changed.

Defined at line 58 of file ../../zircon/system/ulib/region-alloc/region-alloc.cc

void Reset ()

Reset allocator. Releases all available regions, but has no effect on

currently allocated regions.

Defined at line 45 of file ../../zircon/system/ulib/region-alloc/region-alloc.cc

zx_status_t AddRegion (const ralloc_region_t & region, AllowOverlap allow_overlap)

Add a region to the set of allocatable regions.

If allow_overlap is AllowOverlap::No, the added region may not overlap with

any previously added region and will be rejected if it does. If

allow_overlap is AllowOverlap::Yes, the added region will be union'ed with

existing available regions, provided it does not intersect any currently

allocated region.

Possible return values

++ ZX_ERR_NO_MEMORY : not enough bookkeeping memory available in our

assigned region pool to add the region.

++ ZX_ERR_INVALID_ARGS : One of the following conditions applies.

++++ The region is invalid (wraps the space, or size is zero)

++++ The region being added intersects one or more currently

allocated regions.

++++ The region being added intersects one ore more of the currently

available regions, and allow_overlap is false.

Defined at line 69 of file ../../zircon/system/ulib/region-alloc/region-alloc.cc

zx_status_t SubtractRegion (const ralloc_region_t & region, AllowIncomplete allow_incomplete)

Subtract a region from the set of allocatable regions.

If allow_incomplete is false, the subtracted region must exist entirely

within the set of available regions. If allow_incomplete is true, the

subtracted region will remove any portion of any available region it

intersects with.

Regardless of the value of the allow_incomplete flag, it is illegal to

attempt to subtract a region which intersects any currently allocated

region.

Possible return values

++ ZX_ERR_NO_MEMORY : not enough bookkeeping memory available in our

assigned region pool to subtract the region.

++ ZX_ERR_INVALID_ARGS : One of the following conditions applies.

++++ The region is invalid (wraps the space, or size is zero)

++++ The region being subtracted intersects one or more currently

allocated regions.

++++ The region being subtracted intersects portions of the space which

are absent from both the allocated and available sets, and

allow_incomplete is false.

Defined at line 100 of file ../../zircon/system/ulib/region-alloc/region-alloc.cc

void RegionAllocator ()

Defined at line 272 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

void RegionAllocator (const RegionPool::RefPtr & region_pool)

Defined at line 273 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

void RegionAllocator (RegionPool::RefPtr && region_pool)

Defined at line 274 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

void RegionAllocator (const RegionAllocator & c)

Defined at line 276 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

RegionAllocator & operator= (const RegionAllocator & c)

Defined at line 277 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

zx_status_t GetRegion (uint64_t size, uint64_t alignment, Region::UPtr & out_region)

Get a region out of the set of currently available regions which has a

specified size and alignment. Note; the alignment must be a power of

two. Pass 1 if alignment does not matter.

Possible return values

++ ZX_ERR_NO_MEMORY : not enough bookkeeping memory available in our

assigned region pool to perform the allocation.

++ ZX_ERR_INVALID_ARGS : size is zero, or alignment is not a power of two.

++ ZX_ERR_NOT_FOUND : No suitable region could be found in the set of

currently available regions which can satisfy the request.

Defined at line 282 of file ../../zircon/system/ulib/region-alloc/region-alloc.cc

zx_status_t GetRegion (uint64_t size, uint64_t alignment, Region::UPtr & out_region)

Get a region out of the set of currently available regions which has a

specified size and alignment. Note; the alignment must be a power of

two. Pass 1 if alignment does not matter.

Possible return values

++ ZX_ERR_NO_MEMORY : not enough bookkeeping memory available in our

assigned region pool to perform the allocation.

++ ZX_ERR_INVALID_ARGS : size is zero, or alignment is not a power of two.

++ ZX_ERR_NOT_FOUND : No suitable region could be found in the set of

currently available regions which can satisfy the request.

Defined at line 282 of file ../../zircon/system/ulib/region-alloc/region-alloc.cc

zx_status_t SetRegionPool (RegionPool::RefPtr && region_pool)

Defined at line 288 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

bool HasRegionPool ()

Defined at line 293 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

zx_status_t GetRegion (const ralloc_region_t & requested_region, Region::UPtr & out_region)

Get a region with a specific location and size out of the set of

currently available regions.

Possible return values

++ ZX_ERR_NO_MEMORY : not enough bookkeeping memory available in our

assigned region pool to perform the allocation.

++ ZX_ERR_INVALID_ARGS : The size of the requested region is zero.

++ ZX_ERR_NOT_FOUND : No suitable region could be found in the set of

currently available regions which can satisfy the request.

Defined at line 328 of file ../../zircon/system/ulib/region-alloc/region-alloc.cc

zx_status_t GetRegion (const ralloc_region_t & requested_region, Region::UPtr & out_region)

Get a region with a specific location and size out of the set of

currently available regions.

Possible return values

++ ZX_ERR_NO_MEMORY : not enough bookkeeping memory available in our

assigned region pool to perform the allocation.

++ ZX_ERR_INVALID_ARGS : The size of the requested region is zero.

++ ZX_ERR_NOT_FOUND : No suitable region could be found in the set of

currently available regions which can satisfy the request.

Defined at line 328 of file ../../zircon/system/ulib/region-alloc/region-alloc.cc

zx_status_t GetRegion (uint64_t size, Region::UPtr & out_region)

Helper which defaults the alignment of a size/alignment based allocation

to pointer-aligned.

Defined at line 374 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

zx_status_t GetRegion (uint64_t size, Region::UPtr & out_region)

Helper which defaults the alignment of a size/alignment based allocation

to pointer-aligned.

Defined at line 374 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

Region::UPtr GetRegion (uint64_t size, uint64_t alignment)

Helper versions of the GetRegion methods for those who don't care

about the specific reason for failure (nullptr will be returned on

failure).

Defined at line 381 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

Region::UPtr GetRegion (uint64_t size)

Defined at line 387 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

Region::UPtr GetRegion (const ralloc_region_t & requested_region)

Defined at line 393 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

bool TestRegionIntersects (const ralloc_region_t & region, TestRegionSet which)

Returns true if |region| intersects any of the regions in either the set of

currently allocated regions, or currently available regions.

region : The region to test

which : Either TestRegionSet::Allocated or TestRegionSet::Available to

test against the set of currently allocated or currently available

regions.

Defined at line 406 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

bool TestRegionContainedBy (const ralloc_region_t & region, TestRegionSet which)

Returns true if |region| is completely contained by any of the regions in

either the set of currently allocated regions, or currently available

regions.

region : The region to test

which : Either TestRegionSet::Allocated or TestRegionSet::Available to

test against the set of currently allocated or currently available

regions.

Defined at line 421 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

size_t AllocatedRegionCount ()

Defined at line 428 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

size_t AvailableRegionCount ()

Defined at line 433 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

template <typename WalkCallback>
void WalkAllocatedRegions (WalkCallback && cb)

Walk the allocated regions and call the user provided callback for each

entry. Stop when out of entries or the callback returns false.

*** It is absolutely required that the user callback not call into any other

RegionAllocator public APIs, and should likely not acquire any locks of any

kind. This method cannot protect against deadlocks and lock inversions that

are possible by acquiring the allocation lock before calling the user provided

callback.

Defined at line 447 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

template <typename WalkCallback>
void WalkAvailableRegions (WalkCallback && cb)

Walk the available regions and call the user provided callback for each

entry. Stop when out of entries or the callback returns false.

*** It is absolutely required that the user callback not call into any other

RegionAllocator public APIs, and should likely not acquire any locks of any

kind. This method cannot protect against deadlocks and lock inversions that

are possible by acquiring the allocation lock before calling the user provided

callback.

Defined at line 465 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

Enumerations

enum TestRegionSet
Name Value
Allocated 0
Available 1

An enum which selects which set of regions to test against when testing for

intersection or containment. See TestRegionIntersect and

TestRegionContains for examples.

Defined at line 150 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

enum AllowOverlap
Name Value
No 0
Yes 1

Enums which act as strongly typed bools and are used to control the

behavior of AddRegion and SubtractRegion.

Defined at line 157 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

enum AllowIncomplete
Name Value
No 0
Yes 1

Defined at line 162 of file ../../zircon/system/ulib/region-alloc/include/region-alloc/region-alloc.h

Records