The genalloc/genpool subsystem¶
There are a number of memory-allocation subsystems in the kernel, eachaimed at a specific need. Sometimes, however, a kernel developer needs toimplement a new allocator for a specific range of special-purpose memory;often that memory is located on a device somewhere. The author of thedriver for that device can certainly write a little allocator to get thejob done, but that is the way to fill the kernel with dozens of poorlytested allocators. Back in 2005, Jes Sorensen lifted one of thoseallocators from the sym53c8xx_2 driver andposted it as a generic modulefor the creation of ad hoc memory allocators. This code was mergedfor the 2.6.13 release; it has been modified considerably since then.
Code using this allocator should include <linux/genalloc.h>. The actionbegins with the creation of a pool using one of:
- structgen_pool*gen_pool_create(intmin_alloc_order,intnid)¶
create a new special memory pool
Parameters
intmin_alloc_orderlog base 2 of number of bytes each bitmap bit represents
intnidnode id of the node the pool structure should be allocated on, or -1
Description
Create a new special memory pool that can be used to manage special purposememory not managed by the regular kmalloc/kfree interface.
- structgen_pool*devm_gen_pool_create(structdevice*dev,intmin_alloc_order,intnid,constchar*name)¶
managed gen_pool_create
Parameters
structdevice*devdevice that provides the gen_pool
intmin_alloc_orderlog base 2 of number of bytes each bitmap bit represents
intnidnode selector for allocated gen_pool,
NUMA_NO_NODEfor all nodesconstchar*namename of a gen_pool or NULL, identifies a particular gen_pool on device
Description
Create a new special memory pool that can be used to manage special purposememory not managed by the regular kmalloc/kfree interface. The pool will beautomatically destroyed by the device management code.
A call togen_pool_create() will create a pool. The granularity ofallocations is set with min_alloc_order; it is a log-base-2 number likethose used by the page allocator, but it refers to bytes rather than pages.So, if min_alloc_order is passed as 3, then all allocations will be amultiple of eight bytes. Increasing min_alloc_order decreases the memoryrequired to track the memory in the pool. The nid parameter specifieswhich NUMA node should be used for the allocation of the housekeepingstructures; it can be -1 if the caller doesn’t care.
The “managed” interfacedevm_gen_pool_create() ties the pool to aspecific device. Among other things, it will automatically clean up thepool when the given device is destroyed.
A pool is shut down with:
- voidgen_pool_destroy(structgen_pool*pool)¶
destroy a special memory pool
Parameters
structgen_pool*poolpool to destroy
Description
Destroy the specified special memory pool. Verifies that there are nooutstanding allocations.
It’s worth noting that, if there are still allocations outstanding from thegiven pool, this function will take the rather extreme step of invokingBUG(), crashing the entire system. You have been warned.
A freshly created pool has no memory to allocate. It is fairly useless inthat state, so one of the first orders of business is usually to add memoryto the pool. That can be done with one of:
- intgen_pool_add(structgen_pool*pool,unsignedlongaddr,size_tsize,intnid)¶
add a new chunk of special memory to the pool
Parameters
structgen_pool*poolpool to add new memory chunk to
unsignedlongaddrstarting address of memory chunk to add to pool
size_tsizesize in bytes of the memory chunk to add to pool
intnidnode id of the node the chunk structure and bitmap should beallocated on, or -1
Description
Add a new chunk of special memory to the specified pool.
Returns 0 on success or a -ve errno on failure.
- intgen_pool_add_owner(structgen_pool*pool,unsignedlongvirt,phys_addr_tphys,size_tsize,intnid,void*owner)¶
add a new chunk of special memory to the pool
Parameters
structgen_pool*poolpool to add new memory chunk to
unsignedlongvirtvirtual starting address of memory chunk to add to pool
phys_addr_tphysphysical starting address of memory chunk to add to pool
size_tsizesize in bytes of the memory chunk to add to pool
intnidnode id of the node the chunk structure and bitmap should beallocated on, or -1
void*ownerprivate data the publisher would like to recall at alloc time
Description
Add a new chunk of special memory to the specified pool.
Returns 0 on success or a -ve errno on failure.
A call togen_pool_add() will place the size bytes of memorystarting at addr (in the kernel’s virtual address space) into the givenpool, once again using nid as the node ID for ancillary memory allocations.Thegen_pool_add_virt() variant associates an explicit physicaladdress with the memory; this is only necessary if the pool will be usedfor DMA allocations.
The functions for allocating memory from the pool (and putting it back)are:
- unsignedlonggen_pool_alloc(structgen_pool*pool,size_tsize)¶
allocate special memory from the pool
Parameters
structgen_pool*poolpool to allocate from
size_tsizenumber of bytes to allocate from the pool
Description
Allocate the requested number of bytes from the specified pool.Uses the pool allocation function (with first-fit algorithm by default).Can not be used in NMI handler on architectures withoutNMI-safe cmpxchg implementation.
- void*gen_pool_dma_alloc(structgen_pool*pool,size_tsize,dma_addr_t*dma)¶
allocate special memory from the pool for DMA usage
Parameters
structgen_pool*poolpool to allocate from
size_tsizenumber of bytes to allocate from the pool
dma_addr_t*dmadma-view physical address return value. Use
NULLif unneeded.
Description
Allocate the requested number of bytes from the specified pool.Uses the pool allocation function (with first-fit algorithm by default).Can not be used in NMI handler on architectures withoutNMI-safe cmpxchg implementation.
Return
virtual address of the allocated memory, orNULL on failure
- voidgen_pool_free_owner(structgen_pool*pool,unsignedlongaddr,size_tsize,void**owner)¶
free allocated special memory back to the pool
Parameters
structgen_pool*poolpool to free to
unsignedlongaddrstarting address of memory to free back to pool
size_tsizesize in bytes of memory to free
void**ownerprivate data stashed at
gen_pool_add()time
Description
Free previously allocated special memory back to the specifiedpool. Can not be used in NMI handler on architectures withoutNMI-safe cmpxchg implementation.
As one would expect,gen_pool_alloc() will allocate size< bytesfrom the given pool. Thegen_pool_dma_alloc() variant allocatesmemory for use with DMA operations, returning the associated physicaladdress in the space pointed to by dma. This will only work if the memorywas added withgen_pool_add_virt(). Note that this functiondeparts from the usual genpool pattern of using unsigned long values torepresent kernel addresses; it returns a void * instead.
That all seems relatively simple; indeed, some developers clearly found itto be too simple. After all, the interface above provides no control overhow the allocation functions choose which specific piece of memory toreturn. If that sort of control is needed, the following functions will beof interest:
- unsignedlonggen_pool_alloc_algo_owner(structgen_pool*pool,size_tsize,genpool_algo_talgo,void*data,void**owner)¶
allocate special memory from the pool
Parameters
structgen_pool*poolpool to allocate from
size_tsizenumber of bytes to allocate from the pool
genpool_algo_talgoalgorithm passed from caller
void*datadata passed to algorithm
void**owneroptionally retrieve the chunk owner
Description
Allocate the requested number of bytes from the specified pool.Uses the pool allocation function (with first-fit algorithm by default).Can not be used in NMI handler on architectures withoutNMI-safe cmpxchg implementation.
- voidgen_pool_set_algo(structgen_pool*pool,genpool_algo_talgo,void*data)¶
set the allocation algorithm
Parameters
structgen_pool*poolpool to change allocation algorithm
genpool_algo_talgocustom algorithm function
void*dataadditional data used byalgo
Description
Callalgo for each memory allocation in the pool.Ifalgo is NULL use gen_pool_first_fit as defaultmemory allocation function.
Allocations withgen_pool_alloc_algo() specify an algorithm to beused to choose the memory to be allocated; the default algorithm can be setwithgen_pool_set_algo(). The data value is passed to thealgorithm; most ignore it, but it is occasionally needed. One can,naturally, write a special-purpose algorithm, but there is a fair setalready available:
gen_pool_first_fit is a simple first-fit allocator; this is the defaultalgorithm if none other has been specified.
gen_pool_first_fit_align forces the allocation to have a specificalignment (passed via data in a genpool_data_align structure).
gen_pool_first_fit_order_align aligns the allocation to the order of thesize. A 60-byte allocation will thus be 64-byte aligned, for example.
gen_pool_best_fit, as one would expect, is a simple best-fit allocator.
gen_pool_fixed_alloc allocates at a specific offset (passed in agenpool_data_fixed structure via the data parameter) within the pool.If the indicated memory is not available the allocation fails.
There is a handful of other functions, mostly for purposes like queryingthe space available in the pool or iterating through chunks of memory.Most users, however, should not need much beyond what has been describedabove. With luck, wider awareness of this module will help to prevent thewriting of special-purpose memory allocators in the future.
- phys_addr_tgen_pool_virt_to_phys(structgen_pool*pool,unsignedlongaddr)¶
return the physical address of memory
Parameters
structgen_pool*poolpool to allocate from
unsignedlongaddrstarting address of memory
Description
Returns the physical address on success, or -1 on error.
- voidgen_pool_for_each_chunk(structgen_pool*pool,void(*func)(structgen_pool*pool,structgen_pool_chunk*chunk,void*data),void*data)¶
call func for every chunk of generic memory pool
Parameters
structgen_pool*poolthe generic memory pool
void(*func)(structgen_pool*pool,structgen_pool_chunk*chunk,void*data)func to call
void*dataadditional data used byfunc
Description
Callfunc for every chunk of generic memory pool. Thefunc iscalled with rcu_read_lock held.
- boolgen_pool_has_addr(structgen_pool*pool,unsignedlongstart,size_tsize)¶
checks if an address falls within the range of a pool
Parameters
structgen_pool*poolthe generic memory pool
unsignedlongstartstart address
size_tsizesize of the region
Description
Check if the range of addresses falls within the specified pool. Returnstrue if the entire range is contained in the pool and false otherwise.
- size_tgen_pool_avail(structgen_pool*pool)¶
get available free space of the pool
Parameters
structgen_pool*poolpool to get available free space
Description
Return available free space of the specified pool.
- size_tgen_pool_size(structgen_pool*pool)¶
get size in bytes of memory managed by the pool
Parameters
structgen_pool*poolpool to get size
Description
Return size in bytes of memory managed by the pool.
- structgen_pool*gen_pool_get(structdevice*dev,constchar*name)¶
Obtain the gen_pool (if any) for a device
Parameters
structdevice*devdevice to retrieve the gen_pool from
constchar*namename of a gen_pool or NULL, identifies a particular gen_pool on device
Description
Returns the gen_pool for the device if one is present, or NULL.
- structgen_pool*of_gen_pool_get(structdevice_node*np,constchar*propname,intindex)¶
find a pool by phandle property
Parameters
structdevice_node*npdevice node
constchar*propnameproperty name containing phandle(s)
intindexindex into the phandle array
Description
Returns the pool that contains the chunk starting at the physicaladdress of the device tree node pointed at by the phandle property,or NULL if not found.