idr机制(32叉树)

来源:互联网 发布:托福 一个月 知乎 编辑:程序博客网 时间:2024/06/04 19:38

一.结构体

1.idr结构体

[cpp] view plain copy
  1. struct idr {  
  2.     struct idr_layer __rcu *top;    //idr_layer顶层,32叉树的根  
  3.     struct idr_layer *id_free;      //指向idr_layer的空闲链表  
  4.     int layers;     //idr_layer的层数量  
  5.     int id_free_cnt;    //idr_layer空闲链表中剩余的idr_layer个数  
  6.     spinlock_t  lock;  
  7. };  

2.idr_layer结构体

[cpp] view plain copy
  1. struct idr_layer {  
  2.     unsigned long   bitmap; //标记位图,标记使用情况  
  3.     struct idr_layer __rcu  *ary[1<<IDR_BITS];        //子idr_layer数组ary[32]  
  4.     int count;  //ary数组使用情况  
  5.     int layer;  //层号  
  6.     struct rcu_head rcu_head;  
  7. };  

在32位系统中IDR_BITS的取值为5

[cpp] view plain copy
  1. #if BITS_PER_LONG == 32  
  2.     # define IDR_BITS 5  
  3.     # define IDR_FULL 0xfffffffful  
  4.     # define TOP_LEVEL_FULL (IDR_FULL >> 30)  
  5. #elif BITS_PER_LONG == 64  
  6.     # define IDR_BITS 6  
  7.     # define IDR_FULL 0xfffffffffffffffful  
  8.     # define TOP_LEVEL_FULL (IDR_FULL >> 62)  
  9. #else  
  10.     # error "BITS_PER_LONG is not 32 or 64"  
  11. #endif  

 

二.idr的初始化

[cpp] view plain copy
  1. #define IDR_INIT(name)      \  
  2. {               \  
  3.     .top        = NULL, \  
  4.     .id_free        = NULL, \  
  5.     .layers         = 0,    \  
  6.     .id_free_cnt    = 0,    \  
  7.     .lock       = __SPIN_LOCK_UNLOCKED(name.lock),  \  
  8. }  
  9. #define DEFINE_IDR(name)    struct idr name = IDR_INIT(name)  

定义一个idr结构体并赋值

三.分配id

1.idr_pre_get

[cpp] view plain copy
  1. int idr_pre_get(struct idr *idp, gfp_t gfp_mask)  
  2. {  
  3.     while (idp->id_free_cnt < IDR_FREE_MAX) { //IDR_FREE_MAX=14  
  4.         struct idr_layer *new;  //定义新的idr_layer结构体指针  
  5.         new = kmem_cache_zalloc(idr_layer_cache, gfp_mask); //分配*new内存空间  
  6.         if (new == NULL)  
  7.             return (0);  
  8.         move_to_free_list(idp, new);    //-->move_to_free_list  
  9.     }  
  10.     return 1;  
  11. }  
  12. EXPORT_SYMBOL(idr_pre_get);  

move_to_free_list

[cpp] view plain copy
  1. static void move_to_free_list(struct idr *idp, struct idr_layer *p)  
  2. {  
  3.     unsigned long flags;  
  4.     spin_lock_irqsave(&idp->lock, flags);  
  5.     __move_to_free_list(idp, p);    //-->__move_to_free_list  
  6.     spin_unlock_irqrestore(&idp->lock, flags);  
  7. }  

__move_to_free_list

[cpp] view plain copy
  1. static void __move_to_free_list(struct idr *idp, struct idr_layer *p)  
  2. {  
  3.     p->ary[0] = idp->id_free;  
  4.     idp->id_free = p;  
  5.     idp->id_free_cnt++;  
  6. }  

第一次循环结果

接着循环

再接着

一直这样下去直到循环结束(14次)

2.idr_get_new和idr_get_new_above

idr_get_new

