diff options
| author | Benjamin Gaignard <benjamin.gaignard@linaro.org> | 2012-10-04 20:13:20 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-05 14:04:57 -0400 |
| commit | ca279cf1065fb689abea1dc7d8c11787729bb185 (patch) | |
| tree | fdde907d1c3198f81c9085f858ac64c7a3cc50d8 /include | |
| parent | e96875677fb2b7cb739c5d7769824dff7260d31d (diff) | |
genalloc: make it possible to use a custom allocation algorithm
Premit use of another algorithm than the default first-fit one. For
example a custom algorithm could be used to manage alignment requirements.
As I can't predict all the possible requirements/needs for all allocation
uses cases, I add a "free" field 'void *data' to pass any needed
information to the allocation function. For example 'data' could be used
to handle a structure where you store the alignment, the expected memory
bank, the requester device, or any information that could influence the
allocation algorithm.
An usage example may look like this:
struct my_pool_constraints {
int align;
int bank;
...
};
unsigned long my_custom_algo(unsigned long *map, unsigned long size,
unsigned long start, unsigned int nr, void *data)
{
struct my_pool_constraints *constraints = data;
...
deal with allocation contraints
...
return the index in bitmap where perform the allocation
}
void create_my_pool()
{
struct my_pool_constraints c;
struct gen_pool *pool = gen_pool_create(...);
gen_pool_add(pool, ...);
gen_pool_set_algo(pool, my_custom_algo, &c);
}
Add of best-fit algorithm function:
most of the time best-fit is slower then first-fit but memory fragmentation
is lower. The random buffer allocation/free tests don't show any arithmetic
relation between the allocation time and fragmentation but the
best-fit algorithm
is sometime able to perform the allocation when the first-fit can't.
This new algorithm help to remove static allocations on ESRAM, a small but
fast on-chip RAM of few KB, used for high-performance uses cases like DMA
linked lists, graphic accelerators, encoders/decoders. On the Ux500
(in the ARM tree) we have define 5 ESRAM banks of 128 KB each and use of
static allocations becomes unmaintainable:
cd arch/arm/mach-ux500 && grep -r ESRAM .
./include/mach/db8500-regs.h:/* Base address and bank offsets for ESRAM */
./include/mach/db8500-regs.h:#define U8500_ESRAM_BASE 0x40000000
./include/mach/db8500-regs.h:#define U8500_ESRAM_BANK_SIZE 0x00020000
./include/mach/db8500-regs.h:#define U8500_ESRAM_BANK0 U8500_ESRAM_BASE
./include/mach/db8500-regs.h:#define U8500_ESRAM_BANK1 (U8500_ESRAM_BASE + U8500_ESRAM_BANK_SIZE)
./include/mach/db8500-regs.h:#define U8500_ESRAM_BANK2 (U8500_ESRAM_BANK1 + U8500_ESRAM_BANK_SIZE)
./include/mach/db8500-regs.h:#define U8500_ESRAM_BANK3 (U8500_ESRAM_BANK2 + U8500_ESRAM_BANK_SIZE)
./include/mach/db8500-regs.h:#define U8500_ESRAM_BANK4 (U8500_ESRAM_BANK3 + U8500_ESRAM_BANK_SIZE)
./include/mach/db8500-regs.h:#define U8500_ESRAM_DMA_LCPA_OFFSET 0x10000
./include/mach/db8500-regs.h:#define U8500_DMA_LCPA_BASE
(U8500_ESRAM_BANK0 + U8500_ESRAM_DMA_LCPA_OFFSET)
./include/mach/db8500-regs.h:#define U8500_DMA_LCLA_BASE U8500_ESRAM_BANK4
I want to use genalloc to do dynamic allocations but I need to be able to
fine tune the allocation algorithm. I my case best-fit algorithm give
better results than first-fit, but it will not be true for every use case.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@stericsson.com>
Cc: Huang Ying <ying.huang@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/genalloc.h | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h index 5e98eeb2af3b..dd7c569aacad 100644 --- a/include/linux/genalloc.h +++ b/include/linux/genalloc.h | |||
| @@ -29,6 +29,20 @@ | |||
| 29 | 29 | ||
| 30 | #ifndef __GENALLOC_H__ | 30 | #ifndef __GENALLOC_H__ |
| 31 | #define __GENALLOC_H__ | 31 | #define __GENALLOC_H__ |
| 32 | /** | ||
| 33 | * Allocation callback function type definition | ||
| 34 | * @map: Pointer to bitmap | ||
| 35 | * @size: The bitmap size in bits | ||
| 36 | * @start: The bitnumber to start searching at | ||
| 37 | * @nr: The number of zeroed bits we're looking for | ||
| 38 | * @data: optional additional data used by @genpool_algo_t | ||
| 39 | */ | ||
| 40 | typedef unsigned long (*genpool_algo_t)(unsigned long *map, | ||
| 41 | unsigned long size, | ||
| 42 | unsigned long start, | ||
| 43 | unsigned int nr, | ||
| 44 | void *data); | ||
| 45 | |||
| 32 | /* | 46 | /* |
| 33 | * General purpose special memory pool descriptor. | 47 | * General purpose special memory pool descriptor. |
| 34 | */ | 48 | */ |
| @@ -36,6 +50,9 @@ struct gen_pool { | |||
| 36 | spinlock_t lock; | 50 | spinlock_t lock; |
| 37 | struct list_head chunks; /* list of chunks in this pool */ | 51 | struct list_head chunks; /* list of chunks in this pool */ |
| 38 | int min_alloc_order; /* minimum allocation order */ | 52 | int min_alloc_order; /* minimum allocation order */ |
| 53 | |||
| 54 | genpool_algo_t algo; /* allocation function */ | ||
| 55 | void *data; | ||
| 39 | }; | 56 | }; |
| 40 | 57 | ||
| 41 | /* | 58 | /* |
| @@ -78,4 +95,14 @@ extern void gen_pool_for_each_chunk(struct gen_pool *, | |||
| 78 | void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *); | 95 | void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *); |
| 79 | extern size_t gen_pool_avail(struct gen_pool *); | 96 | extern size_t gen_pool_avail(struct gen_pool *); |
| 80 | extern size_t gen_pool_size(struct gen_pool *); | 97 | extern size_t gen_pool_size(struct gen_pool *); |
| 98 | |||
| 99 | extern void gen_pool_set_algo(struct gen_pool *pool, genpool_algo_t algo, | ||
| 100 | void *data); | ||
| 101 | |||
| 102 | extern unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size, | ||
| 103 | unsigned long start, unsigned int nr, void *data); | ||
| 104 | |||
| 105 | extern unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size, | ||
| 106 | unsigned long start, unsigned int nr, void *data); | ||
| 107 | |||
| 81 | #endif /* __GENALLOC_H__ */ | 108 | #endif /* __GENALLOC_H__ */ |
