RMAN(9)
π RMAN(9) π
okay bestie, buckle up β this is the resource management functions page from the Kernel Developer's Manual, and it's genuinely one of the most important little corners of the kernel. iykyk π
β¨ NAME β¨
rman, rman_activate_resource, rman_adjust_resource, rman_deactivate_resource, rman_fini, rman_init, rman_init_from_resource, rman_is_region_manager, rman_manage_region, rman_first_free_region, rman_last_free_region, rman_release_resource, rman_reserve_resource, rman_make_alignment_flags, rman_get_start, rman_get_end, rman_get_device, rman_get_size, rman_get_flags, rman_set_mapping, rman_get_mapping, rman_set_virtual, rman_get_virtual, rman_set_bustag, rman_get_bustag, rman_set_bushandle, rman_get_bushandle, rman_set_rid, rman_get_rid, rman_set_type, rman_get_type β resource management functions
likeβ¦ that's the whole squad. the entire friend group. π«Ά
πΈ SYNOPSIS πΈ
#include <sys/types.h>
#include <sys/rman.h>
int
rman_activate_resource(struct resource *r);
int
rman_adjust_resource(struct resource *r, rman_res_t start,
rman_res_t end);
int
rman_deactivate_resource(struct resource *r);
int
rman_fini(struct rman *rm);
int
rman_init(struct rman *rm);
int
rman_init_from_resource(struct rman *rm, struct resource *r);
int
rman_is_region_manager(struct resource *r, struct rman *rm);
int
rman_manage_region(struct rman *rm, rman_res_t start, rman_res_t end);
int
rman_first_free_region(struct rman *rm, rman_res_t *start,
rman_res_t *end);
int
rman_last_free_region(struct rman *rm, rman_res_t *start,
rman_res_t *end);
int
rman_release_resource(struct resource *r);
struct resource *
rman_reserve_resource(struct rman *rm, rman_res_t start, rman_res_t end,
rman_res_t count, u_int flags, device_t dev);
uint32_t
rman_make_alignment_flags(uint32_t size);
rman_res_t
rman_get_start(struct resource *r);
rman_res_t
rman_get_end(struct resource *r);
device_t
rman_get_device(struct resource *r);
rman_res_t
rman_get_size(struct resource *r);
u_int
rman_get_flags(struct resource *r);
void
rman_set_mapping(struct resource *r, struct resource_map *map);
void
rman_get_mapping(struct resource *r, struct resource_map *map);
void
rman_set_virtual(struct resource *r, void *v);
void *
rman_get_virtual(struct resource *r);
void
rman_set_bustag(struct resource *r, bus_space_tag_t t);
bus_space_tag_t
rman_get_bustag(struct resource *r);
void
rman_set_bushandle(struct resource *r, bus_space_handle_t h);
bus_space_handle_t
rman_get_bushandle(struct resource *r);
void
rman_set_rid(struct resource *r, int rid);
int
rman_get_rid(struct resource *r);
void
rman_set_type(struct resource *r, int type);
int
rman_get_type(struct resource *r);
π DESCRIPTION π
so the rman functions are this flexible resource management abstraction, right? they're used extensively by the bus management code β like, main character energy in the bus world. π
it implements two big concepts: region and resource.
- a region descriptor manages a region. that region could be memory, or some other form of bus space. π«
- each region has a set of bounds, and within those bounds, allocated segments may reside.
- each segment β which we call a resource β has several properties, and those live in a 16-bit flag register, like this:
#define RF_ALLOCATED 0x0001 /* resource has been reserved */
#define RF_ACTIVE 0x0002 /* resource allocation has been activated */
#define RF_SHAREABLE 0x0004 /* resource permits contemporaneous sharing */
#define RF_FIRSTSHARE 0x0020 /* first in sharing list */
#define RF_PREFETCHABLE 0x0040 /* resource is prefetchable */
#define RF_UNMAPPED 0x0100 /* don't map resource when activating */
and bestie, listen: bits 15:10 of the flag register are the ones representing the desired alignment of the resource within the region. don't forget those. π
π¦ the setup + teardown girlies π¦
rman_init(struct rman *rm)β initializes the region descriptor pointed to by the rm argument so it's ready for the resource management functions. okay but like, it has requirements: the fieldsrm_typeandrm_descrofstruct rmanmust be set before you callrman_init().rm_typeshall be set toRMAN_ARRAY.rm_descrshall be set to a string that describes the resource being managed. therm_startandrm_endfields may be set to limit the range of acceptable resource addresses β and if you don't set them,rman_init()will initialize them to allow the entire range of resource addresses. it also initializes any mutexes associated with the structure. if it fails to initialize the mutex, it returnsENOMEM; otherwise it returns0and rm is initialized. slay. β¨rman_fini(struct rman *rm)β frees any structures associated with the structure pointed to by rm. but here's the vibe check: if any of the resources within the managed region have theRF_ALLOCATEDflag set, it returnsEBUSYπ€. otherwise, any mutexes associated with the structure are released and destroyed, and the function returns0.rman_manage_region(struct rman *rm, rman_res_t start, rman_res_t end)β establishes the concept of a region that's under rman control. rm points to the region descriptor, and start and end specify the bounds of the region. if it succeeds, you get0. if the region overlaps with an existing region,EBUSY. if any part of the region falls outside the valid address range for rm,EINVAL. andENOMEMshows up when it failed to allocate memory for the region. πrman_init_from_resource(struct rman *rm, struct resource *r)β a lil wrapper routine that creates a resource manager backed by an existing resource. it initializes rm usingrman_init()and then adds a region to rm corresponding to the address range allocated to r, viarman_manage_region(). cute, efficient, we love her. π«Ά
π the query + reserve girlies π
rman_first_free_region(struct rman *rm, rman_res_t *start, rman_res_t *end)andrman_last_free_region(struct rman *rm, rman_res_t *start, rman_res_t *end)β you use these to query a resource manager for its first (or last) unallocated region. if rm contains no free region, they returnENOENT. otherwise*startand*endget set to the bounds of the free region and zero is returned. periodt. πrman_reserve_resource(struct rman *rm, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags, device_t dev)β okay THIS is where the bulk of the rman logic lives, it's the whole main character. it attempts to reserve a contiguous range in the specified region rm for the use of the device dev. the caller can specify the start and end of an acceptable range, plus the required alignment, and the code will attempt to find a free segment that fits. π«- start is the lowest acceptable starting value of the resource.
- end is the highest acceptable ending value of the resource.
- therefore,
start + count - 1must be β€endfor any allocation to happen. no exceptions bestie, that's just math. - the alignment requirement (if any) is specified in flags. often the
RF_ALIGNMENT_LOG2macro is used to specify alignment to a power-of-2 size, orrman_make_alignment_flags()can be used to compute the flags value at runtime. - a shared segment gets allocated if the
RF_SHAREABLEflag is set; otherwise an exclusive segment is allocated. - and if that shared segment already exists, the caller has its device added to the list of consumers. sharing is caring π
rman_make_alignment_flags(uint32_t size)β returns the flag mask corresponding to the desired alignment size. this should be used when callingrman_reserve_resource_bound(). π₯rman_is_region_manager(struct resource *r, struct rman *rm)β returns true if the allocated resource r was allocated from rm. otherwise returns false. simple as. βrman_adjust_resource(struct resource *r, rman_res_t start, rman_res_t end)β used to adjust the reserved address range of an allocated resource so it reserves start through end. it can grow or shrink one or both ends of the resource range. lowkey powerful, highkey picky:- the current implementation does not support entirely relocating the resource, and will fail with
EINVALif the new resource range does not overlap the old resource range. - if either end of the resource range grows and the new range would conflict with another allocated resource, it fails with
EBUSY. - it does not support adjusting the resource range for shared resources β those attempts fail with
EINVAL. - upon success, the resource r will have a start address of start and an end address of end, and the function returns zero.
- the current implementation does not support entirely relocating the resource, and will fail with
ngl bestie, this is important: none of the constraints of the original allocation request β things like alignment or boundary restrictions β are checked by rman_adjust_resource(). it is the caller's responsibility to enforce any such requirements. π don't come for her when you didn't do your homework.
rman_release_resource(struct resource *r)β releases the reserved resource r. it may attempt to merge adjacent free resources. tidy β¨
π activation era π
rman_activate_resource(struct resource *r)β marks a resource as active by setting theRF_ACTIVEflag. but if this is a time shared resource, and the caller has not yet acquired the resource, the function returnsEBUSY. πrman_deactivate_resource(struct resource *r)β marks a resource r as inactive by clearing theRF_ACTIVEflag. and if other consumers are waiting for this range, it will wakeup their threads. so considerate π
π getters, setters & the little details π
rman_get_start(),rman_get_end(),rman_get_size(), andrman_get_flags()β return the bounds, size, and flags of the previously reserved resource r. πrman_set_bustag()β associates abus_space_tag_tt with the resource r.rman_get_bustag()retrieves this tag once it's set. π§rman_set_bushandle()β associates abus_space_handle_th with the resource r.rman_get_bushandle()retrieves this handle once it's set. β¨rman_set_virtual()β used to associate a kernel virtual address with a resource r.rman_get_virtual()retrieves the KVA once it's set. πΈrman_set_mapping()β used to associate a resource mapping with a resource r. heads up though: the mapping must cover the entire resource. setting a mapping sets the associatedbus_space(9)handle and tag for r as well as the kernel virtual address, if the mapping contains one. those individual values can be retrieved viarman_get_bushandle(),rman_get_bustag(), andrman_get_virtual(). π«rman_get_mapping()β retrieves the associated resource mapping once it's set. π¦rman_set_rid()β associates a resource identifier with a resource r.rman_get_rid()retrieves this RID. πrman_set_type()β associates a resource type with a resource r.rman_get_type()retrieves this type. πΊrman_get_device()β returns a pointer to the device which reserved the resource r. literally her whole job, and she does it flawlessly. π
π₯ SEE ALSO π₯
bus_activate_resource(9), bus_adjust_resource(9), bus_alloc_resource(9), bus_map_resource(9), bus_release_resource(9), bus_set_resource(9), bus_space(9), mutex(9)
go read them, they're the supporting cast and they ate π
π AUTHORS π
This manual page was written by Bruce M Simpson <bms@spc.org>. king behavior honestly πβ¨
okay that's the whole page, you're officially educated, go forth and manage your resources bestie π¦π
Debian Β· March 13, 2024 Β· RMAN(9) β that's the vibe check, and it passed with flying colors ππ
π¦ where this page comes from
- freebsd 15.1: base 15.1
- nixpkgs unstable: source
- Copyright (c) 2003 Bruce M Simpson <bms@spc.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms