Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
5.9 kB · 144 lines
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145The 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 and posted_ 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.
.. _posted: https://lwn.net/Articles/125842/
Code using this allocator should include <linux/genalloc.h>. The actionbegins with the creation of a pool using one of:
.. kernel-doc:: lib/genalloc.c :functions: gen_pool_create
.. kernel-doc:: lib/genalloc.c :functions: devm_gen_pool_create
A call to gen_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" interface devm_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:
.. kernel-doc:: lib/genalloc.c :functions: gen_pool_destroy
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:
.. kernel-doc:: include/linux/genalloc.h :functions: gen_pool_add
.. kernel-doc:: lib/genalloc.c :functions: gen_pool_add_owner
A call to gen_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.The gen_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:
.. kernel-doc:: include/linux/genalloc.h :functions: gen_pool_alloc
.. kernel-doc:: lib/genalloc.c :functions: gen_pool_dma_alloc
.. kernel-doc:: lib/genalloc.c :functions: gen_pool_free_owner
As one would expect, gen_pool_alloc() will allocate size< bytesfrom the given pool. The gen_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 with gen_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:
.. kernel-doc:: lib/genalloc.c :functions: gen_pool_alloc_algo_owner
.. kernel-doc:: lib/genalloc.c :functions: gen_pool_set_algo
Allocations with gen_pool_alloc_algo() specify an algorithm to beused to choose the memory to be allocated; the default algorithm can be setwith gen_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 default algorithm if none other has been specified.
- gen_pool_first_fit_align forces the allocation to have a specific alignment (passed via data in a genpool_data_align structure).
- gen_pool_first_fit_order_align aligns the allocation to the order of the size. 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 a genpool_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.
.. kernel-doc:: lib/genalloc.c :functions: gen_pool_virt_to_phys
.. kernel-doc:: lib/genalloc.c :functions: gen_pool_for_each_chunk
.. kernel-doc:: lib/genalloc.c :functions: gen_pool_has_addr
.. kernel-doc:: lib/genalloc.c :functions: gen_pool_avail
.. kernel-doc:: lib/genalloc.c :functions: gen_pool_size
.. kernel-doc:: lib/genalloc.c :functions: gen_pool_get
.. kernel-doc:: lib/genalloc.c :functions: of_gen_pool_get