Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 330090
b: refs/heads/master
c: ca279cf
h: refs/heads/master
v: v3
  • Loading branch information
Benjamin Gaignard authored and Linus Torvalds committed Oct 5, 2012
1 parent 1a41040 commit 923d30b
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e96875677fb2b7cb739c5d7769824dff7260d31d
refs/heads/master: ca279cf1065fb689abea1dc7d8c11787729bb185
27 changes: 27 additions & 0 deletions trunk/include/linux/genalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,30 @@

#ifndef __GENALLOC_H__
#define __GENALLOC_H__
/**
* Allocation callback function type definition
* @map: Pointer to bitmap
* @size: The bitmap size in bits
* @start: The bitnumber to start searching at
* @nr: The number of zeroed bits we're looking for
* @data: optional additional data used by @genpool_algo_t
*/
typedef unsigned long (*genpool_algo_t)(unsigned long *map,
unsigned long size,
unsigned long start,
unsigned int nr,
void *data);

/*
* General purpose special memory pool descriptor.
*/
struct gen_pool {
spinlock_t lock;
struct list_head chunks; /* list of chunks in this pool */
int min_alloc_order; /* minimum allocation order */

genpool_algo_t algo; /* allocation function */
void *data;
};

/*
Expand Down Expand Up @@ -78,4 +95,14 @@ extern void gen_pool_for_each_chunk(struct gen_pool *,
void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *);
extern size_t gen_pool_avail(struct gen_pool *);
extern size_t gen_pool_size(struct gen_pool *);

extern void gen_pool_set_algo(struct gen_pool *pool, genpool_algo_t algo,
void *data);

extern unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size,
unsigned long start, unsigned int nr, void *data);

extern unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size,
unsigned long start, unsigned int nr, void *data);

#endif /* __GENALLOC_H__ */
88 changes: 84 additions & 4 deletions trunk/lib/genalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ struct gen_pool *gen_pool_create(int min_alloc_order, int nid)
spin_lock_init(&pool->lock);
INIT_LIST_HEAD(&pool->chunks);
pool->min_alloc_order = min_alloc_order;
pool->algo = gen_pool_first_fit;
pool->data = NULL;
}
return pool;
}
Expand Down Expand Up @@ -255,8 +257,9 @@ EXPORT_SYMBOL(gen_pool_destroy);
* @size: number of bytes to allocate from the pool
*
* Allocate the requested number of bytes from the specified pool.
* Uses a first-fit algorithm. Can not be used in NMI handler on
* architectures without NMI-safe cmpxchg implementation.
* Uses the pool allocation function (with first-fit algorithm by default).
* Can not be used in NMI handler on architectures without
* NMI-safe cmpxchg implementation.
*/
unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
{
Expand All @@ -280,8 +283,8 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)

end_bit = (chunk->end_addr - chunk->start_addr) >> order;
retry:
start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit,
start_bit, nbits, 0);
start_bit = pool->algo(chunk->bits, end_bit, start_bit, nbits,
pool->data);
if (start_bit >= end_bit)
continue;
remain = bitmap_set_ll(chunk->bits, start_bit, nbits);
Expand Down Expand Up @@ -400,3 +403,80 @@ size_t gen_pool_size(struct gen_pool *pool)
return size;
}
EXPORT_SYMBOL_GPL(gen_pool_size);

/**
* gen_pool_set_algo - set the allocation algorithm
* @pool: pool to change allocation algorithm
* @algo: custom algorithm function
* @data: additional data used by @algo
*
* Call @algo for each memory allocation in the pool.
* If @algo is NULL use gen_pool_first_fit as default
* memory allocation function.
*/
void gen_pool_set_algo(struct gen_pool *pool, genpool_algo_t algo, void *data)
{
rcu_read_lock();

pool->algo = algo;
if (!pool->algo)
pool->algo = gen_pool_first_fit;

pool->data = data;

rcu_read_unlock();
}
EXPORT_SYMBOL(gen_pool_set_algo);

/**
* gen_pool_first_fit - find the first available region
* of memory matching the size requirement (no alignment constraint)
* @map: The address to base the search on
* @size: The bitmap size in bits
* @start: The bitnumber to start searching at
* @nr: The number of zeroed bits we're looking for
* @data: additional data - unused
*/
unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size,
unsigned long start, unsigned int nr, void *data)
{
return bitmap_find_next_zero_area(map, size, start, nr, 0);
}
EXPORT_SYMBOL(gen_pool_first_fit);

/**
* gen_pool_best_fit - find the best fitting region of memory
* macthing the size requirement (no alignment constraint)
* @map: The address to base the search on
* @size: The bitmap size in bits
* @start: The bitnumber to start searching at
* @nr: The number of zeroed bits we're looking for
* @data: additional data - unused
*
* Iterate over the bitmap to find the smallest free region
* which we can allocate the memory.
*/
unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size,
unsigned long start, unsigned int nr, void *data)
{
unsigned long start_bit = size;
unsigned long len = size + 1;
unsigned long index;

index = bitmap_find_next_zero_area(map, size, start, nr, 0);

while (index < size) {
int next_bit = find_next_bit(map, size, index + nr);
if ((next_bit - index) < len) {
len = next_bit - index;
start_bit = index;
if (len == nr)
return start_bit;
}
index = bitmap_find_next_zero_area(map, size,
next_bit + 1, nr, 0);
}

return start_bit;
}
EXPORT_SYMBOL(gen_pool_best_fit);

0 comments on commit 923d30b

Please sign in to comment.