[cpp] view plain copy
  1. int idr_get_new(struct idr *idp, void *ptr, int *id)  
  2. {  
  3.     int rv;  
  4.     rv = idr_get_new_above_int(idp, ptr, 0);  
  5.     if (rv < 0)  
  6.         return _idr_rc_to_errno(rv);  
  7.     *id = rv;  
  8.     return 0;  
  9. }  
  10. EXPORT_SYMBOL(idr_get_new);  

idr_get_new_above

[cpp] view plain copy
  1. int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)  
  2. {  
  3.     int rv;  
  4.     rv = idr_get_new_above_int(idp, ptr, starting_id);  
  5.     if (rv < 0)  
  6.         return _idr_rc_to_errno(rv);  
  7.     *id = rv;  
  8.     return 0;  
  9. }  
  10. EXPORT_SYMBOL(idr_get_new_above);  

两个函数都会调用idr_get_new_above_int函数,差别在于starting_id不同

下面分情况讨论,先以id为0走个过场

idr的top简称为根top,free简称为根free均为idr_layer指针类型,分别指向使用中和空闲idr_layer链表头

[cpp] view plain copy
  1. static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)  
  2. {  
  3.     struct idr_layer *pa[MAX_LEVEL];    //MAX_LEVEL=7  
  4.     int id;  
  5.     id = idr_get_empty_slot(idp, starting_id, pa);  //-->idr_get_empty_slot  
  6.     if (id >= 0) {  
  7.         rcu_assign_pointer(pa[0]->ary[id & IDR_MASK],(struct idr_layer *)ptr  
  8.         //pa[0]->ary[0]=ptr 也就是idr_layer14->ary[0]=ptr  
  9.         pa[0]->count++;  //idr_layer14->count++  
  10.         idr_mark_full(pa, id);  //设置其位图-->走完0过场的效果见图c  
  11.     }  
  12.     return id;  
  13. }  

idr_get_empty_slot

[cpp] view plain copy
  1. static int idr_get_empty_slot(struct idr *idp, int starting_id,struct idr_layer **pa)  
  2. {  
  3.     struct idr_layer *p, *new;  
  4.     int layers, v, id;  
  5.     unsigned long flags;  
  6.   
  7.     id = starting_id;   //按常规出牌吧,假设这个为0  
  8. build_up:  
  9.     p = idp->top;    //根top指向的idr_layer NULL  
  10.     layers = idp->layers;    //获取layers层数量(0)  
  11.     if (unlikely(!p)) { //第一次运行idp->top=NULL,所以if条件为真,执行if分支的结果参考 图A  
  12.         if (!(p = get_from_free_list(idp))) //>>>1-->get_from_free_list 从根free中获取一个idr_layer14  
  13.             return -1;  
  14.         p->layer = 0;    //指定idr_layer14的层号为0  
  15.         layers = 1; //layers层数量设为1  
  16.     }  
  17.     //layers<6 && id>=2^(layers*5) 看需不需要增加层数 见图B  
  18.     while ((layers < (MAX_LEVEL - 1)) && (id >= (1 << (layers*IDR_BITS)))) {  
  19.         layers++;     
  20.         if (!p->count) {  
  21.             p->layer++;  
  22.             continue;     
  23.         }  
  24.         if (!(new = get_from_free_list(idp))) {  
  25.             spin_lock_irqsave(&idp->lock, flags);  
  26.             for (new = p; p && p != idp->top; new = p) {  
  27.                 p = p->ary[0];  
  28.                 new->ary[0] = NULL;  
  29.                 new->bitmap = new->count = 0;  
  30.                 __move_to_free_list(idp, new);  
  31.             }  
  32.             spin_unlock_irqrestore(&idp->lock, flags);  
  33.             return -1;  
  34.         }  
  35.         new->ary[0] = p;  
  36.         new->count = 1;  
  37.         new->layer = layers-1;  
  38.         if (p->bitmap == IDR_FULL)  
  39.             __set_bit(0, &new->bitmap);  
  40.         p = new;  
  41.     }  
  42.     rcu_assign_pointer(idp->top, p); //根top指向idr_layer14  
  43.     idp->layers = layers;    //设置更新idr->layers层数量  
  44. //----------------------------------------------分割线----------------------------------------------  
  45. //以上部分主要处理layer相关,以下部分主要处理id相关  
  46.     v = sub_alloc(idp, &id, pa);    //>>>2-->sub_alloc  
  47.     if (v == IDR_NEED_TO_GROW)  //IDR_NEED_TO_GROW=-2需要扩大  
  48.         goto build_up;  
  49.     return(v);  
  50. }  

图A:

图B

>>>get_from_free_list 从idr空闲idr_layer链表中获取第一个idr_layer

[cpp] view plain copy
  1. static struct idr_layer *get_from_free_list(struct idr *idp)  
  2. {  
  3.     struct idr_layer *p;    //定义一个idr_layer指针  
  4.     unsigned long flags;  
  5.     spin_lock_irqsave(&idp->lock, flags);  
  6.     if ((p = idp->id_free)) {    //根free获取一个空闲idr_layer  
  7.         idp->id_free = p->ary[0]; //idr空闲链表指针指向第二个idr_layer  
  8.         idp->id_free_cnt--;  //idr的空闲idr_layer个数减1(14-1)  
  9.         p->ary[0] = NULL;    //断开第一个idr_layer和第二个idr_layer的联系  
  10.     }  
  11.     spin_unlock_irqrestore(&idp->lock, flags);  
  12.     return(p);  
  13. }  

这里先穿插一下32进制的计算,上面图B中2^0,2^5,2^10,2^15,2^20,2^25可以(32=2^5)理解成32^0,32^1,32^2,32^3,32^3,32^4,32^5

那么用32进制表达一个十进制数id可以套用一下公式

a的值属于[0,31]

an的值如何获得id/(32^n)即可,等同于id/(2^5^n)等同于id/((1<<5)^n)

an-1的值如何获得id>>(5*(n-1))即可

>>>sub_alloc

[cpp] view plain copy
  1. static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)  
  2. {  
  3.     int n, m, sh;  
  4.     struct idr_layer *p, *new;  
  5.     int l, id, oid;  
  6.     unsigned long bm;  
  7.   
  8.     id = *starting_id;  
  9.  restart:  
  10.     p = idp->top;    //根top  
  11.     l = idp->layers; //l=1  
  12.     pa[l--] = NULL; //p[1]=NULL;l=0  
  13.     while (1) {  
  14.         n = (id >> (IDR_BITS*l)) & IDR_MASK;  //计算对应的n值,属于[0,31]  
  15.         bm = ~p->bitmap; //取反位图  
  16.         m = find_next_bit(&bm, IDR_SIZE, n);    //>>>1 find_next_bit 位图中偏移量为n处查找'1'  
  17.         if (m == IDR_SIZE) {    //位图满了  
  18.             l++;  
  19.             oid = id;  
  20.             id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1;  
  21.             if (id >= 1 << (idp->layers * IDR_BITS)) {  
  22.                 *starting_id = id;  
  23.                 return IDR_NEED_TO_GROW;  
  24.             }  
  25.             p = pa[l];  
  26.             BUG_ON(!p);  
  27.             sh = IDR_BITS * (l + 1);  
  28.             if (oid >> sh == id >> sh)  
  29.                 continue;  
  30.             else  
  31.                 goto restart;  
  32.         }  
  33.         if (m != n) {   //期望的n值被占用,但可找到可用的m值  
  34.             sh = IDR_BITS*l;  
  35.             id = ((id >> sh) ^ n ^ m) << sh;    //>>>2 重新计算id值  
  36.         }  
  37.         if ((id >= MAX_ID_BIT) || (id < 0))  
  38.             return IDR_NOMORE_SPACE;  
  39.         if (l == 0) //l==0跳出while循环  
  40.             break;  
  41.         if (!p->ary[m]) {  
  42.             new = get_from_free_list(idp);  
  43.             if (!new)  
  44.                 return -1;  
  45.             new->layer = l-1;  
  46.             rcu_assign_pointer(p->ary[m], new);  
  47.             p->count++;  
  48.         }  
  49.         pa[l--] = p;  
  50.         p = p->ary[m];  
  51.     }  
  52.   
  53.     pa[l] = p;  //pa[0]=p 也就是idr_layer14  
  54.     return id;  
  55. }  

