RHEL4/mm/mempool.c
<<
>>
Prefs
   1/*
   2 *  linux/mm/mempool.c
   3 *
   4 *  memory buffer pool support. Such pools are mostly used
   5 *  for guaranteed, deadlock-free memory allocations during
   6 *  extreme VM load.
   7 *
   8 *  started by Ingo Molnar, Copyright (C) 2001
   9 */
  10
  11#include <linux/mm.h>
  12#include <linux/slab.h>
  13#include <linux/module.h>
  14#include <linux/mempool.h>
  15#include <linux/blkdev.h>
  16#include <linux/writeback.h>
  17
  18static void add_element(mempool_t *pool, void *element)
  19{
  20        BUG_ON(pool->curr_nr >= pool->min_nr);
  21        pool->elements[pool->curr_nr++] = element;
  22}
  23
  24static void *remove_element(mempool_t *pool)
  25{
  26        BUG_ON(pool->curr_nr <= 0);
  27        return pool->elements[--pool->curr_nr];
  28}
  29
  30static void free_pool(mempool_t *pool)
  31{
  32        while (pool->curr_nr) {
  33                void *element = remove_element(pool);
  34                pool->free(element, pool->pool_data);
  35        }
  36        kfree(pool->elements);
  37        kfree(pool);
  38}
  39
  40/**
  41 * mempool_create - create a memory pool
  42 * @min_nr:    the minimum number of elements guaranteed to be
  43 *             allocated for this pool.
  44 * @alloc_fn:  user-defined element-allocation function.
  45 * @free_fn:   user-defined element-freeing function.
  46 * @pool_data: optional private data available to the user-defined functions.
  47 *
  48 * this function creates and allocates a guaranteed size, preallocated
  49 * memory pool. The pool can be used from the mempool_alloc and mempool_free
  50 * functions. This function might sleep. Both the alloc_fn() and the free_fn()
  51 * functions might sleep - as long as the mempool_alloc function is not called
  52 * from IRQ contexts.
  53 */
  54mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
  55                                mempool_free_t *free_fn, void *pool_data)
  56{
  57        mempool_t *pool;
  58
  59        pool = kmalloc(sizeof(*pool), GFP_KERNEL);
  60        if (!pool)
  61                return NULL;
  62        memset(pool, 0, sizeof(*pool));
  63        pool->elements = kmalloc(min_nr * sizeof(void *), GFP_KERNEL);
  64        if (!pool->elements) {
  65                kfree(pool);
  66                return NULL;
  67        }
  68        spin_lock_init(&pool->lock);
  69        pool->min_nr = min_nr;
  70        pool->pool_data = pool_data;
  71        init_waitqueue_head(&pool->wait);
  72        pool->alloc = alloc_fn;
  73        pool->free = free_fn;
  74
  75        /*
  76         * First pre-allocate the guaranteed number of buffers.
  77         */
  78        while (pool->curr_nr < pool->min_nr) {
  79                void *element;
  80
  81                element = pool->alloc(GFP_KERNEL, pool->pool_data);
  82                if (unlikely(!element)) {
  83                        free_pool(pool);
  84                        return NULL;
  85                }
  86                add_element(pool, element);
  87        }
  88        return pool;
  89}
  90EXPORT_SYMBOL(mempool_create);
  91
  92/**
  93 * mempool_resize - resize an existing memory pool
  94 * @pool:       pointer to the memory pool which was allocated via
  95 *              mempool_create().
  96 * @new_min_nr: the new minimum number of elements guaranteed to be
  97 *              allocated for this pool.
  98 * @gfp_mask:   the usual allocation bitmask.
  99 *
 100 * This function shrinks/grows the pool. In the case of growing,
 101 * it cannot be guaranteed that the pool will be grown to the new
 102 * size immediately, but new mempool_free() calls will refill it.
 103 *
 104 * Note, the caller must guarantee that no mempool_destroy is called
 105 * while this function is running. mempool_alloc() & mempool_free()
 106 * might be called (eg. from IRQ contexts) while this function executes.
 107 */
 108int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask)
 109{
 110        void *element;
 111        void **new_elements;
 112        unsigned long flags;
 113
 114        BUG_ON(new_min_nr <= 0);
 115
 116        spin_lock_irqsave(&pool->lock, flags);
 117        if (new_min_nr < pool->min_nr) {
 118                while (pool->curr_nr > new_min_nr) {
 119                        element = remove_element(pool);
 120                        spin_unlock_irqrestore(&pool->lock, flags);
 121                        pool->free(element, pool->pool_data);
 122                        spin_lock_irqsave(&pool->lock, flags);
 123                }
 124                pool->min_nr = new_min_nr;
 125                goto out_unlock;
 126        }
 127        spin_unlock_irqrestore(&pool->lock, flags);
 128
 129        /* Grow the pool */
 130        new_elements = kmalloc(new_min_nr * sizeof(*new_elements), gfp_mask);
 131        if (!new_elements)
 132                return -ENOMEM;
 133
 134        spin_lock_irqsave(&pool->lock, flags);
 135        memcpy(new_elements, pool->elements,
 136                        pool->curr_nr * sizeof(*new_elements));
 137        kfree(pool->elements);
 138        pool->elements = new_elements;
 139        pool->min_nr = new_min_nr;
 140
 141        while (pool->curr_nr < pool->min_nr) {
 142                spin_unlock_irqrestore(&pool->lock, flags);
 143                element = pool->alloc(gfp_mask, pool->pool_data);
 144                if (!element)
 145                        goto out;
 146                spin_lock_irqsave(&pool->lock, flags);
 147                if (pool->curr_nr < pool->min_nr) {
 148                        add_element(pool, element);
 149                } else {
 150                        spin_unlock_irqrestore(&pool->lock, flags);
 151                        pool->free(element, pool->pool_data);   /* Raced */
 152                        spin_lock_irqsave(&pool->lock, flags);
 153                }
 154        }
 155out_unlock:
 156        spin_unlock_irqrestore(&pool->lock, flags);
 157out:
 158        return 0;
 159}
 160EXPORT_SYMBOL(mempool_resize);
 161
 162/**
 163 * mempool_destroy - deallocate a memory pool
 164 * @pool:      pointer to the memory pool which was allocated via
 165 *             mempool_create().
 166 *
 167 * this function only sleeps if the free_fn() function sleeps. The caller
 168 * has to guarantee that all elements have been returned to the pool (ie:
 169 * freed) prior to calling mempool_destroy().
 170 */
 171void mempool_destroy(mempool_t *pool)
 172{
 173        if (pool->curr_nr != pool->min_nr)
 174                BUG();          /* There were outstanding elements */
 175        free_pool(pool);
 176}
 177EXPORT_SYMBOL(mempool_destroy);
 178
 179/**
 180 * mempool_alloc - allocate an element from a specific memory pool
 181 * @pool:      pointer to the memory pool which was allocated via
 182 *             mempool_create().
 183 * @gfp_mask:  the usual allocation bitmask.
 184 *
 185 * this function only sleeps if the alloc_fn function sleeps or
 186 * returns NULL. Note that due to preallocation, this function
 187 * *never* fails when called from process contexts. (it might
 188 * fail if called from an IRQ context.)
 189 */
 190void * mempool_alloc(mempool_t *pool, int gfp_mask)
 191{
 192        void *element;
 193        unsigned long flags;
 194        DEFINE_WAIT(wait);
 195        int gfp_nowait = gfp_mask & ~(__GFP_WAIT | __GFP_IO);
 196
 197        might_sleep_if(gfp_mask & __GFP_WAIT);
 198repeat_alloc:
 199        element = pool->alloc(gfp_nowait|__GFP_NOWARN, pool->pool_data);
 200        if (likely(element != NULL))
 201                return element;
 202
 203        /*
 204         * If the pool is less than 50% full and we can perform effective
 205         * page reclaim then try harder to allocate an element.
 206         */
 207        mb();
 208        if ((gfp_mask & __GFP_FS) && (gfp_mask != gfp_nowait) &&
 209                                (pool->curr_nr <= pool->min_nr/2)) {
 210                element = pool->alloc(gfp_mask, pool->pool_data);
 211                if (likely(element != NULL))
 212                        return element;
 213        }
 214
 215        /*
 216         * Kick the VM at this point.
 217         */
 218        wakeup_bdflush(0);
 219
 220        spin_lock_irqsave(&pool->lock, flags);
 221        if (likely(pool->curr_nr)) {
 222                element = remove_element(pool);
 223                spin_unlock_irqrestore(&pool->lock, flags);
 224                return element;
 225        }
 226        spin_unlock_irqrestore(&pool->lock, flags);
 227
 228        /* We must not sleep in the GFP_ATOMIC case */
 229        if (!(gfp_mask & __GFP_WAIT))
 230                return NULL;
 231
 232        prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE);
 233        mb();
 234        if (!pool->curr_nr)
 235                io_schedule();
 236        finish_wait(&pool->wait, &wait);
 237
 238        goto repeat_alloc;
 239}
 240EXPORT_SYMBOL(mempool_alloc);
 241
 242/**
 243 * mempool_free - return an element to the pool.
 244 * @element:   pool element pointer.
 245 * @pool:      pointer to the memory pool which was allocated via
 246 *             mempool_create().
 247 *
 248 * this function only sleeps if the free_fn() function sleeps.
 249 */
 250void mempool_free(void *element, mempool_t *pool)
 251{
 252        unsigned long flags;
 253
 254        mb();
 255        if (pool->curr_nr < pool->min_nr) {
 256                spin_lock_irqsave(&pool->lock, flags);
 257                if (pool->curr_nr < pool->min_nr) {
 258                        add_element(pool, element);
 259                        spin_unlock_irqrestore(&pool->lock, flags);
 260                        wake_up(&pool->wait);
 261                        return;
 262                }
 263                spin_unlock_irqrestore(&pool->lock, flags);
 264        }
 265        pool->free(element, pool->pool_data);
 266}
 267EXPORT_SYMBOL(mempool_free);
 268
 269/*
 270 * A commonly used alloc and free fn.
 271 */
 272void *mempool_alloc_slab(int gfp_mask, void *pool_data)
 273{
 274        kmem_cache_t *mem = (kmem_cache_t *) pool_data;
 275        return kmem_cache_alloc(mem, gfp_mask);
 276}
 277EXPORT_SYMBOL(mempool_alloc_slab);
 278
 279void mempool_free_slab(void *element, void *pool_data)
 280{
 281        kmem_cache_t *mem = (kmem_cache_t *) pool_data;
 282        kmem_cache_free(mem, element);
 283}
 284EXPORT_SYMBOL(mempool_free_slab);
 285