Blame lib/rbtree.h

Packit Service 0e769b
/*
Packit Service 0e769b
  Red Black Trees
Packit Service 0e769b
  (C) 1999  Andrea Arcangeli <andrea@suse.de>
Packit Service 0e769b
  
Packit Service 0e769b
  This program is free software; you can redistribute it and/or modify
Packit Service 0e769b
  it under the terms of the GNU General Public License as published by
Packit Service 0e769b
  the Free Software Foundation; either version 2 of the License, or
Packit Service 0e769b
  (at your option) any later version.
Packit Service 0e769b
Packit Service 0e769b
  This program is distributed in the hope that it will be useful,
Packit Service 0e769b
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 0e769b
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 0e769b
  GNU General Public License for more details.
Packit Service 0e769b
Packit Service 0e769b
  You should have received a copy of the GNU General Public License
Packit Service 0e769b
  along with this program; if not, write to the Free Software
Packit Service 0e769b
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit Service 0e769b
Packit Service 0e769b
  linux/include/linux/rbtree.h
Packit Service 0e769b
Packit Service 0e769b
  To use rbtrees you'll have to implement your own insert and search cores.
Packit Service 0e769b
  This will avoid us to use callbacks and to drop drammatically performances.
Packit Service 0e769b
  I know it's not the cleaner way,  but in C (not in C++) to get
Packit Service 0e769b
  performances and genericity...
Packit Service 0e769b
Packit Service 0e769b
  Some example of insert and search follows here. The search is a plain
Packit Service 0e769b
  normal search over an ordered tree. The insert instead must be implemented
Packit Service 0e769b
  int two steps: as first thing the code must insert the element in
Packit Service 0e769b
  order as a red leaf in the tree, then the support library function
Packit Service 0e769b
  rb_insert_color() must be called. Such function will do the
Packit Service 0e769b
  not trivial work to rebalance the rbtree if necessary.
Packit Service 0e769b
Packit Service 0e769b
-----------------------------------------------------------------------
Packit Service 0e769b
static inline struct page * rb_search_page_cache(struct inode * inode,
Packit Service 0e769b
						 unsigned long offset)
Packit Service 0e769b
{
Packit Service 0e769b
	struct fio_rb_node * n = inode->i_rb_page_cache.rb_node;
Packit Service 0e769b
	struct page * page;
Packit Service 0e769b
Packit Service 0e769b
	while (n)
Packit Service 0e769b
	{
Packit Service 0e769b
		page = rb_entry(n, struct page, rb_page_cache);
Packit Service 0e769b
Packit Service 0e769b
		if (offset < page->offset)
Packit Service 0e769b
			n = n->rb_left;
Packit Service 0e769b
		else if (offset > page->offset)
Packit Service 0e769b
			n = n->rb_right;
Packit Service 0e769b
		else
Packit Service 0e769b
			return page;
Packit Service 0e769b
	}
Packit Service 0e769b
	return NULL;
Packit Service 0e769b
}
Packit Service 0e769b
Packit Service 0e769b
static inline struct page * __rb_insert_page_cache(struct inode * inode,
Packit Service 0e769b
						   unsigned long offset,
Packit Service 0e769b
						   struct fio_rb_node * node)
Packit Service 0e769b
{
Packit Service 0e769b
	struct fio_rb_node ** p = &inode->i_rb_page_cache.rb_node;
Packit Service 0e769b
	struct fio_rb_node * parent = NULL;
Packit Service 0e769b
	struct page * page;
Packit Service 0e769b
Packit Service 0e769b
	while (*p)
Packit Service 0e769b
	{
Packit Service 0e769b
		parent = *p;
Packit Service 0e769b
		page = rb_entry(parent, struct page, rb_page_cache);
Packit Service 0e769b
Packit Service 0e769b
		if (offset < page->offset)
Packit Service 0e769b
			p = &(*p)->rb_left;
Packit Service 0e769b
		else if (offset > page->offset)
Packit Service 0e769b
			p = &(*p)->rb_right;
Packit Service 0e769b
		else
Packit Service 0e769b
			return page;
Packit Service 0e769b
	}
Packit Service 0e769b
Packit Service 0e769b
	rb_link_node(node, parent, p);
Packit Service 0e769b
Packit Service 0e769b
	return NULL;
Packit Service 0e769b
}
Packit Service 0e769b
Packit Service 0e769b
static inline struct page * rb_insert_page_cache(struct inode * inode,
Packit Service 0e769b
						 unsigned long offset,
Packit Service 0e769b
						 struct fio_rb_node * node)
Packit Service 0e769b
{
Packit Service 0e769b
	struct page * ret;
Packit Service 0e769b
	if ((ret = __rb_insert_page_cache(inode, offset, node)))
Packit Service 0e769b
		goto out;
Packit Service 0e769b
	rb_insert_color(node, &inode->i_rb_page_cache);
Packit Service 0e769b
 out:
Packit Service 0e769b
	return ret;
Packit Service 0e769b
}
Packit Service 0e769b
-----------------------------------------------------------------------
Packit Service 0e769b
*/
Packit Service 0e769b
Packit Service 0e769b
#ifndef	_LINUX_RBTREE_H
Packit Service 0e769b
#define	_LINUX_RBTREE_H
Packit Service 0e769b
Packit Service 0e769b
#include <stdlib.h>
Packit Service 0e769b
#include <inttypes.h>
Packit Service 0e769b
Packit Service 0e769b
struct fio_rb_node
Packit Service 0e769b
{
Packit Service 0e769b
	intptr_t rb_parent_color;
Packit Service 0e769b
#define	RB_RED		0
Packit Service 0e769b
#define	RB_BLACK	1
Packit Service 0e769b
	struct fio_rb_node *rb_right;
Packit Service 0e769b
	struct fio_rb_node *rb_left;
Packit Service 0e769b
} __attribute__((aligned(sizeof(long))));
Packit Service 0e769b
    /* The alignment might seem pointless, but allegedly CRIS needs it */
