当前位置:编程学习 > C/C++ >>

idr机制(32叉树)

一.结构体
1.idr结构体
[cpp] 
struct idr {  
    struct idr_layer __rcu *top;    //idr_layer顶层,32叉树的根  
    struct idr_layer *id_free;      //指向idr_layer的空闲链表  
    int layers;     //idr_layer的层数量  
    int id_free_cnt;    //idr_layer空闲链表中剩余的idr_layer个数  
    spinlock_t  lock;  
};  
2.idr_layer结构体
[cpp 
struct idr_layer {  
    unsigned long   bitmap; //标记位图,标记使用情况  
    struct idr_layer __rcu  *ary[1<<IDR_BITS];        //子idr_layer数组ary[32]  
    int count;  //ary数组使用情况  
    int layer;  //层号  
    struct rcu_head rcu_head;  
};  
在32位系统中IDR_BITS的取值为5
[cpp]  
#if BITS_PER_LONG == 32  
    # define IDR_BITS 5  
    # define IDR_FULL 0xfffffffful  
    # define TOP_LEVEL_FULL (IDR_FULL >> 30)  
#elif BITS_PER_LONG == 64  
    # define IDR_BITS 6  
    # define IDR_FULL 0xfffffffffffffffful  
    # define TOP_LEVEL_FULL (IDR_FULL >> 62)  
#else  
    # error "BITS_PER_LONG is not 32 or 64"  
#endif  
 
二.idr的初始化
[cpp]  
#define IDR_INIT(name)      \  
{               \  
    .top        = NULL, \  
    .id_free        = NULL, \  
    .layers         = 0,    \  
    .id_free_cnt    = 0,    \  
    .lock       = __SPIN_LOCK_UNLOCKED(name.lock),  \  
}  
#define DEFINE_IDR(name)    struct idr name = IDR_INIT(name)  
定义一个idr结构体并赋值
三.分配id
1.idr_pre_get
[cpp]  
int idr_pre_get(struct idr *idp, gfp_t gfp_mask)  
{  
    while (idp->id_free_cnt < IDR_FREE_MAX) { //IDR_FREE_MAX=14  
        struct idr_layer *new;  //定义新的idr_layer结构体指针  
        new = kmem_cache_zalloc(idr_layer_cache, gfp_mask); //分配*new内存空间  
        if (new == NULL)  
            return (0);  
        move_to_free_list(idp, new);    //-->move_to_free_list  
    }  
    return 1;  
}  
EXPORT_SYMBOL(idr_pre_get);  
move_to_free_list
[cpp] 
static void move_to_free_list(struct idr *idp, struct idr_layer *p)  
{  
    unsigned long flags;  
    spin_lock_irqsave(&idp->lock, flags);  
    __move_to_free_list(idp, p);    //-->__move_to_free_list  
    spin_unlock_irqrestore(&idp->lock, flags);  
}  
__move_to_free_list
[cpp]  
static void __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++;  
}  
第一次循环结果
接着循环
再接着
一直这样下去直到循环结束(14次)
2.idr_get_new和idr_get_new_above
idr_get_new
[cpp] 
int idr_get_new(struct idr *idp, void *ptr, int *id)  
{  
    int rv;  
    rv = idr_get_new_above_int(idp, ptr, 0);  
    if (rv < 0)  
        return _idr_rc_to_errno(rv);  
    *id = rv;  
    return 0;  
}  
EXPORT_SYMBOL(idr_get_new);  
idr_get_new_above
[cpp] 
int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)  
{  
    int rv;  
    rv = idr_get_new_above_int(idp, ptr, starting_id);  
    if (rv < 0)  
        return _idr_rc_to_errno(rv);  
    *id = rv;  
    return 0;  
}  
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] 
static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)  
{  
    struct idr_layer *pa[MAX_LEVEL];    //MAX_LEVEL=7  
    int id;  
    id = idr_get_empty_slot(idp, starting_id, pa);  //-->idr_get_empty_slot  
    if (id >= 0) {  
        rcu_assign_pointer(pa[0]->ary[id & IDR_MASK],(struct idr_layer *)ptr  
        //pa[0]->ary[0]=ptr 也就是idr_layer14->ary[0]=ptr  
        pa[0]->count++;  //idr_layer14->count++  
        idr_mark_full(pa, id);  //设置其位图-->走完0过场的效果见图c  
    }  
    return id;  
}  
idr_get_empty_slot
[cpp] 
static int idr_get_empty_slot(struct idr *idp, int starting_id,struct idr_layer **pa)  
{  
    struct idr_layer *p, *new;  
    int layers, v, id;  
    unsigned long flags;  
  
    id = starting_id;   //按常规出牌吧,假设这个为0  
build_up:  
    p = idp->top;    //根top指向的idr_layer NULL  
    layers = idp->layers;    //获取layers层数量(0)  
    if (unlikely(!p)) { //第一次运行idp->top=NULL,所以if条件为真,执行if分支的结果参考 图A  
        if (!(p = get_from_free_list(idp))) //>>>1-->get_from_free_list 从根free中获取一个idr_layer14  
            return -1;  
  &
补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,