Blame view

include/linux/idr.h 5.93 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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.
   */
f668ab1ac   Luben Tuikov   include/linux: en...
11
12
13
  
  #ifndef __IDR_H__
  #define __IDR_H__
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
  #include <linux/types.h>
  #include <linux/bitops.h>
199f0ca51   Akinobu Mita   idr: create idr_l...
16
  #include <linux/init.h>
2027d1abc   Nadia Derbey   idr: change the i...
17
  #include <linux/rcupdate.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18

050a6b47d   Tejun Heo   idr: make idr_lay...
19
20
21
22
23
24
25
  /*
   * 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
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
  #define IDR_SIZE (1 << IDR_BITS)
  #define IDR_MASK ((1 << IDR_BITS)-1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  struct idr_layer {
54616283c   Tejun Heo   idr: add idr_laye...
29
  	int			prefix;	/* the ID prefix of this idr_layer */
dcbff5d1e   Lai Jiangshan   idr: reorder the ...
30
  	int			layer;	/* distance from leaf */
d2c2486bc   Arnd Bergmann   idr: __rcu annota...
31
  	struct idr_layer __rcu	*ary[1<<IDR_BITS];
4106ecaf5   Tejun Heo   idr: cosmetic upd...
32
  	int			count;	/* When zero, we can release it */
dcbff5d1e   Lai Jiangshan   idr: reorder the ...
33
34
35
36
37
  	union {
  		/* A zero bit means "space here" */
  		DECLARE_BITMAP(bitmap, IDR_SIZE);
  		struct rcu_head		rcu_head;
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
  };
  
  struct idr {
0ffc2a9c8   Tejun Heo   idr: implement lo...
41
  	struct idr_layer __rcu	*hint;	/* the last layer allocated from */
4106ecaf5   Tejun Heo   idr: cosmetic upd...
42
  	struct idr_layer __rcu	*top;
4106ecaf5   Tejun Heo   idr: cosmetic upd...
43
  	int			layers;	/* only valid w/o concurrent changes */
3e6628c4b   Jeff Layton   idr: introduce id...
44
  	int			cur;	/* current pos for cyclic allocation */
4106ecaf5   Tejun Heo   idr: cosmetic upd...
45
  	spinlock_t		lock;
dcbff5d1e   Lai Jiangshan   idr: reorder the ...
46
47
  	int			id_free_cnt;
  	struct idr_layer	*id_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
  };
4106ecaf5   Tejun Heo   idr: cosmetic upd...
49
50
51
  #define IDR_INIT(name)							\
  {									\
  	.lock			= __SPIN_LOCK_UNLOCKED(name.lock),	\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
  }
  #define DEFINE_IDR(name)	struct idr name = IDR_INIT(name)
f9c46d6ea   Nadia Derbey   idr: make idr_fin...
54
  /**
56083ab17   Randy Dunlap   docbook: add idr/...
55
   * DOC: idr sync
f9c46d6ea   Nadia Derbey   idr: make idr_fin...
56
57
58
59
60
61
62
63
64
65
66
67
68
69
   * 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).
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
  /*
   * This is what we export.
   */
0ffc2a9c8   Tejun Heo   idr: implement lo...
73
  void *idr_find_slowpath(struct idr *idp, int id);
d5c7409f7   Tejun Heo   idr: implement id...
74
75
  void idr_preload(gfp_t gfp_mask);
  int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask);
3e6628c4b   Jeff Layton   idr: introduce id...
76
  int idr_alloc_cyclic(struct idr *idr, void *ptr, int start, int end, gfp_t gfp_mask);
96d7fa421   Kristian Hoegsberg   lib: add idr_for_...
77
78
  int idr_for_each(struct idr *idp,
  		 int (*fn)(int id, void *p, void *data), void *data);
38460b48d   KAMEZAWA Hiroyuki   cgroup: CSS ID su...
79
  void *idr_get_next(struct idr *idp, int *nextid);
