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