idr.h 7.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10
/*
 * 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.
 */
11 12 13 14

#ifndef __IDR_H__
#define __IDR_H__

L
Linus Torvalds 已提交
15 16
#include <linux/types.h>
#include <linux/bitops.h>
17
#include <linux/init.h>
N
Nadia Derbey 已提交
18
#include <linux/rcupdate.h>
L
Linus Torvalds 已提交
19

T
Tejun Heo 已提交
20 21 22 23 24 25 26
/*
 * 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
L
Linus Torvalds 已提交
27 28 29 30
#define IDR_SIZE (1 << IDR_BITS)
#define IDR_MASK ((1 << IDR_BITS)-1)

struct idr_layer {
T
Tejun Heo 已提交
31
	int			prefix;	/* the ID prefix of this idr_layer */
32
	DECLARE_BITMAP(bitmap, IDR_SIZE); /* A zero bit means "space here" */
A
Arnd Bergmann 已提交
33
	struct idr_layer __rcu	*ary[1<<IDR_BITS];
34 35 36
	int			count;	/* When zero, we can release it */
	int			layer;	/* distance from leaf */
	struct rcu_head		rcu_head;
L
Linus Torvalds 已提交
37 38 39
};

struct idr {
T
Tejun Heo 已提交
40
	struct idr_layer __rcu	*hint;	/* the last layer allocated from */
41 42 43 44
	struct idr_layer __rcu	*top;
	struct idr_layer	*id_free;
	int			layers;	/* only valid w/o concurrent changes */
	int			id_free_cnt;
J
Jeff Layton 已提交
45
	int			cur;	/* current pos for cyclic allocation */
46
	spinlock_t		lock;
L
Linus Torvalds 已提交
47 48
};

49 50 51
#define IDR_INIT(name)							\
{									\
	.lock			= __SPIN_LOCK_UNLOCKED(name.lock),	\
L
Linus Torvalds 已提交
52 53 54
}
#define DEFINE_IDR(name)	struct idr name = IDR_INIT(name)

N
Nadia Derbey 已提交
55
/**
56
 * DOC: idr sync
N
Nadia Derbey 已提交
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
 * idr synchronization (stolen from radix-tree.h)
 *
 * idr_find() is able to be called locklessly, using RCU. The caller must
 * ensure calls to this function are made within rcu_read_lock() regions.
 * Other readers (lock-free or otherwise) and modifications may be running
 * concurrently.
 *
 * It is still required that the caller manage the synchronization and
 * lifetimes of the items. So if RCU lock-free lookups are used, typically
 * this would mean that the items have their own locks, or are amenable to
 * lock-free access; and that the items are freed by RCU (or only freed after
 * having been deleted from the idr tree *and* a synchronize_rcu() grace
 * period).
 */

L
Linus Torvalds 已提交
72 73 74 75
/*
 * This is what we export.
 */

T
Tejun Heo 已提交
76
void *idr_find_slowpath(struct idr *idp, int id);
77 78
void idr_preload(gfp_t gfp_mask);
int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask);
J
Jeff Layton 已提交
79
int idr_alloc_cyclic(struct idr *idr, void *ptr, int start, int end, gfp_t gfp_mask);
K
Kristian Hoegsberg 已提交
80 81
int idr_for_each(struct idr *idp,
		 int (*fn)(int id, void *p, void *data), void *data);
K
KAMEZAWA Hiroyuki 已提交
82
void *idr_get_next(struct idr *idp, int *nextid);
J
Jeff Mahoney 已提交
83
void *idr_replace(struct idr *idp, void *ptr, int id);
L
Linus Torvalds 已提交
84
void idr_remove(struct idr *idp, int id);
A
Andrew Morton 已提交
85
void idr_destroy(struct idr *idp);
L
Linus Torvalds 已提交
86
void idr_init(struct idr *idp);
87

88 89 90 91 92 93 94 95 96 97 98
/**
 * idr_preload_end - end preload section started with idr_preload()
 *
 * Each idr_preload() should be matched with an invocation of this
 * function.  See idr_preload() for details.
 */
static inline void idr_preload_end(void)
{
	preempt_enable();
}

