diff options
| author | Ingo Molnar <mingo@elte.hu> | 2009-04-06 09:02:57 +0200 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-04-06 09:02:57 +0200 |
| commit | f541ae326fa120fa5c57433e4d9a133df212ce41 (patch) | |
| tree | bdbd94ec72cfc601118051cb35e8617d55510177 /lib/idr.c | |
| parent | e255357764f92afcafafbd4879b222b8c752065a (diff) | |
| parent | 0221c81b1b8eb0cbb6b30a0ced52ead32d2b4e4c (diff) | |
Merge branch 'linus' into perfcounters/core-v2
Merge reason: we have gathered quite a few conflicts, need to merge upstream
Conflicts:
arch/powerpc/kernel/Makefile
arch/x86/ia32/ia32entry.S
arch/x86/include/asm/hardirq.h
arch/x86/include/asm/unistd_32.h
arch/x86/include/asm/unistd_64.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/irq.c
arch/x86/kernel/syscall_table_32.S
arch/x86/mm/iomap_32.c
include/linux/sched.h
kernel/Makefile
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'lib/idr.c')
| -rw-r--r-- | lib/idr.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/lib/idr.c b/lib/idr.c index c11c5765cdef..80ca9aca038b 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -449,6 +449,7 @@ void idr_remove_all(struct idr *idp) n = idp->layers * IDR_BITS; p = idp->top; + rcu_assign_pointer(idp->top, NULL); max = 1 << n; id = 0; @@ -467,7 +468,6 @@ void idr_remove_all(struct idr *idp) p = *--paa; } } - rcu_assign_pointer(idp->top, NULL); idp->layers = 0; } EXPORT_SYMBOL(idr_remove_all); @@ -579,6 +579,52 @@ int idr_for_each(struct idr *idp, EXPORT_SYMBOL(idr_for_each); /** + * idr_get_next - lookup next object of id to given id. + * @idp: idr handle + * @id: pointer to lookup key + * + * Returns pointer to registered object with id, which is next number to + * given id. + */ + +void *idr_get_next(struct idr *idp, int *nextidp) +{ + struct idr_layer *p, *pa[MAX_LEVEL]; + struct idr_layer **paa = &pa[0]; + int id = *nextidp; + int n, max; + + /* find first ent */ + n = idp->layers * IDR_BITS; + max = 1 << n; + p = rcu_dereference(idp->top); + if (!p) + return NULL; + + while (id < max) { + while (n > 0 && p) { + n -= IDR_BITS; + *paa++ = p; + p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); + } + + if (p) { + *nextidp = id; + return p; + } + + id += 1 << n; + while (n < fls(id)) { + n += IDR_BITS; + p = *--paa; + } + } + return NULL; +} + + + +/** * idr_replace - replace pointer for given id * @idp: idr handle * @ptr: pointer you want associated with the id |