>>>find_next_bit

[cpp] view plain copy
  1. #define find_next_bit(p,sz,off) _find_next_bit_le(p,sz,off)     //>>_find_next_bit_le  

该宏的意思是在p指向的(大小为sz的)位图表中的第off个位置开始找寻可用(为"1")的格子,找到返回该位

_find_next_bit_le是汇编代码实现的定义在/arch/arm/lib/findbit.S

[cpp] view plain copy
  1. ENTRY(_find_next_bit_le)  
  2.         teq r1, #0  
  3.         beq 3b  
  4.         ands    ip, r2, #7  
  5.         beq 1b          @ If new byte, goto old routine  
  6.  ARM(       ldrb    r3, [r0, r2, lsr #3]    )  
  7.  THUMB(     lsr r3, r2, #3      )  
  8.  THUMB(     ldrb    r3, [r0, r3]        )  
  9.         movs    r3, r3, lsr ip      @ shift off unused bits  
  10.         bne .L_found  
  11.         orr r2, r2, #7      @ if zero, then no bits here  
  12.         add r2, r2, #1      @ align bit pointer  
  13.         b   2b          @ loop for next bit  
  14. ENDPROC(_find_next_bit_le)  

.L_found找到合适的跳转

[cpp] view plain copy
  1. .L_found:  
  2. #if __LINUX_ARM_ARCH__ >= 5  
  3.         rsb r0, r3, #0  
  4.         and r3, r3, r0  
  5.         clz r3, r3  
  6.         rsb r3, r3, #31  
  7.         add r0, r2, r3  
  8. #else  
  9.         tst r3, #0x0f  
  10.         addeq   r2, r2, #4  
  11.         movne   r3, r3, lsl #4  
  12.         tst r3, #0x30  
  13.         addeq   r2, r2, #2  
  14.         movne   r3, r3, lsl #2  
  15.         tst r3, #0x40  
  16.         addeq   r2, r2, #1  
  17.         mov r0, r2  
  18. #endif  
  19.         cmp r1, r0          @ Clamp to maxbit  
  20.         movlo   r0, r1  
  21.         mov pc, lr  

>>>id值的计算的补充说明

首先前面n的取值n = (id >> (IDR_BITS*l)) & IDR_MASK;

IDR_MASK的定义#define IDR_MASK ((1 << IDR_BITS)-1)也就是说IDR_MASK=31等于2进制的1,1111b

所以&IDR_MASK只是框定n值落在0~31之间,掩码作用

那么不出意外的话n = (id >> (IDR_BITS*l))

接着

sh = IDR_BITS*l;
id = ((id >> sh) ^ n ^ m) << sh;

带入表达式中

id=((id >> IDR_BITS*l) ^ (id >> (IDR_BITS*l)) ^ m) << IDR_BITS*l;

异或的操作是相同为1,不同为0,结合起来化简得

id = ((1 ^ m) << sh=m<<sh

图C

^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_

 已经借用id0走了过场,下面分析下其他情况

[cpp] view plain copy
  1. static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)  
  2. {  
  3.     struct idr_layer *pa[MAX_LEVEL];    //定义父idr_layer数组  
  4.     int id;  
  5.     id = idr_get_empty_slot(idp, starting_id, pa);  //获取id  
  6.     if (id >= 0) {  
  7.         rcu_assign_pointer(pa[0]->ary[id & IDR_MASK],(struct idr_layer *)ptr);  
  8.         //pa[0]->ary[id]=ptr  
  9.         pa[0]->count++;  //idr_layer->count++  
  10.         idr_mark_full(pa, id);  //标记id位图  
  11.     }  
  12.     return id;  
  13. }  
  14.   
  15. static int idr_get_empty_slot(struct idr *idp, int starting_id,struct idr_layer **pa)  
  16. {  
  17.     struct idr_layer *p, *new;  
  18.     int layers, v, id;  
  19.     unsigned long flags;  
  20.   
  21.     id = starting_id;  
  22. build_up:  
  23.     p = idp->top;    //获取根top  
  24.     layers = idp->layers;    //获取层数量 layers=1  
  25.     if (unlikely(!p)) { //FALSE  
  26.         if (!(p = get_from_free_list(idp)))  
  27.             return -1;  
  28.         p->layer = 0;  
  29.         layers = 1;  
  30.     }  
  31.   
  32.     while ((layers < 6) && (id >= (1 << (layers*5)))) { //参考图B,如果id值超过或等于对应层所能容纳的最大数,则进入循环  
  33.         layers++;       //增加层数量  
  34.         if (!p->count) { //0~31没使用,直接使用32就属于这种情况  
  35.             p->layer++;  //由于32需要添加1层的,所以之前的层的层号需要+1  
  36.             continue;    //层数量也需要加1   
  37.         }  
  38.         if (!(new = get_from_free_list(idp))) { //空闲链表中获取新的idr_layer  
  39.             spin_lock_irqsave(&idp->lock, flags);    //分配失败,--空闲idr_layer链表缺货  
  40.             for (new = p; p && p != idp->top; new = p) { //p指针还原  
  41.                     p = p->ary[0];  
  42.                 new->ary[0] = NULL;  
  43.                 new->bitmap = new->count = 0;  
  44.                 __move_to_free_list(idp, new);  //分配更多空闲链表  
  45.             }  
  46.             spin_unlock_irqrestore(&idp->lock, flags);  
  47.             return -1;  
  48.         }  
  49.         new->ary[0] = p; //新的idr_layer->ary[0]指向旧的idr_layer  
  50.         new->count = 1;  //新的idr_layer计数加1  
  51.         new->layer = layers-1;   //设置新的idr_layer的层号  
  52.         if (p->bitmap == IDR_FULL)   //若旧的(叶子)idr_layer的id全用过了  
  53.             __set_bit(0, &new->bitmap);  //那么标记下新(父)idr_layer位图的第0位  
  54.         p = new;    //根top指向新的idr_layer  
  55.     }  
  56.     rcu_assign_pointer(idp->top, p); //设置根top  
  57.     idp->layers = layers;    //更新层数量  
  58.     v = sub_alloc(idp, &id, pa);    //获取id  
  59.     if (v == IDR_NEED_TO_GROW)  //该层id号全用完了,必须扩大idr_layer层数量  
  60.         goto build_up;  
  61.     return(v);  
  62. }  
  63.   
  64. static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)  
  65. {  
  66.     int n, m, sh;  
  67.     struct idr_layer *p, *new;  
  68.     int l, id, oid;  
  69.     unsigned long bm;  
  70.   
  71.     id = *starting_id;  
  72.  restart:  
  73.     p = idp->top;    //获取根top  
  74.     l = idp->layers; //获取层数量l=1  
  75.     pa[l--] = NULL; //pa[1]=NULL,l=0  
  76.     while (1) {  
  77.         n = (id >> (5*l)) & IDR_MASK; //n做处理 属于[0,31]  
  78.         bm = ~p->bitmap; //位图取反  
  79.         m = find_next_bit(&bm, IDR_SIZE, n);    //查找n开始能用的位  
  80.         if (m == IDR_SIZE) {    //id表满了  
  81.             l++;    层数+1  
  82.             oid = id;  
  83.             id = (id | ((1 << (5 * l)) - 1)) + 1; //id或上掩码再+1   
  84.   
  85.             if (id >= 1 << (idp->layers * 5)) { //需要添加层  
  86.                 *starting_id = id;  
  87.                 return IDR_NEED_TO_GROW;  
  88.             }  
  89.             p = pa[l];  
  90.             BUG_ON(!p);  
  91.             sh = 5 * (l + 1);  
  92.             if (oid >> sh == id >> sh)  
  93.                 continue;  
  94.             else  
  95.                 goto restart;  
  96.         }  
  97.         if (m != n) {   //期望id给用但有可用id  
  98.             sh = 5*l;  
  99.             id = ((id >> sh) ^ n ^ m) << sh;    //id设置为可用id  
  100.         }  
  101.         if ((id >= MAX_ID_BIT) || (id < 0))  
  102.             return IDR_NOMORE_SPACE;  
  103.         if (l == 0) //一层层循环计算直到到达叶子处l才为0  
  104.             break;  
  105.         if (!p->ary[m]) {    //叶子m为空  
  106.             new = get_from_free_list(idp);  //从空闲链表拿一个idr_layer  
  107.             if (!new)  
  108.                 return -1;  
  109.             new->layer = l-1;    //设置新链表层数  
  110.             rcu_assign_pointer(p->ary[m], new);  //叶子m指向新链表  
  111.             p->count++;  //使用计数加1  
  112.         }  
  113.         pa[l--] = p;    //pa[大]=节点  
  114.         p = p->ary[m];   //p=节点->叶子m    
  115.     }  
  116.     pa[l] = p;      //pa[小]=叶子  
  117.     return id;  
  118. }  

来个效果图id=4吧


id=32情况(idr_layer13的位图1标记错了)

 

1024情况



四.查找id
1.idr_find

[cpp] view plain copy
  1. void *idr_find(struct idr *idp, int id)  
  2. {  
  3.     int n;  
  4.     struct idr_layer *p;  
  5.   
  6.     p = rcu_dereference_raw(idp->top);   //获取根top  
  7.     if (!p)  
  8.         return NULL;  
  9.     n = (p->layer+1) * IDR_BITS; //计算最外层的n值  
  10.     id &= MAX_ID_MASK;  
  11.     if (id >= (1 << n))  
  12.         return NULL;  
  13.     BUG_ON(n == 0);  
  14.     while (n > 0 && p) { //循环一层层查找  
  15.         n -= IDR_BITS;  
  16.         BUG_ON(n != p->layer*IDR_BITS);  
  17.         p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]); //一次获取an ... a0   
  18.     }  
  19.     return((void *)p);  
  20. }  
  21. EXPORT_SYMBOL(idr_find);  

