/* * include/linux/idr.h * * 2002-10-18 written by Jim Houston jim.houston@ccur.com * Copyright (C) 2002 by Concurrent Computer Corporation * Distributed under the GNU GPL license version 2. * * Small id to pointer translation service avoiding fixed sized * tables. */ #ifndef __IDR_H__ #define __IDR_H__ #include #include #include #include /* * We want shallower trees and thus more bits covered at each layer. 8 * bits gives us large enough first layer for most use cases and maximum * tree depth of 4. Each idr_layer is slightly larger than 2k on 64bit and * 1k on 32bit. */ #define IDR_BITS 8 #define IDR_SIZE (1 << IDR_BITS) #define IDR_MASK ((1 << IDR_BITS)-1) struct idr_layer { int prefix; /* the ID prefix of this idr_layer */ DECLARE_BITMAP(bitmap, IDR_SIZE); /* A zero bit means "space here" */ struct idr_layer __rcu *ary[1<hint); if (hint && (id & ~IDR_MASK) == hint->prefix) return rcu_dereference_raw(hint->ary[id & IDR_MASK]); return idr_find_slowpath(idr, id); } /** * idr_get_new - allocate new idr entry * @idp: idr handle * @ptr: pointer you want associated with the id * @id: pointer to the allocated handle * * Simple wrapper around idr_get_new_above() w/ @starting_id of zero. */ static inline int idr_get_new(struct idr *idp, void *ptr, int *id) { return idr_get_new_above(idp, ptr, 0, id); } /** * idr_for_each_entry - iterate over an idr's elements of a given type * @idp: idr handle * @entry: the type * to use as cursor * @id: id entry's key */ #define idr_for_each_entry(idp, entry, id) \ for (id = 0, entry = (typeof(entry))idr_get_next((idp), &(id)); \ entry != NULL; \ ++id, entry = (typeof(entry))idr_get_next((idp), &(id))) void __idr_remove_all(struct idr *idp); /* don't use */ /** * idr_remove_all - remove all ids from the given idr tree * @idp: idr handle * * If you're trying to destroy @idp, calling idr_destroy() is enough. * This is going away. Don't use. */ static inline void __deprecated idr_remove_all(struct idr *idp) { __idr_remove_all(idp); } /* * IDA - IDR based id allocator, use when translation from id to * pointer isn't necessary. * * IDA_BITMAP_LONGS is calculated to be one less to accommodate * ida_bitmap->nr_busy so that the whole struct fits in 128 bytes. */ #define IDA_CHUNK_SIZE 128 /* 128 bytes per chunk */ #define IDA_BITMAP_LONGS (IDA_CHUNK_SIZE / sizeof(long) - 1) #define IDA_BITMAP_BITS (IDA_BITMAP_LONGS * sizeof(long) * 8) struct ida_bitmap { long nr_busy; unsigned long bitmap[IDA_BITMAP_LONGS]; }; struct ida { struct idr idr; struct ida_bitmap *free_bitmap; }; #define IDA_INIT(name) { .idr = IDR_INIT((name).idr), .free_bitmap = NULL, } #define DEFINE_IDA(name) struct ida name = IDA_INIT(name) int ida_pre_get(struct ida *ida, gfp_t gfp_mask); int ida_get_new_above(struct ida *ida, int starting_id, int *p_id); void ida_remove(struct ida *ida, int id); void ida_destroy(struct ida *ida); void ida_init(struct ida *ida); int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end, gfp_t gfp_mask); void ida_simple_remove(struct ida *ida, unsigned int id); /** * ida_get_new - allocate new ID * @ida: idr handle * @p_id: pointer to the allocated handle * * Simple wrapper around ida_get_new_above() w/ @starting_id of zero. */ static inline int ida_get_new(struct ida *ida, int *p_id) { return ida_get_new_above(ida, 0, p_id); } void __init idr_init_cache(void); #endif /* __IDR_H__ */