Packit Service 0e769b
Packit Service 0e769b
struct rb_root
Packit Service 0e769b
{
Packit Service 0e769b
	struct fio_rb_node *rb_node;
Packit Service 0e769b
};
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
#define rb_parent(r)   ((struct fio_rb_node *)((r)->rb_parent_color & ~3))
Packit Service 0e769b
#define rb_color(r)   ((r)->rb_parent_color & 1)
Packit Service 0e769b
#define rb_is_red(r)   (!rb_color(r))
Packit Service 0e769b
#define rb_is_black(r) rb_color(r)
Packit Service 0e769b
#define rb_set_red(r)  do { (r)->rb_parent_color &= ~1; } while (0)
Packit Service 0e769b
#define rb_set_black(r)  do { (r)->rb_parent_color |= 1; } while (0)
Packit Service 0e769b
Packit Service 0e769b
static inline void rb_set_parent(struct fio_rb_node *rb, struct fio_rb_node *p)
Packit Service 0e769b
{
Packit Service 0e769b
	rb->rb_parent_color = (rb->rb_parent_color & 3) | (uintptr_t)p;
Packit Service 0e769b
}
Packit Service 0e769b
static inline void rb_set_color(struct fio_rb_node *rb, int color)
Packit Service 0e769b
{
Packit Service 0e769b
	rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
Packit Service 0e769b
}
Packit Service 0e769b
Packit Service 0e769b
#define RB_ROOT	(struct rb_root) { NULL, }
Packit Service 0e769b
#define	rb_entry(ptr, type, member) container_of(ptr, type, member)
Packit Service 0e769b
Packit Service 0e769b
#define RB_EMPTY_ROOT(root)	((root)->rb_node == NULL)
Packit Service 0e769b
#define RB_EMPTY_NODE(node)	(rb_parent(node) == node)
Packit Service 0e769b
#define RB_CLEAR_NODE(node)	(rb_set_parent(node, node))
Packit Service 0e769b
Packit Service 0e769b
extern void rb_insert_color(struct fio_rb_node *, struct rb_root *);
Packit Service 0e769b
extern void rb_erase(struct fio_rb_node *, struct rb_root *);
Packit Service 0e769b
Packit Service 0e769b
/* Find logical next and previous nodes in a tree */
Packit Service 0e769b
extern struct fio_rb_node *rb_first(struct rb_root *);
Packit Service 0e769b
extern struct fio_rb_node *rb_next(const struct fio_rb_node *);
Packit Service 0e769b
Packit Service 0e769b
static inline void rb_link_node(struct fio_rb_node * node,
Packit Service 0e769b
				struct fio_rb_node * parent,
Packit Service 0e769b
				struct fio_rb_node ** rb_link)
Packit Service 0e769b
{
Packit Service 0e769b
	node->rb_parent_color = (uintptr_t)parent;
Packit Service 0e769b
	node->rb_left = node->rb_right = NULL;
Packit Service 0e769b
Packit Service 0e769b
	*rb_link = node;
Packit Service 0e769b
}
Packit Service 0e769b
Packit Service 0e769b
#endif	/* _LINUX_RBTREE_H */