前面讲过32进制的id值算法


当构建完idr机制之后

id=top->ary[an]->ary[a(n-1)]->....->ary[a0]来获得

 借助图片分析下(idr_layer13的位图标记有错)

 

五idr操作

1. idr_remove  idr_remove_all 移除

[cpp] view plain copy
  1. void idr_remove(struct idr *idp, int id)  
  2. {  
  3.     struct idr_layer *p;  
  4.     struct idr_layer *to_free;  
  5.     id &= MAX_ID_MASK;  
  6.   
  7.     sub_remove(idp, (idp->layers - 1) * IDR_BITS, id);  
  8.     if (idp->top && idp->top->count == 1 && (idp->layers > 1) &&  
  9.         idp->top->ary[0]) {  
  10.         to_free = idp->top;  
  11.         p = idp->top->ary[0];  
  12.         rcu_assign_pointer(idp->top, p);  
  13.         --idp->layers;  
  14.         to_free->bitmap = to_free->count = 0;  
  15.         free_layer(to_free);  
  16.     }  
  17.     while (idp->id_free_cnt >= IDR_FREE_MAX) {  
  18.         p = get_from_free_list(idp);  
  19.         kmem_cache_free(idr_layer_cache, p);  
  20.     }  
  21.     return;  
  22. }  
  23. EXPORT_SYMBOL(idr_remove);  

移除全部

[cpp] view plain copy
  1. void idr_remove_all(struct idr *idp)  
  2. {  
  3.     int n, id, max;  
  4.     int bt_mask;  
  5.     struct idr_layer *p;  
  6.     struct idr_layer *pa[MAX_LEVEL];  
  7.     struct idr_layer **paa = &pa[0];  
  8.   
  9.     n = idp->layers * IDR_BITS;  
  10.     p = idp->top;  
  11.     rcu_assign_pointer(idp->top, NULL);  
  12.     max = 1 << n;  
  13.   
  14.     id = 0;  
  15.     while (id < max) {  
  16.         while (n > IDR_BITS && p) {  
  17.             n -= IDR_BITS;  
  18.             *paa++ = p;  
  19.             p = p->ary[(id >> n) & IDR_MASK];  
  20.         }  
  21.   
  22.         bt_mask = id;  
  23.         id += 1 << n;  
  24.         /* Get the highest bit that the above add changed from 0->1. */  
  25.         while (n < fls(id ^ bt_mask)) {  
  26.             if (p)  
  27.                 free_layer(p);  
  28.             n += IDR_BITS;  
  29.             p = *--paa;  
  30.         }  
  31.     }  
  32.     idp->layers = 0;  
  33. }  
  34. EXPORT_SYMBOL(idr_remove_all);  


 

