All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrzej Turko <andrzej.turko@linux.intel.com>
To: igt-dev@lists.freedesktop.org
Subject: [igt-dev] [PATCH i-g-t 2/4] lib/igt_bst: Add a BST interface and an AVL implementation
Date: Tue, 20 Jul 2021 16:12:30 +0200	[thread overview]
Message-ID: <20210720141232.12812-3-andrzej.turko@linux.intel.com> (raw)
In-Reply-To: <20210720141232.12812-1-andrzej.turko@linux.intel.com>

This adds an efficient binary search tree implementation
in order to support an allocator with best-fit strategy.

Signed-off-by: Andrzej Turko <andrzej.turko@linux.intel.com>
Cc: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
---
 lib/igt_bst.c     | 157 +++++++++++
 lib/igt_bst.h     |  69 +++++
 lib/igt_bst_avl.c | 651 ++++++++++++++++++++++++++++++++++++++++++++++
 lib/meson.build   |   2 +
 4 files changed, 879 insertions(+)
 create mode 100644 lib/igt_bst.c
 create mode 100644 lib/igt_bst.h
 create mode 100644 lib/igt_bst_avl.c

diff --git a/lib/igt_bst.c b/lib/igt_bst.c
new file mode 100644
index 000000000..a24859213
--- /dev/null
+++ b/lib/igt_bst.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include "igt_bst.h"
+
+
+/**
+ * igt_bst_insert
+ * @bst: igt_bst pointer
+ * @value: a pointer value being inserted
+ * @key: the key under which the value should be stored
+ *
+ * Inserts a new value to the bst.
+ *
+ * Returns: a pointer to the newly created node.
+ */
+void *igt_bst_insert(struct igt_bst *bst, void *value, uint64_t key)
+{
+	return bst->insert(bst, value, key);
+}
+
+/**
+ * igt_bst_erase
+ * @bst: igt_bst pointer
+ * @nodeptr: a pointer to a node in the bst
+ *
+ * Erases the indicated node.
+ *
+ * Returns: the value associated with the
+ * erased node.
+ */
+void *igt_bst_erase(struct igt_bst *bst, void *nodeptr)
+{
+	return bst->erase(bst, nodeptr);
+}
+
+/**
+ * igt_bst_query_successor
+ * @bst: igt_bst pointer
+ * @key: an arbitrary key
+ *
+ * Among the elements currently present in the bst,
+ * finds the one with the smallest key not smaller than
+ * the given key.
+ *
+ * Returns: a value associated with the found element,
+ * NULL if all keys in the tree are smaller than the key
+ * parameter.
+ */
+void *igt_bst_query_successor(struct igt_bst *bst, uint64_t key)
+{
+	return bst->query_successor(bst, key);
+}
+
+/**
+ * igt_bst_query_successor
+ * Similar to igt_bst_query_predecessor, but looks for an
+ * element with the greatest key not exceeding the parameter.
+ */
+void *igt_bst_query_predecessor(struct igt_bst *bst, uint64_t key)
+{
+	return bst->query_predecessor(bst, key);
+}
+
+/**
+ * igt_bst_pop_successor
+ * Like igt_bst_query_successor, but also removes the
+ * found element from the bst.
+ */
+void *igt_bst_pop_successor(struct igt_bst *bst, uint64_t key)
+{
+	return bst->pop_successor(bst, key);
+}
+
+/**
+ * igt_bst_pop_predecessor
+ * Like igt_bst_query_predecessor, but also removes the
+ * found element from the bst.
+ */
+void *igt_bst_pop_predecessor(struct igt_bst *bst, uint64_t key)
+{
+	return bst->pop_predecessor(bst, key);
+}
+
+/* check whether the bst contains any elements */
+bool igt_bst_empty(struct igt_bst *bst)
+{
+	return bst->bst_empty(bst);
+}
+
+/* retrieve the value from the element in the bst given by the pointer to its node */
+void *igt_bst_get_value(struct igt_bst *bst, void *nodeptr)
+{
+	return bst->get_value(nodeptr);
+}
+
+/* retrieve the key from the element the bst given by the pointer to its node */
+uint64_t igt_bst_get_key(struct igt_bst *bst, void *nodeptr)
+{
+	return bst->get_key(nodeptr);
+}
+
+/**
+ * igt_bst_leftmost_entry
+ * @bst: igt_bst pointer
+ *
+ * Finds an element in the bst with the smallest key.
+ *
+ * Returns: a pointer to the found node,
+ * NULL if the bst is empty.
+ */
+void *igt_bst_leftmost_entry(struct igt_bst *bst)
+{
+	return bst->leftmost_entry(bst);
+}
+
+/**
+ * igt_bst_rightmost_entry
+ * See igt_bst_leftmost_entry.
+ */
+void *igt_bst_rightmost_entry(struct igt_bst *bst)
+{
+	return bst->rightmost_entry(bst);
+}
+
+/**
+ * igt_bst_next_entry
+ * @bst: igt_bst pointer
+ * @nodeptr: a pointer to a node in the bst
+ *
+ * Finds the next element in the bst in the
+ * nondecreasing order of keys.
+ * Can be used to iterate over all elements.
+ *
+ * Retuns: a pointer to the next node in the bst,
+ * NULL if nodeptr points to the last node.
+ */
+void *igt_bst_next_entry(struct igt_bst *bst, void *nodeptr)
+{
+	return bst->next_entry(nodeptr);
+}
+
+/**
+ * igt_bst_prev_entry
+ * Like igt_bst_next_entry, but returns the previous node.
+ */
+void *igt_bst_prev_entry(struct igt_bst *bst, void *nodeptr)
+{
+	return bst->prev_entry(nodeptr);
+}
+
+void igt_bst_free(struct igt_bst *bst)
+{
+	bst->bst_free(bst);
+}
diff --git a/lib/igt_bst.h b/lib/igt_bst.h
new file mode 100644
index 000000000..f54fca50c
--- /dev/null
+++ b/lib/igt_bst.h
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#ifndef __IGT_BST_H
+#define __IGT_BST_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/**
+ * SECTION: igt_bst
+ * @short_description: a binary search tree interface
+ * @title: IGT Bst
+ * @include: igt_bst.h
+ *
+ * This interface operates on binary rearch trees
+ * which store void pointers ordered by uint64_t keys.
+ */
+
+struct igt_bst {
+
+	/* private structure of the BST */
+	void *priv;
+
+	void* (*insert)(struct igt_bst *bst, void *value, uint64_t key);
+	void* (*erase)(struct igt_bst *bst, void *nodeptr);
+	void* (*pop_successor)(struct igt_bst *bst, uint64_t key);
+	void* (*pop_predecessor)(struct igt_bst *bst, uint64_t key);
+	void* (*query_successor)(struct igt_bst *bst, uint64_t key);
+	void* (*query_predecessor)(struct igt_bst *bst, uint64_t key);
+	bool (*bst_empty)(struct igt_bst *bst);
+	void* (*get_value)(void *nodeptr);
+	uint64_t (*get_key)(void *nodeptr);
+	void* (*leftmost_entry)(struct igt_bst *bst);
+	void* (*rightmost_entry)(struct igt_bst *bst);
+	void* (*next_entry)(void *nodeptr);
+	void* (*prev_entry)(void *nodeptr);
+	void (*bst_free)(struct igt_bst *bst);
+	int (*validate)(struct igt_bst *bst);
+};
+
+/* contructors */
+struct igt_bst *igt_bst_avl_create(void);
+
+#define igt_bst_for_each_node(bst, nodeptr) \
+	for ((nodeptr) = (bst)->leftmost_entry(bst); (nodeptr); (nodeptr) = (bst)->next_entry(nodeptr))
+
+#define igt_bst_for_each_node_rev(bst, nodeptr) \
+	for ((nodeptr) = (bst)->rightmost_entry(bst); (nodeptr); (nodeptr) = (bst)->prev_entry(nodeptr))
+
+
+void *igt_bst_insert(struct igt_bst *bst, void *value, uint64_t key);
+void *igt_bst_erase(struct igt_bst *bst, void *nodeptr);
+void *igt_bst_query_successor(struct igt_bst *bst, uint64_t key);
+void *igt_bst_query_predecessor(struct igt_bst *bst, uint64_t key);
+void *igt_bst_pop_successor(struct igt_bst *bst, uint64_t key);
+void *igt_bst_pop_predecessor(struct igt_bst *bst, uint64_t key);
+bool igt_bst_empty(struct igt_bst *bst);
+void *igt_bst_get_value(struct igt_bst *bst, void *nodeptr);
+uint64_t igt_bst_get_key(struct igt_bst *bst, void *nodeptr);
+void *igt_bst_leftmost_entry(struct igt_bst *bst);
+void *igt_bst_rightmost_entry(struct igt_bst *bst);
+void *igt_bst_next_entry(struct igt_bst *bst, void *nodeptr);
+void *igt_bst_prev_entry(struct igt_bst *bst, void *nodeptr);
+void igt_bst_free(struct igt_bst *bst);
+
+#endif /* IGT_BST_H */
diff --git a/lib/igt_bst_avl.c b/lib/igt_bst_avl.c
new file mode 100644
index 000000000..7245a798d
--- /dev/null
+++ b/lib/igt_bst_avl.c
@@ -0,0 +1,651 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include "igt.h"
+#include "igt_bst.h"
+
+//#define AVLDBG
+#ifdef AVLDBG
+#define avl_debug(...) fprintf(stderr, __VA_ARGS__)
+#define avl_assert igt_assert
+#define avl_assert_f igt_assert_f
+#else
+#define avl_debug(...) {}
+#define avl_assert(...) {}
+#define avl_assert_f(...) {}
+#endif
+
+struct igt_avl_node {
+	uint64_t key;
+
+	struct igt_avl_node *left;
+	struct igt_avl_node *right;
+	struct igt_avl_node *parent;
+
+	int32_t height;
+
+	void *value;
+};
+
+struct igt_avl {
+	struct igt_avl_node *root;
+};
+
+static int __traverse_validate(struct igt_avl_node *node)
+{
+	int32_t node_balance, left_h, right_h;
+	int n = 1;
+
+	igt_assert(node);
+
+	left_h = 0;
+	right_h = 0;
+
+	avl_debug("at 0x%llx : < key %llu, value 0x%llx >\nleft 0x%llx ; right 0x%llx\n",
+		  (unsigned long long)node,
+		  (unsigned long long)node->key,
+		  (unsigned long long)node->value,
+		  (unsigned long long)node->left,
+		  (unsigned long long)node->right);
+
+	if (node->left) {
+		igt_assert(node->left->parent == node);
+		igt_assert_f(node->key >= node->left->key,
+			     "The order of keys is not preserved in the AVL tree");
+		left_h = node->left->height;
+		n += __traverse_validate(node->left);
+	}
+
+	if (node->right) {
+		igt_assert(node->right->parent == node);
+		igt_assert_f(node->right->key >= node->key,
+			     "The order of keys is not preserved in the AVL tree");
+		right_h = node->right->height;
+		n += __traverse_validate(node->right);
+	}
+
+	node_balance = left_h - right_h;
+	igt_assert(node_balance <= 1 && node_balance >= -1);
+	igt_assert(node->height == (left_h > right_h ? left_h : right_h) + 1);
+
+	return n;
+}
+
+static int avl_validate(struct igt_bst *bst)
+{
+	struct igt_avl *avl = bst->priv;
+
+	avl_debug("Tree traversal:\n");
+
+	/* an empty tree */
+	if (avl->root == NULL)
+		return 0;
+
+	igt_assert(!avl->root->parent);
+	return __traverse_validate(avl->root);
+}
+
+/* fix balance of all vertices from the given node to the root */
+static inline void __avl_fix_balance(struct igt_avl *avl, struct igt_avl_node *node)
+{
+	struct igt_avl_node *left, *right, *l_left, *l_right, *r_left, *r_right;
+	int32_t left_h, right_h, l_left_h, l_right_h, r_left_h, r_right_h;
+	int32_t balance, node_h;
+
+	while (node) {
+
+		node_h = node->height;
+		left = node->left;
+		left_h = (left ? left->height : 0);
+		right = node->right;
+		right_h = (right ? right->height : 0);
+		balance = left_h - right_h;
+
+		avl_debug("Correcting a node with key %llu at 0x%llx (%llu)\n",
+			 (unsigned long long)node->key,
+			  (unsigned long long)node,
+			  *((unsigned long long *)node->value));
+		avl_debug("Heights: %d [%d %d] : balance %d\n",
+			  node_h, left_h, right_h, balance);
+
+		if (balance > 1) {
+			avl_assert(balance == 2);
+			avl_assert(left);
+
+			/* 1st case: left son's subtree is too high */
+			l_left = left->left;
+			l_left_h = (l_left ? l_left->height : 0);
+			l_right = left->right;
+			l_right_h = (l_right ? l_right->height : 0);
+
+			if (l_right_h > l_left_h) {
+				avl_assert(l_right_h == right_h + 1);
+				avl_assert(l_left_h == right_h);
+				avl_assert(l_right);
+
+				/*
+				 * left son's (left's) right son (l_right) is too high,
+				 * rotate the left son and its right son
+				 *
+				 *       N                 N                N
+				 *      /                 /                /
+				 *     L    (rotate)     LR    (rename)   L
+				 *    / \    ----->     /  \    ----->   / \
+				 *  LL  LR             L   LRR          LL  LR
+				 *     /  \           / \
+				 *   LRL  LRR        LL  LRL
+				 *
+				 */
+
+				left->right = l_right->left;
+				if (l_right->left)
+					l_right->left->parent = left;
+				l_right->parent = node;
+				node->left = l_right;
+				l_right->left = left;
+				left->parent = l_right;
+
+				l_left = left;
+				left = l_right;
+				l_right = l_right->right;
+
+				l_left_h = --l_left->height;
+				l_right_h = (l_right ? l_right->height : 0);
+				left_h = ++left->height;
+			}
+
+			avl_assert(left);
+			avl_assert(left_h == right_h + 2);
+			avl_assert(l_left_h == right_h + 1);
+
+			/*
+			 * rotate the node and its left son
+			 *
+			 *       |               |               |
+			 *       N    (rotate)   L    (rename)   N
+			 *      / \    ----->   / \    ----->   / \
+			 *     L   R           LL  N          ... ...
+			 *    / \                 / \
+			 *  LL  LR               LR  R
+			 *
+			 */
+
+			node->left = l_right;
+			if (l_right)
+				l_right->parent = node;
+			left->parent = node->parent;
+			if (node->parent) {
+				if (node->parent->left == node)
+					node->parent->left = left;
+				else
+					node->parent->right = left;
+
+			} else {
+				avl->root = left;
+			}
+			node->parent = left;
+			left->right = node;
+
+			node->height = (l_right_h > right_h ? l_right_h : right_h) + 1;
+			left->height = (node->height > l_left_h ? node->height : l_left_h) + 1;
+
+			node = left;
+		}
+
+
+		if (balance < -1) {
+			avl_assert(balance == -2);
+			avl_assert(right);
+
+			/* 2nd case: right son's subtree is too high */
+			r_left = right->left;
+			r_left_h = (r_left ? r_left->height : 0);
+			r_right = right->right;
+			r_right_h = (r_right ? r_right->height : 0);
+
+			if (r_left_h > r_right_h) {
+				avl_assert(r_left_h == left_h + 1);
+				avl_assert(r_right_h == left_h);
+				avl_assert(r_left);
+
+				/*
+				 * right son's (right's) left son (r_left) is too high,
+				 * rotate the right son and its left son.
+				 *
+				 *       N                  N                N
+				 *        \                  \                \
+				 *         R   (rotate)      RL    (rename)    R
+				 *        / \   ----->      /  \    ----->    / \
+				 *      RL  RR            RLL   R            RL RR
+				 *     /  \                    / \
+				 *   RLL  RLR               RLR  RR
+				 *
+				 */
+
+				right->left = r_left->right;
+				if (r_left->right)
+					r_left->right->parent = right;
+				r_left->parent = node;
+				node->right = r_left;
+				r_left->right = right;
+				right->parent = r_left;
+
+				r_right = right;
+				right = r_left;
+				r_left = r_left->left;
+
+				r_right_h = --r_right->height;
+				r_left_h = (r_left ? r_left->height : 0);
+				right_h = ++right->height;
+			}
+
+			avl_assert(right);
+			avl_assert(right_h == left_h + 2);
+			avl_assert(r_right_h == left_h + 1);
+
+			/*
+			 * rotate the node and its right son
+			 *
+			 *       |               |               |
+			 *       N    (rotate)   R    (rename)   N
+			 *      / \    ----->   / \    ----->   / \
+			 *     L   R           N   RR         ... ...
+			 *        / \         / \
+			 *      RL   RR      L  RL
+			 *
+			 */
+
+			node->right = r_left;
+			if (r_left)
+				r_left->parent = node;
+			right->parent = node->parent;
+			if (node->parent) {
+				if (node->parent->left == node)
+					node->parent->left = right;
+				else
+					node->parent->right = right;
+
+			} else {
+				avl->root = right;
+			}
+			node->parent = right;
+			right->left = node;
+
+			node->height = (r_left_h > left_h ? r_left_h : left_h) + 1;
+			right->height = (node->height > r_right_h ? node->height : r_right_h) + 1;
+
+			node = right;
+		}
+
+		if (balance >= -1 && balance <= 1)
+			node->height = (left_h > right_h ? left_h : right_h) + 1;
+
+		avl_assert(node->height - node_h >= -1 && node->height - node_h <= 1);
+
+		if (node->height == node_h)
+			break;
+
+		node = node->parent;
+	}
+}
+
+static void *avl_insert(struct igt_bst *bst, void *value, uint64_t key)
+{
+	struct igt_avl *avl = bst->priv;
+	struct igt_avl_node *node, *parent;
+
+	node = avl->root;
+	parent = NULL;
+	while (node) {
+		parent = node;
+		if (key < node->key)
+			node = node->left;
+		else
+			node = node->right;
+	}
+
+	node = malloc(sizeof(struct igt_avl_node));
+	igt_assert(node);
+	node->key = key;
+	node->parent = parent;
+	node->left = NULL;
+	node->right = NULL;
+	node->height = 1;
+	node->value = value;
+	if (parent) {
+		if (key < parent->key)
+			parent->left = node;
+		else
+			parent->right = node;
+
+		__avl_fix_balance(avl, parent);
+	} else {
+		avl->root = node;
+	}
+
+	return node;
+}
+
+static inline void
+__avl_erase_node(struct igt_avl *avl, struct igt_avl_node *node,
+		 struct igt_avl_node *del_pos)
+{
+	struct igt_avl_node *parent, *son;
+
+	avl_assert(node);
+	avl_assert(del_pos);
+	avl_assert(!del_pos->left || !del_pos->right);
+	son = (del_pos->left ? del_pos->left : del_pos->right);
+	parent = del_pos->parent;
+
+	avl_debug("Erasing node 0x%llx with position 0x%llx\n",
+		  (unsigned long long)node, (unsigned long long)del_pos);
+
+	if (node != del_pos) {
+		/* move a node from the deleted position
+		 * to place of the deleted node
+		 */
+
+		del_pos->left = node->left;
+		if (del_pos->left)
+			del_pos->left->parent = del_pos;
+		del_pos->right = node->right;
+		if (del_pos->right)
+			del_pos->right->parent = del_pos;
+
+		del_pos->parent = node->parent;
+		if (node->parent) {
+			if (node->parent->left == node)
+				node->parent->left = del_pos;
+			else
+				node->parent->right = del_pos;
+
+		} else {
+			avl->root = del_pos;
+		}
+
+		del_pos->height = node->height;
+
+		if (parent == node)
+			parent = del_pos;
+
+	}
+
+	if (son)
+		son->parent = parent;
+
+	if (parent) {
+		if (parent->left == del_pos)
+			parent->left = son;
+		else
+			parent->right = son;
+
+		__avl_fix_balance(avl, parent);
+	} else {
+		avl->root = son;
+	}
+
+	avl_assert(del_pos->parent != del_pos);
+
+	free(node);
+}
+
+static void *avl_erase(struct igt_bst *bst, void *nodeptr)
+{
+	struct igt_avl_node *node, *del_pos;
+	void *value;
+
+	igt_assert(nodeptr);
+	node = (struct igt_avl_node *) nodeptr;
+	value = node->value;
+	del_pos = node->left;
+	if (del_pos) {
+		while (del_pos->right)
+			del_pos = del_pos->right;
+
+		__avl_erase_node(bst->priv, node, del_pos);
+	} else {
+		__avl_erase_node(bst->priv, node, node);
+	}
+
+	return value;
+}
+
+static void *avl_pop_successor(struct igt_bst *bst, uint64_t key)
+{
+	struct igt_avl *avl = bst->priv;
+	struct igt_avl_node *node, *succ, *parent;
+	void *value;
+
+	node = avl->root;
+	parent = NULL;
+	succ = NULL;
+	while (node) {
+		parent = node;
+		if (node->key >= key) {
+			succ = node;
+			node = node->left;
+		} else {
+			node = node->right;
+		}
+	}
+
+	if (!succ)
+		return NULL;
+
+	value = succ->value;
+	__avl_erase_node(avl, succ, parent);
+
+	return value;
+}
+
+static void *avl_pop_predecessor(struct igt_bst *bst, uint64_t key)
+{
+	struct igt_avl *avl = bst->priv;
+	struct igt_avl_node *node, *parent, *pred;
+	void *value;
+
+	node = avl->root;
+	parent = NULL;
+	pred = NULL;
+	while (node) {
+		parent = node;
+		if (node->key <= key) {
+			pred = node;
+			node = node->right;
+		} else {
+			node = node->left;
+		}
+	}
+
+	if (!pred)
+		return NULL;
+
+	value = pred->value;
+	__avl_erase_node(avl, pred, parent);
+
+	return value;
+}
+
+static void *avl_query_successor(struct igt_bst *bst, uint64_t key)
+{
+	struct igt_avl *avl = bst->priv;
+	struct igt_avl_node *node;
+	void *value = NULL;
+
+	node = avl->root;
+	while (node) {
+		if (node->key >= key) {
+			value = node->value;
+			node = node->left;
+		} else {
+			node = node->right;
+		}
+	}
+
+	return value;
+}
+
+static void *avl_query_predecessor(struct igt_bst *bst, uint64_t key)
+{
+	struct igt_avl *avl = bst->priv;
+	struct igt_avl_node *node;
+	void *value = NULL;
+
+	node = avl->root;
+	while (node) {
+		if (node->key <= key) {
+			value = node->value;
+			node = node->right;
+		} else {
+			node = node->left;
+		}
+	}
+
+	return value;
+}
+
+static bool avl_bst_empty(struct igt_bst *bst)
+{
+	struct igt_avl *avl = bst->priv;
+
+	return (avl->root == NULL);
+}
+
+
+static void *avl_get_value(void *nodeptr)
+{
+	return ((struct igt_avl_node *)nodeptr)->value;
+}
+
+static uint64_t avl_get_key(void *nodeptr)
+{
+	return ((struct igt_avl_node *)nodeptr)->key;
+}
+
+static void *avl_leftmost_entry(struct igt_bst *bst)
+{
+	struct igt_avl *avl = bst->priv;
+	struct igt_avl_node *node;
+
+	node = avl->root;
+	if (node) {
+		while (node->left)
+			node = node->left;
+	}
+
+	return node;
+}
+
+static void *avl_rightmost_entry(struct igt_bst *bst)
+{
+	struct igt_avl *avl = bst->priv;
+	struct igt_avl_node *node;
+
+	node = avl->root;
+	if (node) {
+		while (node->right)
+			node = node->right;
+	}
+	return node;
+}
+
+static void *avl_next_entry(void *nodeptr)
+{
+	struct igt_avl_node *node;
+
+	igt_assert(nodeptr);
+	node = (struct igt_avl_node *) nodeptr;
+	if (node->right) {
+		node = node->right;
+		while (node->left)
+			node = node->left;
+
+		return node;
+	}
+	while (node->parent) {
+		if (node->parent->left == node)
+			return node->parent;
+
+		node = node->parent;
+	}
+	return NULL;
+}
+
+static void *avl_prev_entry(void *nodeptr)
+{
+	struct igt_avl_node *node;
+
+	igt_assert(nodeptr);
+	node = (struct igt_avl_node *) nodeptr;
+	if (node->left) {
+		node = node->left;
+		while (node->right)
+			node = node->right;
+
+		return node;
+	}
+	while (node->parent) {
+		if (node->parent->right == node)
+			return node->parent;
+
+		node = node->parent;
+	}
+	return NULL;
+}
+
+static void __avl_free(struct igt_avl_node *node)
+{
+	avl_assert(node);
+
+	if (node->left)
+		__avl_free(node->left);
+
+	if (node->right)
+		__avl_free(node->right);
+
+	free(node);
+}
+
+static void avl_bst_free(struct igt_bst *bst)
+{
+	struct igt_avl *avl = bst->priv;
+
+	if (avl->root)
+		__avl_free(avl->root);
+
+	free(avl);
+}
+
+struct igt_bst *igt_bst_avl_create(void)
+{
+	struct igt_avl *avl;
+	struct igt_bst *bst;
+
+	avl = malloc(sizeof(struct igt_avl));
+	bst = malloc(sizeof(struct igt_bst));
+	igt_assert(avl);
+	igt_assert(bst);
+
+	avl->root = NULL;
+	bst->priv = avl;
+	bst->insert = avl_insert;
+	bst->erase = avl_erase;
+	bst->pop_successor = avl_pop_successor;
+	bst->pop_predecessor = avl_pop_predecessor;
+	bst->query_successor = avl_query_successor;
+	bst->query_predecessor = avl_query_predecessor;
+	bst->bst_empty = avl_bst_empty;
+	bst->get_value = avl_get_value;
+	bst->get_key = avl_get_key;
+	bst->leftmost_entry = avl_leftmost_entry;
+	bst->rightmost_entry = avl_rightmost_entry;
+	bst->next_entry = avl_next_entry;
+	bst->prev_entry = avl_prev_entry;
+	bst->bst_free = avl_bst_free;
+	bst->validate = avl_validate;
+
+	return bst;
+}
diff --git a/lib/meson.build b/lib/meson.build
index 67d405129..a1aa0ee12 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -11,6 +11,8 @@ lib_sources = [
 	'i915/gem_mman.c',
 	'i915/gem_vm.c',
 	'i915/intel_memory_region.c',
+	'igt_bst.c',
+	'igt_bst_avl.c',
 	'igt_collection.c',
 	'igt_color_encoding.c',
 	'igt_debugfs.c',
-- 
2.25.1

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

  parent reply	other threads:[~2021-07-20 14:12 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-20 14:12 [igt-dev] [PATCH i-g-t v2 0/4] Implement the BST allocator Andrzej Turko
2021-07-20 14:12 ` [igt-dev] [PATCH i-g-t 1/4] lib/intel_allocator: Fix argument names in declarations Andrzej Turko
2021-07-21  9:19   ` Zbigniew Kempczyński
2021-07-20 14:12 ` Andrzej Turko [this message]
2021-07-20 14:12 ` [igt-dev] [PATCH i-g-t 3/4] lib/intel_allocator_bst: Implement the allocator with a BST Andrzej Turko
2021-07-20 14:12 ` [igt-dev] [PATCH i-g-t 4/4] tests/i915_api_intel_allocator: Add the BST allocator Andrzej Turko
2021-07-20 15:21 ` [igt-dev] ✓ Fi.CI.BAT: success for Implement the BST allocator (rev2) Patchwork
2021-07-20 16:31 ` [igt-dev] ✗ Fi.CI.IGT: failure " Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2021-07-20 13:27 [igt-dev] [PATCH i-g-t 0/4] Implement the BST allocator Andrzej Turko
2021-07-20 13:27 ` [igt-dev] [PATCH i-g-t 2/4] lib/igt_bst: Add a BST interface and an AVL implementation Andrzej Turko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210720141232.12812-3-andrzej.turko@linux.intel.com \
    --to=andrzej.turko@linux.intel.com \
    --cc=igt-dev@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.