在我们实际编程中,有时候需要做这么一件事情..就是一个ID对应一个地址..就好像你的身份证对应你的人一样,只要知道号.就能快速的找到与之对应的地址.有人说,用个数组不就行了..但是数组是定长的,不方便.那用链表行不行,链表行是行了.但是链表的查找很慢,尤其是数据一旦多了.又万一要找的数据是最后一个,那咋办..岂不是得遍历每一个....有没有什么好的办法能直接快速定位到要找的地址呢....
我们设想下.在32位操作系统中,典型的数据类型为 int 也就是4字节.如果将这个4字节中的每一个位表示一个数据.那么就可以用一个unsigned int来表示32个地址了.然后根据这个4字节内的值,就可以快速的找到对应的地址了...方便多了.但是这么一来.只能存32个值...那如果将这个32个地址和对应的4字节的bitmap组成结构体.用bitmap描述一个32的数组....接着用bitmap原本描述地址的,用来存储这个结构体本身..这样构建起2层的树形结构.岂不是可以描述1024个地址了..而顶层仅仅使用了一个4字节的bitmap来描述...又扩大了使用的地址范围了...而继续刚刚的,,1024 远远没有达到4字节的最大值..那岂不是浪费..所以继续增加树的层数.3层树那就是32768,4层树就是1048576....6层就是1073741824 7层就超过4字节所能表达的最大值了...具体怎么实现呢...下面就来分析下kernel中idr机制..就是上面描述的那样...
首先我先声明.我这里分析的代码是从linux2.6.36中提取出来的.并在vs2010中编译测试过..由于kernel中有一些有的没有函数.我去掉了...不影响整体..相信看懂这个代码,再去看kernel会一目了然...
struct __idr_layer {
unsigned long bitmap; /* A zero bit means "space here" */
struct __idr_layer *ary[1<
上面的就是idr所涉及的结构体..上面已经有了很多注释了...其中LINUX_LOCK部分,是我自己修改的.因为我的这段代码提取出来主要用在应用程序中...所以定义了平台相关的多线程同步机制..
/* 根据ID查找对应的地址 */
void* find(int id);
/* 操作之前的准备,用于申请layer,存入空闲区 */
int pre_get();
/* 将ptr对应id,id为自动计算 */
int get_new(void *ptr, int *id);
/* 将ptr对应id,id为starting_id开始的号 */
int get_new_above(void *ptr, int starting_id, int *id);
/* 遍历每一个节点,并调用fn函数 */
int each(int (*fn)(int id, void *p, void *data), void *data);
/* 获得nextidp的下一个地址,nextidp返回下一个id值 */
void* get_next(int *nextidp);
/* 替换指定ID值中的存储地址 */
void* replace(void *ptr, int id);
/* 解除指定id值对应的地址 */
void remove(int id);
/* 清空top树中所有的内容 */
void remove_all();
/* 清空整个idr,包涵free_layer区域 */
void destroy();
/* 初始化idr构建lock机制 */
void init();
上面就是idr的所有操作了..下面我们先看一下idr的基本使用方法.我们按照使用方法进行分析..
#include "idr.h"
int main(int argc, char* argv[])
{
idr _id;
int i = 10;
while(i--){
int ret = -10;
int id = i;
do{
if(_id.pre_get())
ret = _id.get_new((void*)i,&id);
}while(ret == -idr::EAGAIN);
}
i = 10;
void* val;
while(i--){
val = _id.find(i);
}
_id.destroy();
return 0;
}
参看代码以及上面对函数的基本解释.可以看懂这部分在干什么了..下面开始从构造函数idr::idr开始分析...
idr::idr(void)
{
init();
}
idr::~idr(void)
{
destroy();
}
void idr::destroy()
{
remove_all();
while (m_idp.id_free_cnt) {
struct __idr_layer *p = get_from_free_list(&m_idp); //清空free中的节点
delete p;
}
lock_destroy();
}
void idr::init()
{
memset(&m_idp, 0, sizeof(struct __idr));
lock_init();
}
构造函数仅仅就是将idr结构体清空,如果使用锁机制,就初始化锁...接着分析pre_get()函数.该函数是分配layer到空闲区域...已被在进行分配id->prt过程中随时可以得到layer.
int idr::pre_get()
{
/* 循环申请layer,存入free_区域 */
while (m_idp.id_free_cnt < IDR_FREE_MAX) {
struct __idr_layer *nnew;
nnew = (struct __idr_layer*) new __idr_layer;
if (nnew == NULL)
return (0);
memset(nnew, 0, sizeof(struct __idr_layer));
move_to_free_list(&m_idp, nnew);
}
return 1;
}
void idr::__move_to_free_list(struct __idr *idp, struct __idr_layer *p)
{
p->ary[0] = idp->id_free;
idp->id_free = p;
idp->id_free_cnt++;
}
void idr::move_to_free_list(struct __idr *idp, struct __idr_layer *p)
{
// unsigned long flags;
/*
* Depends on the return element being zeroed.
*/
lock_lock();
__move_to_free_list(idp, p);
lock_unlock();
}
看的时候可以有些郁闷,好我给大家看个图..最终会变成这样的布局...
其中id_free_cnt等于14(这是一个宏.回头看了代码就知道了.是个固定值..)而layer形成了一个链表.每次idr需要取layer的时候,都直接取最后一个.然后id_free = id_free->ary[0];也就是之前一个.好.这个应该很好理解..
接着是get_new这个函数...这里是整个idr的核心部分
int idr::get_new(void *ptr, int *id)
{
int rv;
/* 调用idr_get_new_above_int绑定id到ptr,id从0开始.自动计算 */
rv = idr_get_new_above_int(&m_idp, ptr, 0);
/*
* This is a cheap hack until the IDR code can be fixed to
* return proper error values.
*/
if (rv < 0)
return _idr_rc_to_errno(rv);
/* 返回新的id号 */
*id = rv;
return 0;
}
int idr::idr_get_new_above_int(struct __idr *idp, void *ptr, int starting_id)
{
struct __idr_layer *pa[MAX_LEVEL];
int id;
/*
根据starting_id获取空闲id,会自动分配layer,以及树的增长
pa中存放依次存放叶子节点到top的layer层次指针
*/
id = idr_get_empty_slot(&m_idp, starting_id, pa);
if (id >= 0) {
/*
* Successfully found an empty slot. Install the user
* pointer and mark the slot full.
*/
/* id关联ptr */
pa[0]->ary[id & IDR_MASK] = (struct __idr_layer *)ptr;
pa[0]->count++;
/* 标志该节点已被使用bitmap中置位 */
idr_mark_full(pa, id);
}
return id;
}
int idr::idr_get_empty_slot(struct __idr *idp, int starting_id,struct __idr_layer **pa)
{
struct __idr_layer *p, *nnew;
int layers, v, id;
id = starting_id;
build_up:
p = idp->top;
layers = idp->layers;
/* 如果第一次使用,则top为NULL获取top的layer. */
if (!p) {
if (!(p = get_from_free_list(idp)))
return -1;
p->layer = 0;
layers = 1;
}
/*
* Add a new layer to the top of the tree if the requested
* id is larger than the currently allocated space.
*/
while ((layers < (MAX_LEVEL - 1)) && (id >= (1 << (layers*IDR_BITS)))) {
/* 树增长 */
layers++;
if (!p->count) {
/* special case: if the tree is currently empty,
* then we grow the tree by moving the top node
* upwards.
*/
p->layer++;
continue;
}
/* 获取新的layer,作为top.将原本的top作为该新的top的子节点 */
if (!(nnew = get_from_free_list(idp))) {
/*
* The allocation failed. If we built part of
* the structure tear it down.
*/
lock_lock();
for (nnew = p; p && p != idp->top; nnew = p) {
p = p->ary[0];
nnew->ary[0] = NULL;
nnew->bitmap = nnew->count = 0;
__move_to_free_list(idp, nnew);
}
lock_unlock();
return -1;
}
/* 设置新的top */
nnew->ary[0] = p;
nnew->count = 1;
nnew->layer = layers-1;
/* 若之前的top为满,则标志该节点对应的这一位为1 */
if (p->bitmap == IDR_FULL)
__set_bit(0, &nnew->bitmap);
p = nnew;
}
idp->top = p;
idp->layers = layers;
/* 获取id.从idr树中,会自动增加缺少的top的子节点 */
v = sub_alloc(idp, &id, pa);
if (v == IDR_NEED_TO_GROW)
goto build_up;
return(v);
}
void idr::idr_mark_full(struct __idr_layer **pa, int id)
{
struct __idr_layer *p = pa[0];
int l = 0;
/* 根据id设置bitmap */
__set_bit(id & IDR_MASK, &p->bitmap);
/*
* If this layer is full mark the bit in the layer above to
* show that this part of the radix tree is full. This may+ [0x6] 0x00000000 {bitmap=??? ary=0x00000004 count=??? ...} idr_layer *
* complete the layer above and require walking up the radix
* tree.
*/
/* 若整个layer节点为满,则标志该layer的父节点对应的位为1 */
while (p->bitmap == IDR_FULL) {
if (!(p = pa[++l]))
break;
id = id >> IDR_BITS;
__set_bit((id & IDR_MASK), &p->bitmap);
}
}
int idr::sub_alloc(struct __idr *idp, int *starting_id, struct __idr_layer **pa)
{
int n, m, sh;
struct __idr_layer *p, *nnew;
int l, id, oid;
unsigned long bm;
id = *starting_id;
restart:
p = idp->top;
l = idp->layers;
/* 设置最后一个为NULL用于判断到达顶层 */
pa[l--] = NULL;
while (1) {
/*
* We run around this while until we reach the leaf node...
*/
/* 计算n,为该layer中的哪个位置(0~31) */
n = (id >> (IDR_BITS*l)) & IDR_MASK;
bm = ~p->bitmap;
/* 根据bm和n计算获得下一个空闲位置 */
m = find_next_bit(&bm, IDR_SIZE, n);
/* 如果空闲位置==IDR_SIZE(32),表示已经满了,则需要增长树 */
if (m == IDR_SIZE) {
/* no space available go back to previous layer. */
l++;
oid = id;
/* 重新计算id,该id为被增长之后的新值 */
id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1;
/* if already at the top layer, we need to grow */
if (id >= 1 << (idp->layers * IDR_BITS)) {
*starting_id = id;
/* 返回上一层,增长树 */
return IDR_NEED_TO_GROW;
}
p = pa[l];
// BUG_ON(!p);
/* If we need to go up one layer, continue the
* loop; otherwise, restart from the top.
*/
sh = IDR_BITS * (l + 1);
if (oid >> sh == id >> sh)
continue;
else
goto restart;
}
/* 调整id号 */
if (m != n) {
sh = IDR_BITS*l;
id = ((id >> sh) ^ n ^ m) << sh;
}
if ((id >= MAX_ID_BIT) || (id < 0))
return IDR_NOMORE_SPACE;
/* 最终所有的操作,都会循环到l==0这边.因为所有的ptr地址,都保存在第0层的页节点上 */
if (l == 0)
break;
/*
* Create the layer below if it is missing.
*/
/* 新增缺少的layer节点,并根据id获取对应的节点 */
if (!p->ary[m]) {
nnew = get_from_free_list(idp);
if (!nnew)
return -1;
nnew->layer = l-1;
p->ary[m] = nnew;
p->count++;
}
/* 指向下层新的layer节点,保存p地址,到pa中 */
pa[l--] = p;
p = p->ary[m];
}
pa[l] = p;
return id;
}
我大部分都已经注释了...下面看下在单层情况下是什么布局
在idr.layers == 1 的情况就是上面这图所示,所有的ptr都落在ary对应的地址区域...而对应得到的id值就是0到31.也就是5位..用4字节的低5位表示0到31 这32个地址对应的区域..下面再看下2层的情况
从前副图中,我们总结下..在1层中,id最大值为1 << 5(32只需要5个二进制位) * 1 = 在2层中1 << 5(32只需要5个二进制位) * 2 在2层的情况中,仅仅覆盖了4字节中的32^3次方 32768 个id号..所以这颗树可以继续增长..直到4字节的最大值
好..看下第三层的图示吧...这也是最后一张图了..剩下的没有画..太大了...继续想象吧...
我们从3层中想象下,如何通过id来找到指定的ptr.首先假设id值为12345;对应的二进制为0b 1 00110 10011 我们说过每5位表示一个layer的底层32位值.把么首先从顶层0b1找到idr->top.ary[1]->ary[0b00110]->ary[10011]得到的,就是该id对应的ptr了...
void* idr::find(int id)
{
int n;
struct __idr_layer *p;
/* p指向顶层 */
p = m_idp.top;
if (!p)
return NULL;
/* 计算当前整颗树能放置多少页节点 */
n = (p->layer+1) * IDR_BITS;
/* Mask off upper bits we don't use for the search. */
id &= MAX_ID_MASK;
if (id >= (1 << n))
return NULL;
/* 从id中每IDR_BITS对应一个地址,从top开始,依次取出layer找到底层的layer获取ptr地址 */
while (n > 0 && p) {
n -= IDR_BITS;
p = p->ary[(id >> n) & IDR_MASK];
}
return((void *)p);
}
为了验证我说的是不是对的,直接看下代码.来看看find函数是怎么找到id对应的ptr的....上面已经有注释了,就不多说了....
到这里大部分已经讲完了..剩下的部分.自己慢慢分析了....最后我贴出我整理的代码..希望能帮助大家...谢谢
idr.h
#ifndef __IDR_H__
#define __IDR_H__
/* 定义系统平台 */
#define SYSTEM_LINUX 1
#define SYSTEM_WINDOWS 2
/* 选择系统平台 */
#define SYSTEM_TYPE SYSTEM_WINDOWS
#define BITS_PER_LONG 32
#define USE_LOCK
/* 使用多线程锁机制 */
#if defined(USE_LOCK)
# if SYSTEM_TYPE == SYSTEM_LINUX
# define LINUX_LOCK
# endif /* SYSTEM_TYPE == SYSTEM_LINUX */
#endif /* defined(USE_LOCK) */
/* 包含系统平台头文件 */
#if defined(LINUX_LOCK)
#include
#endif /* defined(LINUX_LOCK) */
#if BITS_PER_LONG == 32
# define IDR_BITS 5
# define IDR_FULL 0xfffffffful
/* We can only use two of the bits in the top level because there is
only one possible bit in the top level (5 bits * 7 levels = 35
bits, but you only use 31 bits in the id). */
# define TOP_LEVEL_FULL (IDR_FULL >> 30)
#elif BITS_PER_LONG == 64
# define IDR_BITS 6
# define IDR_FULL 0xfffffffffffffffful
/* We can only use two of the bits in the top level because there is
only one possible bit in the top level (6 bits * 6 levels = 36
bits, but you only use 31 bits in the id). */
# define TOP_LEVEL_FULL (IDR_FULL >> 62)
#else
# error "BITS_PER_LONG is not 32 or 64"
#endif /* BITS_PER_LONG == 32 */
#define IDR_SIZE (1 << IDR_BITS)
#define IDR_MASK ((1 << IDR_BITS)-1)
#define MAX_ID_SHIFT (sizeof(int)*8 - 1)
#define MAX_ID_BIT (1U << MAX_ID_SHIFT)
#define MAX_ID_MASK (MAX_ID_BIT - 1)
/* Leave the possibility of an incomplete final layer */
#define MAX_LEVEL (MAX_ID_SHIFT + IDR_BITS - 1) / IDR_BITS
/* Number of id_layer structs to leave in free list */
/* 最大空闲区域layer个数 */
#define IDR_FREE_MAX MAX_LEVEL + MAX_LEVEL
#define _idr_rc_to_errno(rc) ((rc) == -1 ? -EAGAIN : -ENOSPC)
#define IDR_NEED_TO_GROW -2
#define IDR_NOMORE_SPACE -3
class idr
{
struct __idr_layer {
unsigned long bitmap; /* A zero bit means "space here" */
struct __idr_layer *ary[1<p 存放到指定的idr的空闲区中,此处仅仅是加锁而已 */
void move_to_free_list(struct __idr *idp, struct __idr_layer *p);
/* 将layer->p 存放到指定的idr的空闲区中,若使用锁机制,保证该函数被执行在加锁中 */
void __move_to_free_list(struct __idr *idp, struct __idr_layer *p);
/* */
int idr_get_new_above_int(struct __idr *idp, void *ptr, int starting_id);
/* 从指定的id号开始,去获取空闲的id对应的位置,返回空闲的id号 */
int idr_get_empty_slot(struct __idr *idp, int starting_id,struct __idr_layer **pa);
/* 设置id号对应的位被置位,并且如果是多层树结构,则该层满之后,将上层置位 */
void idr_mark_full(struct __idr_layer **pa, int id);
/* 置位 */
void __set_bit(int nr, volatile unsigned long *addr);
/* 清除位 */
void __clear_bit(int nr, volatile unsigned long *addr);
/* 测试位 */
int test_bit(unsigned int nr, const unsigned long *addr);
/* 子叶分配,以及计算id值,并返回id值..pa为数组.从0->依次存放该节点的父节点指针 */
int sub_alloc(struct __idr *idp, int *starting_id, struct __idr_layer **pa);
/* 找到下一个可用的位,并返回该位的编号 */
unsigned long find_next_bit( const unsigned long *addr, unsigned long size,
unsigned long offset);
unsigned long __ffs(unsigned long word);
int fls(int x);
inline void* ERR_PTR(long error)
{
return (void *) error;
}
void free_layer(struct __idr_layer *p);
void sub_remove(struct __idr *idp, int shift, int id);
void idr_remove_warning(int id);
private:
struct __idr m_idp;
};
#endif /* __IDR_H__ */
idr.cpp
#include "idr.h"
#include
idr::idr(void)
{
init();
}
idr::~idr(void)
{
destroy();
}
void* idr::find(int id)
{
int n;
struct __idr_layer *p;
/* p指向顶层 */
p = m_idp.top;
if (!p)
return NULL;
/* 计算当前整颗树能放置多少页节点 */
n = (p->layer+1) * IDR_BITS;
/* Mask off upper bits we don't use for the search. */
id &= MAX_ID_MASK;
if (id >= (1 << n))
return NULL;
/* 从id中每IDR_BITS对应一个地址,从top开始,依次取出layer找到底层的layer获取ptr地址 */
while (n > 0 && p) {
n -= IDR_BITS;
p = p->ary[(id >> n) & IDR_MASK];
}
return((void *)p);
}
int idr::pre_get()
{
/* 循环申请layer,存入free_区域 */
while (m_idp.id_free_cnt < IDR_FREE_MAX) {
struct __idr_layer *nnew;
nnew = (struct __idr_layer*) new __idr_layer;
if (nnew == NULL)
return (0);
memset(nnew, 0, sizeof(struct __idr_layer));
move_to_free_list(&m_idp, nnew);
}
return 1;
}
int idr::get_new(void *ptr, int *id)
{
int rv;
/* 调用idr_get_new_above_int绑定id到ptr,id从0开始.自动计算 */
rv = idr_get_new_above_int(&m_idp, ptr, 0);
/*
* This is a cheap hack until the IDR code can be fixed to
* return proper error values.
*/
if (rv < 0)
return _idr_rc_to_errno(rv);
/* 返回新的id号 */
*id = rv;
return 0;
}
int idr::get_new_above(void *ptr, int starting_id, int *id)
{
int rv;
/* 调用idr_get_new_above_int绑定id到ptr,id从starting_id开始.自动计算 */
rv = idr_get_new_above_int(&m_idp, ptr, starting_id);
/*
* This is a cheap hack until the IDR code can be fixed to
* return proper error values.
*/
if (rv < 0)
return _idr_rc_to_errno(rv);
/* 返回新的id号 */
*id = rv;
return 0;
}
int idr::each(int (*fn)(int id, void *p, void *data), void *data)
{
int n, id, max, error = 0;
struct __idr_layer *p;
struct __idr_layer *pa[MAX_LEVEL];
struct __idr_layer **paa = &pa[0];
n = m_idp.layers * IDR_BITS;
/* p指向top */
p = m_idp.top;
/* 计算页节点的最大数量 */
max = 1 << n;
id = 0;
while (id < max) {
while (n > 0 && p) {
n -= IDR_BITS;
*paa++ = p;
p = p->ary[(id >> n) & IDR_MASK];
}
/* callback函数调用 */
if (p) {
error = fn(id, (void *)p, data);
if (error)
break;
}
id += 1 << n;
while (n < fls(id)) {
n += IDR_BITS;
p = *--paa;
}
}
return error;
}
void* idr::get_next(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 = m_idp.layers * IDR_BITS;
max = 1 << n;
p = m_idp.top;
if (!p)
return NULL;
while (id < max) {
while (n > 0 && p) {
n -= IDR_BITS;
*paa++ = p;
p = 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;
}
void* idr::replace(void *ptr, int id)
{
int n;
struct __idr_layer *p, *old_p;
p = m_idp.top;
if (!p)
return ERR_PTR(-EINVAL);
n = (p->layer+1) * IDR_BITS;
id &= MAX_ID_MASK;
if (id >= (1 << n))
return ERR_PTR(-EINVAL);
/* 找到id对应的layer节点 */
n -= IDR_BITS;
while ((n > 0) && p) {
p = p->ary[(id >> n) & IDR_MASK];
n -= IDR_BITS;
}
n = id & IDR_MASK;
if (p == NULL || !test_bit(n, &p->bitmap))
return ERR_PTR(-ENOENT);
/* 替换id对应的ptr为新的ptr */
old_p = p->ary[n];
p->ary[n] = (__idr_layer*)ptr;
/* 返回旧的ptr地址 */
return old_p;
}
void idr::remove(int id)
{
struct __idr_layer *p;
struct __idr_layer *to_free;
/* Mask off upper bits we don't use for the search. */
id &= MAX_ID_MASK;
sub_remove(&m_idp, (m_idp.layers - 1) * IDR_BITS, id);
if (m_idp.top && m_idp.top->count == 1 && (m_idp.layers > 1) &&
m_idp.top->ary[0]) {
/*
* Single child at leftmost slot: we can shrink the tree.
* This level is not needed anymore since when layers are
* inserted, they are inserted at the top of the existing
* tree.
*/
to_free = m_idp.top;
p = m_idp.top->ary[0];
m_idp.top = p;
--m_idp.layers;
to_free->bitmap = to_free->count = 0;
free_layer(to_free);
}
while (m_idp.id_free_cnt >= IDR_FREE_MAX) {
p = get_from_free_list(&m_idp);
/*
* Note: we don't call the rcu callback here, since the only
* layers that fall into the freelist are those that have been
* preallocated.
*/
delete p;
}
return;
}
void idr::remove_all()
{
int n, id, max;
int bt_mask;
struct __idr_layer *p;
struct __idr_layer *pa[MAX_LEVEL];
struct __idr_layer **paa = &pa[0];
n = m_idp.layers * IDR_BITS;
p = m_idp.top;
m_idp.top = NULL;
max = 1 << n;
id = 0;
while (id < max) {
while (n > IDR_BITS && p) {
n -= IDR_BITS;
*paa++ = p;
p = p->ary[(id >> n) & IDR_MASK];
}
bt_mask = id;
id += 1 << n;
/* Get the highest bit that the above add changed from 0->1. */
while (n < fls(id ^ bt_mask)) {
if (p)
free_layer(p);
n += IDR_BITS;
p = *--paa;
}
}
m_idp.layers = 0;
}
void idr::destroy()
{
remove_all();
while (m_idp.id_free_cnt) {
struct __idr_layer *p = get_from_free_list(&m_idp);
delete p;
}
lock_destroy();
}
void idr::init()
{
memset(&m_idp, 0, sizeof(struct __idr));
lock_init();
}
/***************************private function****************************/
idr::__idr_layer* idr::get_from_free_list(struct __idr *idp)
{
struct __idr_layer *p;
lock_lock();
if ((p = m_idp.id_free)) {
/* 从空闲区摘取一个layer */
m_idp.id_free = p->ary[0];
m_idp.id_free_cnt--;
p->ary[0] = NULL;
}
lock_unlock();
return(p);
}
void idr::__move_to_free_list(struct __idr *idp, struct __idr_layer *p)
{
p->ary[0] = idp->id_free;
idp->id_free = p;
idp->id_free_cnt++;
}
void idr::move_to_free_list(struct __idr *idp, struct __idr_layer *p)
{
// unsigned long flags;
/*
* Depends on the return element being zeroed.
*/
lock_lock();
__move_to_free_list(idp, p);
lock_unlock();
}
int idr::idr_get_new_above_int(struct __idr *idp, void *ptr, int starting_id)
{
struct __idr_layer *pa[MAX_LEVEL];
int id;
/*
根据starting_id获取空闲id,会自动分配layer,以及树的增长
pa中存放依次存放叶子节点到top的layer层次指针
*/
id = idr_get_empty_slot(&m_idp, starting_id, pa);
if (id >= 0) {
/*
* Successfully found an empty slot. Install the user
* pointer and mark the slot full.
*/
/* id关联ptr */
pa[0]->ary[id & IDR_MASK] = (struct __idr_layer *)ptr;
pa[0]->count++;
/* 标志该节点已被使用bitmap中置位 */
idr_mark_full(pa, id);
}
return id;
}
int idr::idr_get_empty_slot(struct __idr *idp, int starting_id,struct __idr_layer **pa)
{
struct __idr_layer *p, *nnew;
int layers, v, id;
id = starting_id;
build_up:
p = idp->top;
layers = idp->layers;
/* 如果第一次使用,则top为NULL获取top的layer. */
if (!p) {
if (!(p = get_from_free_list(idp)))
return -1;
p->layer = 0;
layers = 1;
}
/*
* Add a new layer to the top of the tree if the requested
* id is larger than the currently allocated space.
*/
while ((layers < (MAX_LEVEL - 1)) && (id >= (1 << (layers*IDR_BITS)))) {
/* 树增长 */
layers++;
if (!p->count) {
/* special case: if the tree is currently empty,
* then we grow the tree by moving the top node
* upwards.
*/
p->layer++;
continue;
}
/* 获取新的layer,作为top.将原本的top作为该新的top的子节点 */
if (!(nnew = get_from_free_list(idp))) {
/*
* The allocation failed. If we built part of
* the structure tear it down.
*/
lock_lock();
for (nnew = p; p && p != idp->top; nnew = p) {
p = p->ary[0];
nnew->ary[0] = NULL;
nnew->bitmap = nnew->count = 0;
__move_to_free_list(idp, nnew);
}
lock_unlock();
return -1;
}
/* 设置新的top */
nnew->ary[0] = p;
nnew->count = 1;
nnew->layer = layers-1;
/* 若之前的top为满,则标志该节点对应的这一位为1 */
if (p->bitmap == IDR_FULL)
__set_bit(0, &nnew->bitmap);
p = nnew;
}
idp->top = p;
idp->layers = layers;
/* 获取id.从idr树中,会自动增加缺少的top的子节点 */
v = sub_alloc(idp, &id, pa);
if (v == IDR_NEED_TO_GROW)
goto build_up;
return(v);
}
void idr::idr_mark_full(struct __idr_layer **pa, int id)
{
struct __idr_layer *p = pa[0];
int l = 0;
/* 根据id设置bitmap */
__set_bit(id & IDR_MASK, &p->bitmap);
/*
* If this layer is full mark the bit in the layer above to
* show that this part of the radix tree is full. This may+ [0x6] 0x00000000 {bitmap=??? ary=0x00000004 count=??? ...} idr_layer *
* complete the layer above and require walking up the radix
* tree.
*/
/* 若整个layer节点为满,则标志该layer的父节点对应的位为1 */
while (p->bitmap == IDR_FULL) {
if (!(p = pa[++l]))
break;
id = id >> IDR_BITS;
__set_bit((id & IDR_MASK), &p->bitmap);
}
}
int idr::sub_alloc(struct __idr *idp, int *starting_id, struct __idr_layer **pa)
{
int n, m, sh;
struct __idr_layer *p, *nnew;
int l, id, oid;
unsigned long bm;
id = *starting_id;
restart:
p = idp->top;
l = idp->layers;
/* 设置最后一个为NULL用于判断到达顶层 */
pa[l--] = NULL;
while (1) {
/*
* We run around this while until we reach the leaf node...
*/
/* 计算n,为该layer中的哪个位置(0~31) */
n = (id >> (IDR_BITS*l)) & IDR_MASK;
bm = ~p->bitmap;
/* 根据bm和n计算获得下一个空闲位置 */
m = find_next_bit(&bm, IDR_SIZE, n);
/* 如果空闲位置==IDR_SIZE(32),表示已经满了,则需要增长树 */
if (m == IDR_SIZE) {
/* no space available go back to previous layer. */
l++;
oid = id;
/* 重新计算id,该id为被增长之后的新值 */
id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1;
/* if already at the top layer, we need to grow */
if (id >= 1 << (idp->layers * IDR_BITS)) {
*starting_id = id;
/* 返回上一层,增长树 */
return IDR_NEED_TO_GROW;
}
p = pa[l];
// BUG_ON(!p);
/* If we need to go up one layer, continue the
* loop; otherwise, restart from the top.
*/
sh = IDR_BITS * (l + 1);
if (oid >> sh == id >> sh)
continue;
else
goto restart;
}
/* 调整id号 */
if (m != n) {
sh = IDR_BITS*l;
id = ((id >> sh) ^ n ^ m) << sh;
}
if ((id >= MAX_ID_BIT) || (id < 0))
return IDR_NOMORE_SPACE;
/* 最终所有的操作,都会循环到l==0这边.因为所有的ptr地址,都保存在第0层的页节点上 */
if (l == 0)
break;
/*
* Create the layer below if it is missing.
*/
/* 新增缺少的layer节点,并根据id获取对应的节点 */
if (!p->ary[m]) {
nnew = get_from_free_list(idp);
if (!nnew)
return -1;
nnew->layer = l-1;
p->ary[m] = nnew;
p->count++;
}
/* 指向下层新的layer节点,保存p地址,到pa中 */
pa[l--] = p;
p = p->ary[m];
}
pa[l] = p;
return id;
}
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
void idr::__set_bit(int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
*p |= mask;
}
int idr::test_bit(unsigned int nr, const unsigned long *addr)
{
return ((1UL << (nr % BITS_PER_LONG)) &
(((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
}
void idr::__clear_bit(int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
*p &= ~mask;
}
unsigned long idr::find_next_bit( const unsigned long *addr, unsigned long size,
unsigned long offset)
{
const unsigned long *p = addr + BIT_WORD(offset);
unsigned long result = offset & ~(BITS_PER_LONG-1);
unsigned long tmp;
if (offset >= size)
return size;
size -= result;
offset %= BITS_PER_LONG;
if (offset) {
tmp = *(p++);
tmp &= (~0UL << offset);
if (size < BITS_PER_LONG)
goto found_first;
if (tmp)
goto found_middle;
size -= BITS_PER_LONG;
result += BITS_PER_LONG;
}
while (size & ~(BITS_PER_LONG-1)) {
if ((tmp = *(p++)))
goto found_middle;
result += BITS_PER_LONG;
size -= BITS_PER_LONG;
}
if (!size)
return result;
tmp = *p;
found_first:
tmp &= (~0UL >> (BITS_PER_LONG - size));
if (tmp == 0UL) /* Are any bits set? */
return result + size; /* Nope. */
found_middle:
return result + __ffs(tmp);
}
unsigned long idr::__ffs(unsigned long word)
{
int num = 0;
#if BITS_PER_LONG == 64
if ((word & 0xffffffff) == 0) {
num += 32;
word >>= 32;
}
#endif
if ((word & 0xffff) == 0) {
num += 16;
word >>= 16;
}
if ((word & 0xff) == 0) {
num += 8;
word >>= 8;
}
if ((word & 0xf) == 0) {
num += 4;
word >>= 4;
}
if ((word & 0x3) == 0) {
num += 2;
word >>= 2;
}
if ((word & 0x1) == 0)
num += 1;
return num;
}
int idr::fls(int x)
{
int r = 32;
if (!x)
return 0;
if (!(x & 0xffff0000u)) {
x <<= 16;
r -= 16;
}
if (!(x & 0xff000000u)) {
x <<= 8;
r -= 8;
}
if (!(x & 0xf0000000u)) {
x <<= 4;
r -= 4;
}
if (!(x & 0xc0000000u)) {
x <<= 2;
r -= 2;
}
if (!(x & 0x80000000u)) {
x <<= 1;
r -= 1;
}
return r;
}
void idr::sub_remove(struct __idr *idp, int shift, int id)
{
struct __idr_layer *p = idp->top;
struct __idr_layer **pa[MAX_LEVEL];
struct __idr_layer ***paa = &pa[0];
struct __idr_layer *to_free;
int n;
*paa = NULL;
*++paa = &idp->top;
while ((shift > 0) && p) {
n = (id >> shift) & IDR_MASK;
__clear_bit(n, &p->bitmap);
*++paa = &p->ary[n];
p = p->ary[n];
shift -= IDR_BITS;
}
n = id & IDR_MASK;
if (p != NULL && test_bit(n, &p->bitmap)){
__clear_bit(n, &p->bitmap);
p->ary[n] = NULL;
to_free = NULL;
while(*paa && ! --((**paa)->count)){
if (to_free)
free_layer(to_free);
to_free = **paa;
**paa-- = NULL;
}
if (!*paa)
idp->layers = 0;
if (to_free)
free_layer(to_free);
} else
idr_remove_warning(id);
}
void idr::free_layer(struct __idr_layer *p)
{
}
void idr::idr_remove_warning(int id)
{
// printf("idr_remove called for id=%d which is not allocated.\n", id);
}