RHEL4/lib/idr.c
<<
>>
Prefs
   1/*
   2 * 2002-10-18  written by Jim Houston jim.houston@ccur.com
   3 *      Copyright (C) 2002 by Concurrent Computer Corporation
   4 *      Distributed under the GNU GPL license version 2.
   5 *
   6 * Modified by George Anzinger to reuse immediately and to use
   7 * find bit instructions.  Also removed _irq on spinlocks.
   8 *
   9 * Small id to pointer translation service.  
  10 *
  11 * It uses a radix tree like structure as a sparse array indexed 
  12 * by the id to obtain the pointer.  The bitmap makes allocating
  13 * a new id quick.  
  14 *
  15 * You call it to allocate an id (an int) an associate with that id a
  16 * pointer or what ever, we treat it as a (void *).  You can pass this
  17 * id to a user for him to pass back at a later time.  You then pass
  18 * that id to this code and it returns your pointer.
  19
  20 * You can release ids at any time. When all ids are released, most of 
  21 * the memory is returned (we keep IDR_FREE_MAX) in a local pool so we
  22 * don't need to go to the memory "store" during an id allocate, just 
  23 * so you don't need to be too concerned about locking and conflicts
  24 * with the slab allocator.
  25 */
  26
  27#ifndef TEST                        // to test in user space...
  28#include <linux/slab.h>
  29#include <linux/init.h>
  30#include <linux/module.h>
  31#endif
  32#include <linux/err.h>
  33#include <linux/string.h>
  34#include <linux/idr.h>
  35
  36static kmem_cache_t *idr_layer_cache;
  37
  38static struct idr_layer *alloc_layer(struct idr *idp)
  39{
  40        struct idr_layer *p;
  41
  42        spin_lock(&idp->lock);
  43        if (!(p = idp->id_free)) {
  44                spin_unlock(&idp->lock);
  45                return NULL;
  46        }
  47        idp->id_free = p->ary[0];
  48        idp->id_free_cnt--;
  49        p->ary[0] = NULL;
  50        spin_unlock(&idp->lock);
  51        return(p);
  52}
  53
  54static void free_layer(struct idr *idp, struct idr_layer *p)
  55{
  56        /*
  57         * Depends on the return element being zeroed.
  58         */
  59        spin_lock(&idp->lock);
  60        p->ary[0] = idp->id_free;
  61        idp->id_free = p;
  62        idp->id_free_cnt++;
  63        spin_unlock(&idp->lock);
  64}
  65
  66/**
  67 * idr_pre_get - reserver resources for idr allocation
  68 * @idp:        idr handle
  69 * @gfp_mask:   memory allocation flags
  70 *
  71 * This function should be called prior to locking and calling the
  72 * following function.  It preallocates enough memory to satisfy
  73 * the worst possible allocation.
  74 *
  75 * If the system is REALLY out of memory this function returns 0,
  76 * otherwise 1.
  77 */
  78int idr_pre_get(struct idr *idp, unsigned gfp_mask)
  79{
  80        while (idp->id_free_cnt < IDR_FREE_MAX) {
  81                struct idr_layer *new;
  82                new = kmem_cache_alloc(idr_layer_cache, gfp_mask);
  83                if(new == NULL)
  84                        return (0);
  85                free_layer(idp, new);
  86        }
  87        return 1;
  88}
  89EXPORT_SYMBOL(idr_pre_get);
  90
  91static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
  92{
  93        int n, m, sh;
  94        struct idr_layer *p, *new;
  95        struct idr_layer *pa[MAX_LEVEL];
  96        int l, id;
  97        long bm;
  98
  99        id = *starting_id;
 100        p = idp->top;
 101        l = idp->layers;
 102        pa[l--] = NULL;
 103        while (1) {
 104                /*
 105                 * We run around this while until we reach the leaf node...
 106                 */
 107                n = (id >> (IDR_BITS*l)) & IDR_MASK;
 108                bm = ~p->bitmap;
 109                m = find_next_bit(&bm, IDR_SIZE, n);
 110                if (m == IDR_SIZE) {
 111                        /* no space available go back to previous layer. */
 112                        l++;
 113                        id = (id | ((1 << (IDR_BITS*l))-1)) + 1;
 114                        if (!(p = pa[l])) {
 115                                *starting_id = id;
 116                                return -2;
 117                        }
 118                        continue;
 119                }
 120                if (m != n) {
 121                        sh = IDR_BITS*l;
 122                        id = ((id >> sh) ^ n ^ m) << sh;
 123                }
 124                if ((id >= MAX_ID_BIT) || (id < 0))
 125                        return -3;
 126                if (l == 0)
 127                        break;
 128                /*
 129                 * Create the layer below if it is missing.
 130                 */
 131                if (!p->ary[m]) {
 132                        if (!(new = alloc_layer(idp)))
 133                                return -1;
 134                        p->ary[m] = new;
 135                        p->count++;
 136                }
 137                pa[l--] = p;
 138                p = p->ary[m];
 139        }
 140        /*
 141         * We have reached the leaf node, plant the
 142         * users pointer and return the raw id.
 143         */
 144        p->ary[m] = (struct idr_layer *)ptr;
 145        __set_bit(m, &p->bitmap);
 146        p->count++;
 147        /*
 148         * If this layer is full mark the bit in the layer above
 149         * to show that this part of the radix tree is full.
 150         * This may complete the layer above and require walking
 151         * up the radix tree.
 152         */
 153        n = id;
 154        while (p->bitmap == IDR_FULL) {
 155                if (!(p = pa[++l]))
 156                        break;
 157                n = n >> IDR_BITS;
 158                __set_bit((n & IDR_MASK), &p->bitmap);
 159        }
 160        return(id);
 161}
 162
 163static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
 164{
 165        struct idr_layer *p, *new;
 166        int layers, v, id;
 167        
 168        id = starting_id;
 169build_up:
 170        p = idp->top;
 171        layers = idp->layers;
 172        if (unlikely(!p)) {
 173                if (!(p = alloc_layer(idp)))
 174                        return -1;
 175                layers = 1;
 176        }
 177        /*
 178         * Add a new layer to the top of the tree if the requested
 179         * id is larger than the currently allocated space.
 180         */
 181        while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) {
 182                layers++;
 183                if (!p->count)
 184                        continue;
 185                if (!(new = alloc_layer(idp))) {
 186                        /*
 187                         * The allocation failed.  If we built part of
 188                         * the structure tear it down.
 189                         */
 190                        for (new = p; p && p != idp->top; new = p) {
 191                                p = p->ary[0];
 192                                new->ary[0] = NULL;
 193                                new->bitmap = new->count = 0;
 194                                free_layer(idp, new);
 195                        }
 196                        return -1;
 197                }
 198                new->ary[0] = p;
 199                new->count = 1;
 200                if (p->bitmap == IDR_FULL)
 201                        __set_bit(0, &new->bitmap);
 202                p = new;
 203        }
 204        idp->top = p;
 205        idp->layers = layers;
 206        v = sub_alloc(idp, ptr, &id);
 207        if (v == -2)
 208                goto build_up;
 209        return(v);
 210}
 211
 212/**
 213 * idr_get_new_above - allocate new idr entry above a start id
 214 * @idp: idr handle
 215 * @ptr: pointer you want associated with the ide
 216 * @start_id: id to start search at
 217 * @id: pointer to the allocated handle
 218 *
 219 * This is the allocate id function.  It should be called with any
 220 * required locks.
 221 *
 222 * If memory is required, it will return -EAGAIN, you should unlock
 223 * and go back to the idr_pre_get() call.  If the idr is full, it will
 224 * return -ENOSPC.
 225 *
 226 * @id returns a value in the range 0 ... 0x7fffffff
 227 */
 228int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
 229{
 230        int rv;
 231        rv = idr_get_new_above_int(idp, ptr, starting_id);
 232        /*
 233         * This is a cheap hack until the IDR code can be fixed to
 234         * return proper error values.
 235         */
 236        if (rv < 0) {
 237                if (rv == -1)
 238                        return -EAGAIN;
 239                else /* Will be -3 */
 240                        return -ENOSPC;
 241        }
 242        *id = rv;
 243        return 0;
 244}
 245EXPORT_SYMBOL(idr_get_new_above);
 246
 247/**
 248 * idr_get_new - allocate new idr entry
 249 * @idp: idr handle
 250 * @ptr: pointer you want associated with the ide
 251 * @id: pointer to the allocated handle
 252 *
 253 * This is the allocate id function.  It should be called with any
 254 * required locks.
 255 *
 256 * If memory is required, it will return -EAGAIN, you should unlock
 257 * and go back to the idr_pre_get() call.  If the idr is full, it will
 258 * return -ENOSPC.
 259 *
 260 * @id returns a value in the range 0 ... 0x7fffffff
 261 */
 262int idr_get_new(struct idr *idp, void *ptr, int *id)
 263{
 264        int rv;
 265        rv = idr_get_new_above_int(idp, ptr, 0);
 266        /*
 267         * This is a cheap hack until the IDR code can be fixed to
 268         * return proper error values.
 269         */
 270        if (rv < 0) {
 271                if (rv == -1)
 272                        return -EAGAIN;
 273                else /* Will be -3 */
 274                        return -ENOSPC;
 275        }
 276        *id = rv;
 277        return 0;
 278}
 279EXPORT_SYMBOL(idr_get_new);
 280
 281static void sub_remove(struct idr *idp, int shift, int id)
 282{
 283        struct idr_layer *p = idp->top;
 284        struct idr_layer **pa[MAX_LEVEL];
 285        struct idr_layer ***paa = &pa[0];
 286
 287        *paa = NULL;
 288        *++paa = &idp->top;
 289
 290        while ((shift > 0) && p) {
 291                int n = (id >> shift) & IDR_MASK;
 292                __clear_bit(n, &p->bitmap);
 293                *++paa = &p->ary[n];
 294                p = p->ary[n];
 295                shift -= IDR_BITS;
 296        }
 297        if (likely(p != NULL)){
 298                int n = id & IDR_MASK;
 299                __clear_bit(n, &p->bitmap);
 300                p->ary[n] = NULL;
 301                while(*paa && ! --((**paa)->count)){
 302                        free_layer(idp, **paa);
 303                        **paa-- = NULL;
 304                }
 305                if ( ! *paa )
 306                        idp->layers = 0;
 307        }
 308}
 309
 310/**
 311 * idr_remove - remove the given id and free it's slot
 312 * idp: idr handle
 313 * id: uniqueue key
 314 */
 315void idr_remove(struct idr *idp, int id)
 316{
 317        struct idr_layer *p;
 318
 319        /* Mask off upper bits we don't use for the search. */
 320        id &= MAX_ID_MASK;
 321
 322        sub_remove(idp, (idp->layers - 1) * IDR_BITS, id);
 323        if ( idp->top && idp->top->count == 1 && 
 324             (idp->layers > 1) &&
 325             idp->top->ary[0]){  // We can drop a layer
 326
 327                p = idp->top->ary[0];
 328                idp->top->bitmap = idp->top->count = 0;
 329                free_layer(idp, idp->top);
 330                idp->top = p;
 331                --idp->layers;
 332        }
 333        while (idp->id_free_cnt >= IDR_FREE_MAX) {
 334                
 335                p = alloc_layer(idp);
 336                kmem_cache_free(idr_layer_cache, p);
 337                return;
 338        }
 339}
 340EXPORT_SYMBOL(idr_remove);
 341
 342/**
 343 * idr_find - return pointer for given id
 344 * @idp: idr handle
 345 * @id: lookup key
 346 *
 347 * Return the pointer given the id it has been registered with.  A %NULL
 348 * return indicates that @id is not valid or you passed %NULL in
 349 * idr_get_new().
 350 *
 351 * The caller must serialize idr_find() vs idr_get_new() and idr_remove().
 352 */
 353void *idr_find(struct idr *idp, int id)
 354{
 355        int n;
 356        struct idr_layer *p;
 357
 358        n = idp->layers * IDR_BITS;
 359        p = idp->top;
 360
 361        /* Mask off upper bits we don't use for the search. */
 362        id &= MAX_ID_MASK;
 363
 364        if (id >= (1 << n))
 365                return NULL;
 366
 367        while (n > 0 && p) {
 368                n -= IDR_BITS;
 369                p = p->ary[(id >> n) & IDR_MASK];
 370        }
 371        return((void *)p);
 372}
 373EXPORT_SYMBOL(idr_find);
 374
 375/**
 376 * idr_replace - replace pointer for given id
 377 * @idp: idr handle
 378 * @ptr: pointer you want associated with the ide
 379 * @id: lookup key
 380 *
 381 * Replace the pointer registered with an id and return the old value.
 382 * A -ENOENT return indicates that @id was not found.
 383 * A -EINVAL return indicates that @id was not within valid constraints.
 384 *
 385 * The caller must serialize vs idr_find(), idr_get_new(), and idr_remove().
 386 */
 387void *idr_replace(struct idr *idp, void *ptr, int id)
 388{
 389        int n;
 390        struct idr_layer *p, *old_p;
 391
 392        n = idp->layers * IDR_BITS;
 393        p = idp->top;
 394
 395        id &= MAX_ID_MASK;
 396
 397        if (id >= (1 << n))
 398                return ERR_PTR(-EINVAL);
 399
 400        n -= IDR_BITS;
 401        while ((n > 0) && p) {
 402                p = p->ary[(id >> n) & IDR_MASK];
 403                n -= IDR_BITS;
 404        }
 405
 406        n = id & IDR_MASK;
 407        if (unlikely(p == NULL || !test_bit(n, &p->bitmap)))
 408                return ERR_PTR(-ENOENT);
 409
 410        old_p = p->ary[n];
 411        p->ary[n] = ptr;
 412
 413        return (void *)old_p;
 414}
 415EXPORT_SYMBOL(idr_replace);
 416
 417static void idr_cache_ctor(void * idr_layer, 
 418                           kmem_cache_t *idr_layer_cache, unsigned long flags)
 419{
 420        memset(idr_layer, 0, sizeof(struct idr_layer));
 421}
 422
 423static  int init_id_cache(void)
 424{
 425        if (!idr_layer_cache)
 426                idr_layer_cache = kmem_cache_create("idr_layer_cache", 
 427                        sizeof(struct idr_layer), 0, 0, idr_cache_ctor, NULL);
 428        return 0;
 429}
 430
 431/**
 432 * idr_init - initialize idr handle
 433 * @idp:        idr handle
 434 *
 435 * This function is use to set up the handle (@idp) that you will pass
 436 * to the rest of the functions.
 437 */
 438void idr_init(struct idr *idp)
 439{
 440        init_id_cache();
 441        memset(idp, 0, sizeof(struct idr));
 442        spin_lock_init(&idp->lock);
 443}
 444EXPORT_SYMBOL(idr_init);
 445