2.idr_replace 替换

[cpp] view plain copy
  1. void *idr_replace(struct idr *idp, void *ptr, int id)  
  2. {  
  3.     int n;  
  4.     struct idr_layer *p, *old_p;  
  5.   
  6.     p = idp->top;  
  7.     if (!p)  
  8.         return ERR_PTR(-EINVAL);  
  9.   
  10.     n = (p->layer+1) * IDR_BITS;  
  11.   
  12.     id &= MAX_ID_MASK;  
  13.   
  14.     if (id >= (1 << n))  
  15.         return ERR_PTR(-EINVAL);  
  16.   
  17.     n -= IDR_BITS;  
  18.     while ((n > 0) && p) {  
  19.         p = p->ary[(id >> n) & IDR_MASK];  
  20.         n -= IDR_BITS;  
  21.     }  
  22.   
  23.     n = id & IDR_MASK;  
  24.     if (unlikely(p == NULL || !test_bit(n, &p->bitmap)))  
  25.         return ERR_PTR(-ENOENT);  
  26.   
  27.     old_p = p->ary[n];  
  28.     rcu_assign_pointer(p->ary[n], ptr);  
  29.   
  30.     return old_p;  
  31. }  
  32. EXPORT_SYMBOL(idr_replace);  

 

六.idr空闲链表的销毁