5806f07cd   Jeff Mahoney   [PATCH] lib: add ...
80
  void *idr_replace(struct idr *idp, void *ptr, int id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  void idr_remove(struct idr *idp, int id);
8d3b35914   Andrew Morton   [PATCH] inotify/i...
82
  void idr_destroy(struct idr *idp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  void idr_init(struct idr *idp);
05f7a7d6a   Andreas Gruenbacher   idr: Add new func...
84
  bool idr_is_empty(struct idr *idp);
f668ab1ac   Luben Tuikov   include/linux: en...
85

49038ef4f   Tejun Heo   idr: relocate idr...
86
  /**
d5c7409f7   Tejun Heo   idr: implement id...
87
88
89
90
91
92
93
94
95
96
97
   * 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();
  }
  
  /**
0ffc2a9c8   Tejun Heo   idr: implement lo...
98
   * idr_find - return pointer for given id
5857f70c8   Randy Dunlap   idr: fix new kern...
99
   * @idr: idr handle
0ffc2a9c8   Tejun Heo   idr: implement lo...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
   * @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);
  }
  
  /**
49038ef4f   Tejun Heo   idr: relocate idr...
120
121
122
123
   * 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
b949be585   George Spelvin   idr: document exi...
124
125
126
127
   *
   * @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.
49038ef4f   Tejun Heo   idr: relocate idr...
128
   */
b949be585   George Spelvin   idr: document exi...
129
130
  #define idr_for_each_entry(idp, entry, id)			\
  	for (id = 0; ((entry) = idr_get_next(idp, &(id))) != NULL; ++id)
49038ef4f   Tejun Heo   idr: relocate idr...
131

a55bbd375   Andreas Gruenbacher   drbd: Backport th...
132
133
134
135
136
137
138
139
140
141
142
143
144
  /**
   * idr_for_each_entry - continue iteration over an idr's elements of a given type
   * @idp:     idr handle
   * @entry:   the type * to use as cursor
   * @id:      id entry's key
   *
   * Continue to iterate over list of given type, continuing after
   * the current position.
   */
  #define idr_for_each_entry_continue(idp, entry, id)			\
  	for ((entry) = idr_get_next((idp), &(id));			\
  	     entry;							\
  	     ++id, (entry) = idr_get_next((idp), &(id)))
c8615d371   Tejun Heo   idr: deprecate id...
145
  /*
72dba584b   Tejun Heo   ida: implement id...
146
147
   * IDA - IDR based id allocator, use when translation from id to
   * pointer isn't necessary.
ed9f524ac   Namhyung Kim   ida: document IDA...
148
149
150
   *
   * IDA_BITMAP_LONGS is calculated to be one less to accommodate
   * ida_bitmap->nr_busy so that the whole struct fits in 128 bytes.
72dba584b   Tejun Heo   ida: implement id...
151
152
   */
  #define IDA_CHUNK_SIZE		128	/* 128 bytes per chunk */
ed9f524ac   Namhyung Kim   ida: document IDA...
153
154
  #define IDA_BITMAP_LONGS	(IDA_CHUNK_SIZE / sizeof(long) - 1)
  #define IDA_BITMAP_BITS 	(IDA_BITMAP_LONGS * sizeof(long) * 8)
72dba584b   Tejun Heo   ida: implement id...
155
156
157
158
159
160
161
162
163
164
  
  struct ida_bitmap {
  	long			nr_busy;
  	unsigned long		bitmap[IDA_BITMAP_LONGS];
  };
  
  struct ida {
  	struct idr		idr;
  	struct ida_bitmap	*free_bitmap;
  };
eece09ec2   Thomas Gleixner   locking: Various ...
165
  #define IDA_INIT(name)		{ .idr = IDR_INIT((name).idr), .free_bitmap = NULL, }
72dba584b   Tejun Heo   ida: implement id...
166
167
168
169
  #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);
72dba584b   Tejun Heo   ida: implement id...
170
171
172
  void ida_remove(struct ida *ida, int id);
  void ida_destroy(struct ida *ida);
  void ida_init(struct ida *ida);
88eca0207   Rusty Russell   ida: simplified f...
173
174
175
  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);
9749f30f1   Philipp Reisner   idr: idr_for_each...
176
  /**
49038ef4f   Tejun Heo   idr: relocate idr...
177
178
179
180
181
   * 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.
9749f30f1   Philipp Reisner   idr: idr_for_each...
182
   */
49038ef4f   Tejun Heo   idr: relocate idr...
183
184
185
186
187
188
  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);
9749f30f1   Philipp Reisner   idr: idr_for_each...
189

f668ab1ac   Luben Tuikov   include/linux: en...
190
  #endif /* __IDR_H__ */