linux kernel idr机制

在我们实际编程中,有时候需要做这么一件事情..就是一个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);
}
 
 

你可能感兴趣的:(Kernel)