idr_destroy

[cpp] view plain copy
  1. void idr_destroy(struct idr *idp)  
  2. {  
  3.     while (idp->id_free_cnt) {  
  4.         struct idr_layer *p = get_from_free_list(idp);  
  5.         kmem_cache_free(idr_layer_cache, p);  
  6.     }  
  7. }  
  8. EXPORT_SYMBOL(idr_destroy);  

 

七.用法

1.api函数

[cpp] view plain copy
  1. void *idr_find(struct idr *idp, int id);    //查找id对应的指针  
  2. int idr_pre_get(struct idr *idp, gfp_t gfp_mask);   //分配idr_layer空闲链表  
  3. int idr_get_new(struct idr *idp, void *ptr, int *id);   //获取id,捆绑指针ptr  
  4. int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);    //起始数值获取id,捆绑指针ptr  
  5. int idr_for_each(struct idr *idp,int (*fn)(int id, void *p, void *data), void *data);  
  6. void *idr_get_next(struct idr *idp, int *nextid);     
  7. void *idr_replace(struct idr *idp, void *ptr, int id);  //替换id捆绑的指针  
  8. void idr_remove(struct idr *idp, int id);   //移除id  
  9. void idr_remove_all(struct idr *idp);   //移除所有id  
  10. void idr_destroy(struct idr *idp);  //销毁idr_layer空闲链表  
  11. void idr_init(struct idr *idp); //初始化idr  

2.大致用法

1.idr_init声明设置idr

2.idr_pre_get分配空闲idr_layer链表

3.id_get_new/idr_get_new_above分配id并将id与指针ptr捆绑

4.利用idr_find根据id获取指针ptr

5.idr_remove/idr_remove_all移除分配的id

6.idr_destroy销毁空闲idr_layer链表

 7.idr_replace替换id

 

 

原创粉丝点击