From a8584bd986fc87c2641a36b5ee93fc55fb753b28 Mon Sep 17 00:00:00 2001 From: Justus Winter <4winter@informatik.uni-hamburg.de> Date: Thu, 14 May 2015 11:21:44 +0200 Subject: [PATCH gnumach 8/8] update radix tree code --- kern/rdxtree.c | 163 +++++++++++++++++++++++++++++++------------------------ kern/rdxtree.h | 26 +++++---- kern/rdxtree_i.h | 21 +++---- 3 files changed, 119 insertions(+), 91 deletions(-) diff --git a/kern/rdxtree.c b/kern/rdxtree.c index 44784f3..78868b1 100644 --- a/kern/rdxtree.c +++ b/kern/rdxtree.c @@ -21,12 +21,15 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Upstream site with license notes : + * http://git.sceen.net/rbraun/librbraun.git/ */ #include #include #include -#include #include #include @@ -34,9 +37,9 @@ #include "rdxtree.h" #include "rdxtree_i.h" +/* XXX */ #define CHAR_BIT 8U #define ERR_SUCCESS KERN_SUCCESS -//XXX #define ERR_BUSY KERN_INVALID_ARGUMENT #define ERR_NOMEM KERN_RESOURCE_SHORTAGE @@ -121,7 +124,7 @@ void rdxtree_cache_init(void) { kmem_cache_init(&rdxtree_node_cache, "rdxtree_node", - sizeof(struct rdxtree_node), 0, NULL, NULL, NULL, 0); + sizeof(struct rdxtree_node), 0, NULL, NULL, NULL, 0); } #ifdef RDXTREE_ENABLE_NODE_CREATION_FAILURES @@ -251,15 +254,20 @@ rdxtree_node_remove(struct rdxtree_node *node, unsigned int index) } static inline void * -rdxtree_node_find(struct rdxtree_node *node, unsigned int index, int get_slot) +rdxtree_node_find(struct rdxtree_node *node, unsigned int *indexp) { + unsigned int index; void *ptr; + index = *indexp; + while (index < ARRAY_SIZE(node->entries)) { - ptr = rdxtree_entry_addr(node->entries[index]); + ptr = rdxtree_entry_addr(llsync_read_ptr(node->entries[index])); - if (ptr != NULL) - return get_slot ? (void *)&node->entries[index] : ptr; + if (ptr != NULL) { + *indexp = index; + return ptr; + } index++; } @@ -695,115 +703,128 @@ rdxtree_replace_slot(void **slot, void *ptr) return old; } -static struct rdxtree_node * -rdxtree_walk(struct rdxtree *tree, struct rdxtree_node *node) +static void * +rdxtree_walk_next(struct rdxtree *tree, struct rdxtree_iter *iter) { - struct rdxtree_node *prev, *child; - unsigned int height, index; + struct rdxtree_node *root, *node, *prev; + unsigned int height, shift, index, orig_index; + rdxtree_key_t key; + void *entry; - if (node == NULL) { - height = tree->height; - node = rdxtree_entry_addr(tree->root); + entry = llsync_read_ptr(tree->root); - while (height > 1) { - node = rdxtree_node_find(node, 0, 0); - height--; - } + if (entry == NULL) + return NULL; - return node; + if (!rdxtree_entry_is_node(entry)) { + if (iter->key != (rdxtree_key_t)-1) + return NULL; + else { + iter->key = 0; + return rdxtree_entry_addr(entry); + } } - height = 0; + key = iter->key + 1; - for (;;) { - prev = node->parent; + if ((key == 0) && (iter->node != NULL)) + return NULL; - if (prev == NULL) - return NULL; + root = rdxtree_entry_addr(entry); - index = node->index; - child = rdxtree_node_find(prev, index + 1, 0); +restart: + node = root; + height = root->height + 1; - if (child != NULL) - break; + if (key > rdxtree_max_key(height)) + return NULL; - height++; - node = prev; - } + shift = (height - 1) * RDXTREE_RADIX; - node = child; + do { + prev = node; + index = (key >> shift) & RDXTREE_RADIX_MASK; + orig_index = index; + node = rdxtree_node_find(node, &index); + + if (node == NULL) { + shift += RDXTREE_RADIX; + key = ((key >> shift) + 1) << shift; - while (height > 0) { - node = rdxtree_node_find(node, 0, 0); + if (key == 0) + return NULL; + + goto restart; + } + + if (orig_index != index) + key = ((key >> shift) + (index - orig_index)) << shift; + + shift -= RDXTREE_RADIX; height--; - } + } while (height > 0); + iter->node = prev; + iter->key = key; return node; } void * -rdxtree_iter_next(struct rdxtree *tree, struct rdxtree_iter *iter) +rdxtree_walk(struct rdxtree *tree, struct rdxtree_iter *iter) { - unsigned int index; - - if (tree->height == 0) { - if (iter->slot != NULL) - return NULL; + unsigned int index, orig_index; + void *ptr; - iter->slot = &tree->root; - return *iter->slot; - } + if (iter->node == NULL) + return rdxtree_walk_next(tree, iter); - if (iter->node != NULL) { - index = iter->slot - ((struct rdxtree_node *)iter->node)->entries; - iter->slot = rdxtree_node_find(iter->node, index + 1, 1); - } + index = (iter->key + 1) & RDXTREE_RADIX_MASK; - if (iter->slot == NULL) { - iter->node = rdxtree_walk(tree, iter->node); + if (index != 0) { + orig_index = index; + ptr = rdxtree_node_find(iter->node, &index); - if (iter->node != NULL) - iter->slot = rdxtree_node_find(iter->node, 0, 1); + if (ptr != NULL) { + iter->key += (index - orig_index) + 1; + return ptr; + } } - if (iter->slot == NULL) - return NULL; - - return *iter->slot; + return rdxtree_walk_next(tree, iter); } void rdxtree_remove_all(struct rdxtree *tree) { - struct rdxtree_node *node, *parent, *next; - unsigned int height, index; + struct rdxtree_node *node, *parent; + struct rdxtree_iter iter; - height = tree->height; - - if (height == 0) { + if (tree->height == 0) { if (tree->root != NULL) llsync_assign_ptr(tree->root, NULL); return; } - node = rdxtree_walk(tree, NULL); + for (;;) { + rdxtree_iter_init(&iter); + rdxtree_walk_next(tree, &iter); - do { - next = rdxtree_walk(tree, node); + if (iter.node == NULL) + break; + node = iter.node; parent = node->parent; - if (parent != NULL) { - index = node->index; - rdxtree_node_remove(parent, index); - rdxtree_remove_bm_set(parent, index); + if (parent == NULL) + rdxtree_init(tree); + else { + rdxtree_node_remove(parent, node->index); + rdxtree_remove_bm_set(parent, node->index); rdxtree_cleanup(tree, parent); node->parent = NULL; } rdxtree_node_schedule_destruction(node); - - node = next; - } while (node != NULL); + } } diff --git a/kern/rdxtree.h b/kern/rdxtree.h index f2f38a0..b272f8a 100644 --- a/kern/rdxtree.h +++ b/kern/rdxtree.h @@ -27,6 +27,9 @@ * * In addition to the standard insertion operation, this implementation * can allocate keys for the caller at insertion time. + * + * Upstream site with license notes : + * http://git.sceen.net/rbraun/librbraun.git/ */ #ifndef _RDXTREE_H @@ -49,12 +52,6 @@ typedef uint64_t rdxtree_key_t; #endif /* RDXTREE_KEY_32 */ /* - * Initialize the node cache. - */ -void -rdxtree_cache_init(void); - -/* * Radix tree. */ struct rdxtree; @@ -181,10 +178,19 @@ void * rdxtree_replace_slot(void **slot, void *ptr); /* * Forge a loop to process all pointers of a tree. */ -#define rdxtree_for_each(tree, iter, ptr) \ -for (rdxtree_iter_init(iter), ptr = rdxtree_iter_next(tree, iter); \ - ptr != NULL; \ - ptr = rdxtree_iter_next(tree, iter)) +#define rdxtree_for_each(tree, iter, ptr) \ +for (rdxtree_iter_init(iter), ptr = rdxtree_walk(tree, iter); \ + ptr != NULL; \ + ptr = rdxtree_walk(tree, iter)) + +/* + * Return the key of the current pointer from an iterator. + */ +static inline rdxtree_key_t +rdxtree_iter_key(const struct rdxtree_iter *iter) +{ + return iter->key; +} /* * Remove all pointers from a tree. diff --git a/kern/rdxtree_i.h b/kern/rdxtree_i.h index 9c9f962..1bd1f64 100644 --- a/kern/rdxtree_i.h +++ b/kern/rdxtree_i.h @@ -13,6 +13,10 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * + * Upstream site with license notes : + * http://git.sceen.net/rbraun/librbraun.git/ */ #ifndef _RDXTREE_I_H @@ -28,10 +32,14 @@ struct rdxtree { /* * Radix tree iterator. + * + * The node member refers to the node containing the current pointer, if any. + * The key member refers to the current pointer, and is valid if and only if + * rdxtree_walk() has been called at least once on the iterator. */ struct rdxtree_iter { void *node; - void **slot; + rdxtree_key_t key; }; /* @@ -41,7 +49,7 @@ static inline void rdxtree_iter_init(struct rdxtree_iter *iter) { iter->node = NULL; - iter->slot = NULL; + iter->key = (rdxtree_key_t)-1; } int rdxtree_insert_common(struct rdxtree *tree, rdxtree_key_t key, @@ -53,13 +61,6 @@ int rdxtree_insert_alloc_common(struct rdxtree *tree, void *ptr, void * rdxtree_lookup_common(const struct rdxtree *tree, rdxtree_key_t key, int get_slot); -/* - * Walk over pointers in a tree. - * - * Move the iterator to the next pointer in the given tree. - * - * The next pointer is returned if there is one, NULL otherwise. - */ -void * rdxtree_iter_next(struct rdxtree *tree, struct rdxtree_iter *iter); +void * rdxtree_walk(struct rdxtree *tree, struct rdxtree_iter *iter); #endif /* _RDXTREE_I_H */ -- 2.1.4