T
Tejun Heo 已提交
99 100
/**
 * idr_find - return pointer for given id
R
Randy Dunlap 已提交
101
 * @idr: idr handle
T
Tejun Heo 已提交
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
 * @id: lookup key
 *
 * Return the pointer given the id it has been registered with.  A %NULL
 * return indicates that @id is not valid or you passed %NULL in
 * idr_get_new().
 *
 * This function can be called under rcu_read_lock(), given that the leaf
 * pointers lifetimes are correctly managed.
 */
static inline void *idr_find(struct idr *idr, int id)
{
	struct idr_layer *hint = rcu_dereference_raw(idr->hint);

	if (hint && (id & ~IDR_MASK) == hint->prefix)
		return rcu_dereference_raw(hint->ary[id & IDR_MASK]);

	return idr_find_slowpath(idr, id);
}

121 122 123 124 125
/**
 * 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
126 127 128 129
 *
 * @entry and @id do not need to be initialized before the loop, and
 * after normal terminatinon @entry is left with the value NULL.  This
 * is convenient for a "not found" value.
130
 */
131 132
#define idr_for_each_entry(idp, entry, id)			\
	for (id = 0; ((entry) = idr_get_next(idp, &(id))) != NULL; ++id)
133

134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
/*
 * Don't use the following functions.  These exist only to suppress
 * deprecated warnings on EXPORT_SYMBOL()s.
 */
int __idr_pre_get(struct idr *idp, gfp_t gfp_mask);
int __idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
void __idr_remove_all(struct idr *idp);

/**
 * idr_pre_get - reserve resources for idr allocation
 * @idp:	idr handle
 * @gfp_mask:	memory allocation flags
 *
 * Part of old alloc interface.  This is going away.  Use
 * idr_preload[_end]() and idr_alloc() instead.
 */
static inline int __deprecated idr_pre_get(struct idr *idp, gfp_t gfp_mask)
{
	return __idr_pre_get(idp, gfp_mask);
}

/**
 * idr_get_new_above - allocate new idr entry above or equal to a start id
 * @idp: idr handle
 * @ptr: pointer you want associated with the id
 * @starting_id: id to start search at
 * @id: pointer to the allocated handle
 *
 * Part of old alloc interface.  This is going away.  Use
 * idr_preload[_end]() and idr_alloc() instead.
 */
static inline int __deprecated idr_get_new_above(struct idr *idp, void *ptr,
						 int starting_id, int *id)
{
	return __idr_get_new_above(idp, ptr, starting_id, 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
 *
 * Part of old alloc interface.  This is going away.  Use
 * idr_preload[_end]() and idr_alloc() instead.
 */
static inline int __deprecated idr_get_new(struct idr *idp, void *ptr, int *id)
{
	return __idr_get_new_above(idp, ptr, 0, id);
}
T
Tejun Heo 已提交
184 185 186 187 188 189 190 191 192 193 194 195

/**
 * 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);
}
196 197 198 199

/*
 * IDA - IDR based id allocator, use when translation from id to
 * pointer isn't necessary.
200 201 202
 *
 * IDA_BITMAP_LONGS is calculated to be one less to accommodate
 * ida_bitmap->nr_busy so that the whole struct fits in 128 bytes.
203 204
 */
#define IDA_CHUNK_SIZE		128	/* 128 bytes per chunk */
205 206
#define IDA_BITMAP_LONGS	(IDA_CHUNK_SIZE / sizeof(long) - 1)
#define IDA_BITMAP_BITS 	(IDA_BITMAP_LONGS * sizeof(long) * 8)
207 208 209 210 211 212 213 214 215 216 217

struct ida_bitmap {
	long			nr_busy;
	unsigned long		bitmap[IDA_BITMAP_LONGS];
};

struct ida {
	struct idr		idr;
	struct ida_bitmap	*free_bitmap;
};

218
#define IDA_INIT(name)		{ .idr = IDR_INIT((name).idr), .free_bitmap = NULL, }
219 220 221 222 223 224 225 226
#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);

227 228 229 230
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);

231
/**
232 233 234 235 236
 * 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.
237
 */
238 239 240 241 242 243
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);
244

245
#endif /* __IDR_H__ */