⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radix-tree.c

📁 Lib files of linux kernel
💻 C
📖 第 1 页 / 共 3 页
字号:
 */void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index){	unsigned int height, shift;	struct radix_tree_node *node, **slot;	node = rcu_dereference(root->rnode);	if (node == NULL)		return NULL;	if (!radix_tree_is_indirect_ptr(node)) {		if (index > 0)			return NULL;		return node;	}	node = radix_tree_indirect_to_ptr(node);	height = node->height;	if (index > radix_tree_maxindex(height))		return NULL;	shift = (height-1) * RADIX_TREE_MAP_SHIFT;	do {		slot = (struct radix_tree_node **)			(node->slots + ((index>>shift) & RADIX_TREE_MAP_MASK));		node = rcu_dereference(*slot);		if (node == NULL)			return NULL;		shift -= RADIX_TREE_MAP_SHIFT;		height--;	} while (height > 0);	return node;}EXPORT_SYMBOL(radix_tree_lookup);/** *	radix_tree_tag_set - set a tag on a radix tree node *	@root:		radix tree root *	@index:		index key *	@tag: 		tag index * *	Set the search tag (which must be < RADIX_TREE_MAX_TAGS) *	corresponding to @index in the radix tree.  From *	the root all the way down to the leaf node. * *	Returns the address of the tagged item.   Setting a tag on a not-present *	item is a bug. */void *radix_tree_tag_set(struct radix_tree_root *root,			unsigned long index, unsigned int tag){	unsigned int height, shift;	struct radix_tree_node *slot;	height = root->height;	BUG_ON(index > radix_tree_maxindex(height));	slot = radix_tree_indirect_to_ptr(root->rnode);	shift = (height - 1) * RADIX_TREE_MAP_SHIFT;	while (height > 0) {		int offset;		offset = (index >> shift) & RADIX_TREE_MAP_MASK;		if (!tag_get(slot, tag, offset))			tag_set(slot, tag, offset);		slot = slot->slots[offset];		BUG_ON(slot == NULL);		shift -= RADIX_TREE_MAP_SHIFT;		height--;	}	/* set the root's tag bit */	if (slot && !root_tag_get(root, tag))		root_tag_set(root, tag);	return slot;}EXPORT_SYMBOL(radix_tree_tag_set);/** *	radix_tree_tag_clear - clear a tag on a radix tree node *	@root:		radix tree root *	@index:		index key *	@tag: 		tag index * *	Clear the search tag (which must be < RADIX_TREE_MAX_TAGS) *	corresponding to @index in the radix tree.  If *	this causes the leaf node to have no tags set then clear the tag in the *	next-to-leaf node, etc. * *	Returns the address of the tagged item on success, else NULL.  ie: *	has the same return value and semantics as radix_tree_lookup(). */void *radix_tree_tag_clear(struct radix_tree_root *root,			unsigned long index, unsigned int tag){	/*	 * The radix tree path needs to be one longer than the maximum path	 * since the "list" is null terminated.	 */	struct radix_tree_path path[RADIX_TREE_MAX_PATH + 1], *pathp = path;	struct radix_tree_node *slot = NULL;	unsigned int height, shift;	height = root->height;	if (index > radix_tree_maxindex(height))		goto out;	shift = (height - 1) * RADIX_TREE_MAP_SHIFT;	pathp->node = NULL;	slot = radix_tree_indirect_to_ptr(root->rnode);	while (height > 0) {		int offset;		if (slot == NULL)			goto out;		offset = (index >> shift) & RADIX_TREE_MAP_MASK;		pathp[1].offset = offset;		pathp[1].node = slot;		slot = slot->slots[offset];		pathp++;		shift -= RADIX_TREE_MAP_SHIFT;		height--;	}	if (slot == NULL)		goto out;	while (pathp->node) {		if (!tag_get(pathp->node, tag, pathp->offset))			goto out;		tag_clear(pathp->node, tag, pathp->offset);		if (any_tag_set(pathp->node, tag))			goto out;		pathp--;	}	/* clear the root's tag bit */	if (root_tag_get(root, tag))		root_tag_clear(root, tag);out:	return slot;}EXPORT_SYMBOL(radix_tree_tag_clear);#ifndef __KERNEL__	/* Only the test harness uses this at present *//** * radix_tree_tag_get - get a tag on a radix tree node * @root:		radix tree root * @index:		index key * @tag: 		tag index (< RADIX_TREE_MAX_TAGS) * * Return values: * *  0: tag not present or not set *  1: tag set */int radix_tree_tag_get(struct radix_tree_root *root,			unsigned long index, unsigned int tag){	unsigned int height, shift;	struct radix_tree_node *node;	int saw_unset_tag = 0;	/* check the root's tag bit */	if (!root_tag_get(root, tag))		return 0;	node = rcu_dereference(root->rnode);	if (node == NULL)		return 0;	if (!radix_tree_is_indirect_ptr(node))		return (index == 0);	node = radix_tree_indirect_to_ptr(node);	height = node->height;	if (index > radix_tree_maxindex(height))		return 0;	shift = (height - 1) * RADIX_TREE_MAP_SHIFT;	for ( ; ; ) {		int offset;		if (node == NULL)			return 0;		offset = (index >> shift) & RADIX_TREE_MAP_MASK;		/*		 * This is just a debug check.  Later, we can bale as soon as		 * we see an unset tag.		 */		if (!tag_get(node, tag, offset))			saw_unset_tag = 1;		if (height == 1) {			int ret = tag_get(node, tag, offset);			BUG_ON(ret && saw_unset_tag);			return !!ret;		}		node = rcu_dereference(node->slots[offset]);		shift -= RADIX_TREE_MAP_SHIFT;		height--;	}}EXPORT_SYMBOL(radix_tree_tag_get);#endif/** *	radix_tree_next_hole    -    find the next hole (not-present entry) *	@root:		tree root *	@index:		index key *	@max_scan:	maximum range to search * *	Search the set [index, min(index+max_scan-1, MAX_INDEX)] for the lowest *	indexed hole. * *	Returns: the index of the hole if found, otherwise returns an index *	outside of the set specified (in which case 'return - index >= max_scan' *	will be true). * *	radix_tree_next_hole may be called under rcu_read_lock. However, like *	radix_tree_gang_lookup, this will not atomically search a snapshot of the *	tree at a single point in time. For example, if a hole is created at index *	5, then subsequently a hole is created at index 10, radix_tree_next_hole *	covering both indexes may return 10 if called under rcu_read_lock. */unsigned long radix_tree_next_hole(struct radix_tree_root *root,				unsigned long index, unsigned long max_scan){	unsigned long i;	for (i = 0; i < max_scan; i++) {		if (!radix_tree_lookup(root, index))			break;		index++;		if (index == 0)			break;	}	return index;}EXPORT_SYMBOL(radix_tree_next_hole);static unsigned int__lookup(struct radix_tree_node *slot, void ***results, unsigned long index,	unsigned int max_items, unsigned long *next_index){	unsigned int nr_found = 0;	unsigned int shift, height;	unsigned long i;	height = slot->height;	if (height == 0)		goto out;	shift = (height-1) * RADIX_TREE_MAP_SHIFT;	for ( ; height > 1; height--) {		i = (index >> shift) & RADIX_TREE_MAP_MASK;		for (;;) {			if (slot->slots[i] != NULL)				break;			index &= ~((1UL << shift) - 1);			index += 1UL << shift;			if (index == 0)				goto out;	/* 32-bit wraparound */			i++;			if (i == RADIX_TREE_MAP_SIZE)				goto out;		}		shift -= RADIX_TREE_MAP_SHIFT;		slot = rcu_dereference(slot->slots[i]);		if (slot == NULL)			goto out;	}	/* Bottom level: grab some items */	for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) {		index++;		if (slot->slots[i]) {			results[nr_found++] = &(slot->slots[i]);			if (nr_found == max_items)				goto out;		}	}out:	*next_index = index;	return nr_found;}/** *	radix_tree_gang_lookup - perform multiple lookup on a radix tree *	@root:		radix tree root *	@results:	where the results of the lookup are placed *	@first_index:	start the lookup from this key *	@max_items:	place up to this many items at *results * *	Performs an index-ascending scan of the tree for present items.  Places *	them at *@results and returns the number of items which were placed at *	*@results. * *	The implementation is naive. * *	Like radix_tree_lookup, radix_tree_gang_lookup may be called under *	rcu_read_lock. In this case, rather than the returned results being *	an atomic snapshot of the tree at a single point in time, the semantics *	of an RCU protected gang lookup are as though multiple radix_tree_lookups *	have been issued in individual locks, and results stored in 'results'. */unsigned intradix_tree_gang_lookup(struct radix_tree_root *root, void **results,			unsigned long first_index, unsigned int max_items){	unsigned long max_index;	struct radix_tree_node *node;	unsigned long cur_index = first_index;	unsigned int ret;	node = rcu_dereference(root->rnode);	if (!node)		return 0;	if (!radix_tree_is_indirect_ptr(node)) {		if (first_index > 0)			return 0;		results[0] = node;		return 1;	}	node = radix_tree_indirect_to_ptr(node);	max_index = radix_tree_maxindex(node->height);	ret = 0;	while (ret < max_items) {		unsigned int nr_found, slots_found, i;		unsigned long next_index;	/* Index of next search */		if (cur_index > max_index)			break;		slots_found = __lookup(node, (void ***)results + ret, cur_index,					max_items - ret, &next_index);		nr_found = 0;		for (i = 0; i < slots_found; i++) {			struct radix_tree_node *slot;			slot = *(((void ***)results)[ret + i]);			if (!slot)				continue;			results[ret + nr_found] = rcu_dereference(slot);			nr_found++;		}		ret += nr_found;		if (next_index == 0)			break;		cur_index = next_index;	}	return ret;}EXPORT_SYMBOL(radix_tree_gang_lookup);/** *	radix_tree_gang_lookup_slot - perform multiple slot lookup on radix tree *	@root:		radix tree root *	@results:	where the results of the lookup are placed *	@first_index:	start the lookup from this key *	@max_items:	place up to this many items at *results * *	Performs an index-ascending scan of the tree for present items.  Places *	their slots at *@results and returns the number of items which were *	placed at *@results. * *	The implementation is naive. * *	Like radix_tree_gang_lookup as far as RCU and locking goes. Slots must *	be dereferenced with radix_tree_deref_slot, and if using only RCU *	protection, radix_tree_deref_slot may fail requiring a retry. */unsigned intradix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,			unsigned long first_index, unsigned int max_items){	unsigned long max_index;	struct radix_tree_node *node;	unsigned long cur_index = first_index;	unsigned int ret;	node = rcu_dereference(root->rnode);	if (!node)		return 0;	if (!radix_tree_is_indirect_ptr(node)) {		if (first_index > 0)			return 0;		results[0] = (void **)&root->rnode;		return 1;	}	node = radix_tree_indirect_to_ptr(node);	max_index = radix_tree_maxindex(node->height);	ret = 0;	while (ret < max_items) {		unsigned int slots_found;		unsigned long next_index;	/* Index of next search */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -