[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Update radix-tree.[ch] from upstream Linux to gain RCU awareness.



# HG changeset patch
# User Keir Fraser <keir@xxxxxxx>
# Date 1304929523 -3600
# Node ID 44bfebf40b2bb7f219333ef5bf97eb7493592cdc
# Parent  4b0692880dfa557d4e1537c7a58c412c1286a416
Update radix-tree.[ch] from upstream Linux to gain RCU awareness.

We still leave behind features we don't need such as tagged nodes.

Other changes:
 - Allow callers to define their own node alloc routines.
 - Only allocate per-node rcu_head when using the default RCU-safe
   alloc routines.
 - Keep our own radix_tree_destroy().

In future it may also be worth getting rid of the complex and
pointless special-casing of radix-tree height==0, in which a single
data item can be stored directly in radix_tree_root. It introduces a
whole lot of special cases and complicates RCU handling. If we get rid
of it we can reclaim the 'indirect pointer' tag in bit 0 of every slot
entry.

Signed-off-by: Keir Fraser <keir@xxxxxxx>
---


diff -r 4b0692880dfa -r 44bfebf40b2b xen/common/radix-tree.c
--- a/xen/common/radix-tree.c   Thu May 05 17:40:34 2011 +0100
+++ b/xen/common/radix-tree.c   Mon May 09 09:25:23 2011 +0100
@@ -1,7 +1,8 @@
 /*
  * Copyright (C) 2001 Momchil Velikov
  * Portions Copyright (C) 2001 Christoph Hellwig
- * Copyright (C) 2005 SGI, Christoph Lameter <clameter@xxxxxxx>
+ * Copyright (C) 2005 SGI, Christoph Lameter
+ * Copyright (C) 2006 Nick Piggin
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -18,432 +19,740 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/*
- * Copyright (C) 2009 adaption for Xen tmem by Dan Magenheimer, Oracle Corp.
- * Changed:
- * o Linux 2.6.18 source used (prior to read-copy-update addition)
- * o constants and data structures moved out to radix-tree.h header
- * o tagging code removed
- * o radix_tree_insert has func parameter for dynamic data struct allocation
- * o radix_tree_destroy added (including recursive helper function)
- * o __init functions must be called explicitly
- * o other include files adapted to Xen
- */
-
 #include <xen/config.h>
 #include <xen/init.h>
-#include <xen/lib.h>
-#include <xen/types.h>
-#include <xen/errno.h>
 #include <xen/radix-tree.h>
-#include <asm/cache.h>
 
+struct radix_tree_path {
+       struct radix_tree_node *node;
+       int offset;
+};
+
+#define RADIX_TREE_INDEX_BITS  (8 /* CHAR_BIT */ * sizeof(unsigned long))
+#define RADIX_TREE_MAX_PATH (DIV_ROUND_UP(RADIX_TREE_INDEX_BITS, \
+                                         RADIX_TREE_MAP_SHIFT))
+
+/*
+ * The height_to_maxindex array needs to be one deeper than the maximum
+ * path as height 0 holds only 1 entry.
+ */
 static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH + 1] __read_mostly;
 
+static inline void *ptr_to_indirect(void *ptr)
+{
+       return (void *)((unsigned long)ptr | RADIX_TREE_INDIRECT_PTR);
+}
+
+static inline void *indirect_to_ptr(void *ptr)
+{
+       return (void *)((unsigned long)ptr & ~RADIX_TREE_INDIRECT_PTR);
+}
+
+struct rcu_node {
+       struct radix_tree_node node;
+       struct rcu_head rcu_head;
+};
+
+static struct radix_tree_node *rcu_node_alloc(void *arg)
+{
+       struct rcu_node *rcu_node = xmalloc(struct rcu_node);
+       return rcu_node ? &rcu_node->node : NULL;
+}
+
+static void _rcu_node_free(struct rcu_head *head)
+{
+       struct rcu_node *rcu_node =
+               container_of(head, struct rcu_node, rcu_head);
+       xfree(rcu_node);
+}
+
+static void rcu_node_free(struct radix_tree_node *node, void *arg)
+{
+       struct rcu_node *rcu_node = container_of(node, struct rcu_node, node);
+       call_rcu(&rcu_node->rcu_head, _rcu_node_free);
+}
+
+static struct radix_tree_node *radix_tree_node_alloc(
+       struct radix_tree_root *root)
+{
+       struct radix_tree_node *ret;
+       ret = root->node_alloc(root->node_alloc_free_arg);
+       if (ret)
+               memset(ret, 0, sizeof(*ret));
+       return ret;
+}
+
+static void radix_tree_node_free(
+       struct radix_tree_root *root, struct radix_tree_node *node)
+{
+       root->node_free(node, root->node_alloc_free_arg);
+}
+
 /*
- * Return the maximum key which can be store into a
- * radix tree with height HEIGHT.
+ *     Return the maximum key which can be store into a
+ *     radix tree with height HEIGHT.
  */
 static inline unsigned long radix_tree_maxindex(unsigned int height)
 {
-    return height_to_maxindex[height];
+       return height_to_maxindex[height];
 }
 
 /*
- * Extend a radix tree so it can store key @index.
+ *     Extend a radix tree so it can store key @index.
  */
-static int radix_tree_extend(struct radix_tree_root *root, unsigned long index,
-                             struct radix_tree_node *(*node_alloc)(void *), 
void *arg)
+static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
 {
-    struct radix_tree_node *node;
-    unsigned int height;
+       struct radix_tree_node *node;
+       unsigned int height;
 
-    /* Figure out what the height should be.  */
-    height = root->height + 1;
-    if (index > radix_tree_maxindex(height))
-        while (index > radix_tree_maxindex(height))
-            height++;
+       /* Figure out what the height should be.  */
+       height = root->height + 1;
+       while (index > radix_tree_maxindex(height))
+               height++;
 
-    if (root->rnode == NULL) {
-        root->height = height;
-        goto out;
-    }
+       if (root->rnode == NULL) {
+               root->height = height;
+               goto out;
+       }
 
-    do {
-        if (!(node = node_alloc(arg)))
-            return -ENOMEM;
+       do {
+               unsigned int newheight;
+               if (!(node = radix_tree_node_alloc(root)))
+                       return -ENOMEM;
 
-        /* Increase the height.  */
-        node->slots[0] = root->rnode;
+               /* Increase the height.  */
+               node->slots[0] = indirect_to_ptr(root->rnode);
 
-        node->count = 1;
-        root->rnode = node;
-        root->height++;
-    } while (height > root->height);
- out:
-    return 0;
+               newheight = root->height+1;
+               node->height = newheight;
+               node->count = 1;
+               node = ptr_to_indirect(node);
+               rcu_assign_pointer(root->rnode, node);
+               root->height = newheight;
+       } while (height > root->height);
+out:
+       return 0;
 }
 
 /**
- * radix_tree_insert    -    insert into a radix tree
- * @root:  radix tree root
- * @index:  index key
- * @item:  item to insert
+ *     radix_tree_insert    -    insert into a radix tree
+ *     @root:          radix tree root
+ *     @index:         index key
+ *     @item:          item to insert
  *
- * Insert an item into the radix tree at position @index.
+ *     Insert an item into the radix tree at position @index.
  */
-int radix_tree_insert(struct radix_tree_root *root, unsigned long index,
-                      void *item, struct radix_tree_node *(*node_alloc)(void 
*), void *arg)
+int radix_tree_insert(struct radix_tree_root *root,
+                       unsigned long index, void *item)
 {
-    struct radix_tree_node *node = NULL, *slot;
-    unsigned int height, shift;
-    int offset;
-    int error;
+       struct radix_tree_node *node = NULL, *slot;
+       unsigned int height, shift;
+       int offset;
+       int error;
 
-    /* Make sure the tree is high enough.  */
-    if (index > radix_tree_maxindex(root->height)) {
-        error = radix_tree_extend(root, index, node_alloc, arg);
-        if (error)
-            return error;
-    }
+       BUG_ON(radix_tree_is_indirect_ptr(item));
 
-    slot = root->rnode;
-    height = root->height;
-    shift = (height-1) * RADIX_TREE_MAP_SHIFT;
+       /* Make sure the tree is high enough.  */
+       if (index > radix_tree_maxindex(root->height)) {
+               error = radix_tree_extend(root, index);
+               if (error)
+                       return error;
+       }
 
-    offset = 0;   /* uninitialised var warning */
-    while (height > 0) {
-        if (slot == NULL) {
-            /* Have to add a child node.  */
-            if (!(slot = node_alloc(arg)))
-                return -ENOMEM;
-            if (node) {
+       slot = indirect_to_ptr(root->rnode);
 
-                node->slots[offset] = slot;
-                node->count++;
-            } else
-                root->rnode = slot;
-        }
+       height = root->height;
+       shift = (height-1) * RADIX_TREE_MAP_SHIFT;
 
-        /* Go a level down */
-        offset = (index >> shift) & RADIX_TREE_MAP_MASK;
-        node = slot;
-        slot = node->slots[offset];
-        shift -= RADIX_TREE_MAP_SHIFT;
-        height--;
-    }
+       offset = 0;                     /* uninitialised var warning */
+       while (height > 0) {
+               if (slot == NULL) {
+                       /* Have to add a child node.  */
+                       if (!(slot = radix_tree_node_alloc(root)))
+                               return -ENOMEM;
+                       slot->height = height;
+                       if (node) {
+                               rcu_assign_pointer(node->slots[offset], slot);
+                               node->count++;
+                       } else
+                               rcu_assign_pointer(root->rnode, 
ptr_to_indirect(slot));
+               }
 
-    if (slot != NULL)
-        return -EEXIST;
+               /* Go a level down */
+               offset = (index >> shift) & RADIX_TREE_MAP_MASK;
+               node = slot;
+               slot = node->slots[offset];
+               shift -= RADIX_TREE_MAP_SHIFT;
+               height--;
+       }
 
-    if (node) {
-        node->count++;
-        node->slots[offset] = item;
-    } else {
-        root->rnode = item;
-    }
+       if (slot != NULL)
+               return -EEXIST;
 
-    return 0;
+       if (node) {
+               node->count++;
+               rcu_assign_pointer(node->slots[offset], item);
+       } else {
+               rcu_assign_pointer(root->rnode, item);
+       }
+
+       return 0;
 }
 EXPORT_SYMBOL(radix_tree_insert);
 
-static inline void **__lookup_slot(struct radix_tree_root *root,
-                                   unsigned long index)
+/*
+ * is_slot == 1 : search for the slot.
+ * is_slot == 0 : search for the node.
+ */
+static void *radix_tree_lookup_element(struct radix_tree_root *root,
+                               unsigned long index, int is_slot)
 {
-    unsigned int height, shift;
-    struct radix_tree_node **slot;
+       unsigned int height, shift;
+       struct radix_tree_node *node, **slot;
 
-    height = root->height;
+       node = rcu_dereference(root->rnode);
+       if (node == NULL)
+               return NULL;
 
-    if (index > radix_tree_maxindex(height))
-        return NULL;
+       if (!radix_tree_is_indirect_ptr(node)) {
+               if (index > 0)
+                       return NULL;
+               return is_slot ? (void *)&root->rnode : node;
+       }
+       node = indirect_to_ptr(node);
 
-    if (height == 0 && root->rnode)
-        return (void **)&root->rnode;
+       height = node->height;
+       if (index > radix_tree_maxindex(height))
+               return NULL;
 
-    shift = (height-1) * RADIX_TREE_MAP_SHIFT;
-    slot = &root->rnode;
+       shift = (height-1) * RADIX_TREE_MAP_SHIFT;
 
-    while (height > 0) {
-        if (*slot == NULL)
-            return NULL;
+       do {
+               slot = (struct radix_tree_node **)
+                       (node->slots + ((index>>shift) & RADIX_TREE_MAP_MASK));
+               node = rcu_dereference(*slot);
+               if (node == NULL)
+                       return NULL;
 
-        slot = (struct radix_tree_node **)
-            ((*slot)->slots +
-             ((index >> shift) & RADIX_TREE_MAP_MASK));
-        shift -= RADIX_TREE_MAP_SHIFT;
-        height--;
-    }
+               shift -= RADIX_TREE_MAP_SHIFT;
+               height--;
+       } while (height > 0);
 
-    return (void **)slot;
+       return is_slot ? (void *)slot : indirect_to_ptr(node);
 }
 
 /**
- * radix_tree_lookup_slot    -    lookup a slot in a radix tree
- * @root:  radix tree root
- * @index:  index key
+ *     radix_tree_lookup_slot    -    lookup a slot in a radix tree
+ *     @root:          radix tree root
+ *     @index:         index key
  *
- * Lookup the slot corresponding to the position @index in the radix tree
- * @root. This is useful for update-if-exists operations.
+ *     Returns:  the slot corresponding to the position @index in the
+ *     radix tree @root. This is useful for update-if-exists operations.
+ *
+ *     This function can be called under rcu_read_lock iff the slot is not
+ *     modified by radix_tree_replace_slot, otherwise it must be called
+ *     exclusive from other writers. Any dereference of the slot must be done
+ *     using radix_tree_deref_slot.
  */
 void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long 
index)
 {
-    return __lookup_slot(root, index);
+       return (void **)radix_tree_lookup_element(root, index, 1);
 }
 EXPORT_SYMBOL(radix_tree_lookup_slot);
 
 /**
- * radix_tree_lookup    -    perform lookup operation on a radix tree
- * @root:  radix tree root
- * @index:  index key
+ *     radix_tree_lookup    -    perform lookup operation on a radix tree
+ *     @root:          radix tree root
+ *     @index:         index key
  *
- * Lookup the item at the position @index in the radix tree @root.
+ *     Lookup the item at the position @index in the radix tree @root.
+ *
+ *     This function can be called under rcu_read_lock, however the caller
+ *     must manage lifetimes of leaf nodes (eg. RCU may also be used to free
+ *     them safely). No RCU barriers are required to access or modify the
+ *     returned item, however.
  */
 void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index)
 {
-    void **slot;
-
-    slot = __lookup_slot(root, index);
-    return slot != NULL ? *slot : NULL;
+       return radix_tree_lookup_element(root, index, 0);
 }
 EXPORT_SYMBOL(radix_tree_lookup);
 
+/**
+ *     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). In rare cases of index wrap-around, 0 will be returned.
+ *
+ *     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);
+
+/**
+ *     radix_tree_prev_hole    -    find the prev hole (not-present entry)
+ *     @root:          tree root
+ *     @index:         index key
+ *     @max_scan:      maximum range to search
+ *
+ *     Search backwards in the range [max(index-max_scan+1, 0), index]
+ *     for the first hole.
+ *
+ *     Returns: the index of the hole if found, otherwise returns an index
+ *     outside of the set specified (in which case 'index - return >= max_scan'
+ *     will be true). In rare cases of wrap-around, ULONG_MAX will be returned.
+ *
+ *     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 10, then subsequently a hole is created at index 5,
+ *     radix_tree_prev_hole covering both indexes may return 5 if called under
+ *     rcu_read_lock.
+ */
+unsigned long radix_tree_prev_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 == ULONG_MAX)
+                       break;
+       }
+
+       return index;
+}
+EXPORT_SYMBOL(radix_tree_prev_hole);
+
 static unsigned int
-__lookup(struct radix_tree_root *root, void **results, unsigned long index,
-         unsigned int max_items, unsigned long *next_index)
+__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;
-    struct radix_tree_node *slot;
-    unsigned long i;
+       unsigned int nr_found = 0;
+       unsigned int shift, height;
+       unsigned long i;
 
-    height = root->height;
-    if (index > radix_tree_maxindex(height))
-        if (height == 0) {
-            if (root->rnode && index == 0)
-                results[nr_found++] = root->rnode;
-            goto out;
-        }
+       height = slot->height;
+       if (height == 0)
+               goto out;
+       shift = (height-1) * RADIX_TREE_MAP_SHIFT;
 
-    shift = (height-1) * RADIX_TREE_MAP_SHIFT;
-    slot = root->rnode;
+       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;
+               }
 
-    for ( ; height > 1; height--) {
+               shift -= RADIX_TREE_MAP_SHIFT;
+               slot = rcu_dereference(slot->slots[i]);
+               if (slot == NULL)
+                       goto out;
+       }
 
-        for (i = (index >> shift) & RADIX_TREE_MAP_MASK ;
-             i < RADIX_TREE_MAP_SIZE; i++) {
-            if (slot->slots[i] != NULL)
-                break;
-            index &= ~((1UL << shift) - 1);
-            index += 1UL << shift;
-            if (index == 0)
-                goto out; /* 32-bit wraparound */
-        }
-        if (i == RADIX_TREE_MAP_SIZE)
-            goto out;
-
-        shift -= RADIX_TREE_MAP_SHIFT;
-        slot = slot->slots[i];
-    }
-
-    /* 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;
+       /* 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
+ *     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.
+ *     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.
+ *     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 int
 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
-                       unsigned long first_index, unsigned int max_items)
+                       unsigned long first_index, unsigned int max_items)
 {
-    const unsigned long max_index = radix_tree_maxindex(root->height);
-    unsigned long cur_index = first_index;
-    unsigned int ret = 0;
+       unsigned long max_index;
+       struct radix_tree_node *node;
+       unsigned long cur_index = first_index;
+       unsigned int ret;
 
-    while (ret < max_items) {
-        unsigned int nr_found;
-        unsigned long next_index; /* Index of next search */
+       node = rcu_dereference(root->rnode);
+       if (!node)
+               return 0;
 
-        if (cur_index > max_index)
-            break;
-        nr_found = __lookup(root, results + ret, cur_index,
-                            max_items - ret, &next_index);
-        ret += nr_found;
-        if (next_index == 0)
-            break;
-        cur_index = next_index;
-    }
-    return ret;
+       if (!radix_tree_is_indirect_ptr(node)) {
+               if (first_index > 0)
+                       return 0;
+               results[0] = node;
+               return 1;
+       }
+       node = 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] =
+                               indirect_to_ptr(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_shrink    -    shrink height of a radix tree to minimal
- * @root  radix tree root
+ *     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.
  */
-static inline void radix_tree_shrink(struct radix_tree_root *root,
-                                     void (*node_free)(struct radix_tree_node 
*))
+unsigned int
+radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
+                       unsigned long first_index, unsigned int max_items)
 {
-    /* try to shrink tree height */
-    while (root->height > 0 &&
-           root->rnode->count == 1 &&
-           root->rnode->slots[0]) {
-        struct radix_tree_node *to_free = root->rnode;
+       unsigned long max_index;
+       struct radix_tree_node *node;
+       unsigned long cur_index = first_index;
+       unsigned int ret;
 
-        root->rnode = to_free->slots[0];
-        root->height--;
-        to_free->slots[0] = NULL;
-        to_free->count = 0;
-        node_free(to_free);
-    }
+       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 = 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 */
+
+               if (cur_index > max_index)
+                       break;
+               slots_found = __lookup(node, results + ret, cur_index,
+                                       max_items - ret, &next_index);
+               ret += slots_found;
+               if (next_index == 0)
+                       break;
+               cur_index = next_index;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(radix_tree_gang_lookup_slot);
+
+/**
+ *     radix_tree_shrink    -    shrink height of a radix tree to minimal
+ *     @root           radix tree root
+ */
+static inline void radix_tree_shrink(struct radix_tree_root *root)
+{
+       /* try to shrink tree height */
+       while (root->height > 0) {
+               struct radix_tree_node *to_free = root->rnode;
+               void *newptr;
+
+               BUG_ON(!radix_tree_is_indirect_ptr(to_free));
+               to_free = indirect_to_ptr(to_free);
+
+               /*
+                * The candidate node has more than one child, or its child
+                * is not at the leftmost slot, we cannot shrink.
+                */
+               if (to_free->count != 1)
+                       break;
+               if (!to_free->slots[0])
+                       break;
+
+               /*
+                * We don't need rcu_assign_pointer(), since we are simply
+                * moving the node from one part of the tree to another: if it
+                * was safe to dereference the old pointer to it
+                * (to_free->slots[0]), it will be safe to dereference the new
+                * one (root->rnode) as far as dependent read barriers go.
+                */
+               newptr = to_free->slots[0];
+               if (root->height > 1)
+                       newptr = ptr_to_indirect(newptr);
+               root->rnode = newptr;
+               root->height--;
+
+               /*
+                * We have a dilemma here. The node's slot[0] must not be
+                * NULLed in case there are concurrent lookups expecting to
+                * find the item. However if this was a bottom-level node,
+                * then it may be subject to the slot pointer being visible
+                * to callers dereferencing it. If item corresponding to
+                * slot[0] is subsequently deleted, these callers would expect
+                * their slot to become empty sooner or later.
+                *
+                * For example, lockless pagecache will look up a slot, deref
+                * the page pointer, and if the page is 0 refcount it means it
+                * was concurrently deleted from pagecache so try the deref
+                * again. Fortunately there is already a requirement for logic
+                * to retry the entire slot lookup -- the indirect pointer
+                * problem (replacing direct root node with an indirect pointer
+                * also results in a stale slot). So tag the slot as indirect
+                * to force callers to retry.
+                */
+               if (root->height == 0)
+                       *((unsigned long *)&to_free->slots[0]) |=
+                                               RADIX_TREE_INDIRECT_PTR;
+
+               radix_tree_node_free(root, to_free);
+       }
 }
 
 /**
- * radix_tree_delete    -    delete an item from a radix tree
- * @root:  radix tree root
- * @index:  index key
+ *     radix_tree_delete    -    delete an item from a radix tree
+ *     @root:          radix tree root
+ *     @index:         index key
  *
- * Remove the item at @index from the radix tree rooted at @root.
+ *     Remove the item at @index from the radix tree rooted at @root.
  *
- * Returns the address of the deleted item, or NULL if it was not present.
+ *     Returns the address of the deleted item, or NULL if it was not present.
  */
-void *radix_tree_delete(struct radix_tree_root *root, unsigned long index,
-                        void(*node_free)(struct radix_tree_node *))
+void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
 {
-    struct radix_tree_path path[RADIX_TREE_MAX_PATH + 1], *pathp = path;
-    struct radix_tree_node *slot = NULL;
-    unsigned int height, shift;
-    int offset;
+       /*
+        * 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;
+       struct radix_tree_node *to_free;
+       unsigned int height, shift;
+       int offset;
 
-    height = root->height;
-    if (index > radix_tree_maxindex(height))
-        goto out;
+       height = root->height;
+       if (index > radix_tree_maxindex(height))
+               goto out;
 
-    slot = root->rnode;
-    if (height == 0 && root->rnode) {
-        root->rnode = NULL;
-        goto out;
-    }
+       slot = root->rnode;
+       if (height == 0) {
+               root->rnode = NULL;
+               goto out;
+       }
+       slot = indirect_to_ptr(slot);
 
-    shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
-    pathp->node = NULL;
+       shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
+       pathp->node = NULL;
 
-    do {
-        if (slot == NULL)
-            goto out;
+       do {
+               if (slot == NULL)
+                       goto out;
 
-        pathp++;
-        offset = (index >> shift) & RADIX_TREE_MAP_MASK;
-        pathp->offset = offset;
-        pathp->node = slot;
-        slot = slot->slots[offset];
-        shift -= RADIX_TREE_MAP_SHIFT;
-        height--;
-    } while (height > 0);
+               pathp++;
+               offset = (index >> shift) & RADIX_TREE_MAP_MASK;
+               pathp->offset = offset;
+               pathp->node = slot;
+               slot = slot->slots[offset];
+               shift -= RADIX_TREE_MAP_SHIFT;
+               height--;
+       } while (height > 0);
 
-    if (slot == NULL)
-        goto out;
+       if (slot == NULL)
+               goto out;
 
-    /* Now free the nodes we do not need anymore */
-    while (pathp->node) {
-        pathp->node->slots[pathp->offset] = NULL;
-        pathp->node->count--;
+       to_free = NULL;
+       /* Now free the nodes we do not need anymore */
+       while (pathp->node) {
+               pathp->node->slots[pathp->offset] = NULL;
+               pathp->node->count--;
+               /*
+                * Queue the node for deferred freeing after the
+                * last reference to it disappears (set NULL, above).
+                */
+               if (to_free)
+                       radix_tree_node_free(root, to_free);
 
-        if (pathp->node->count) {
-            if (pathp->node == root->rnode)
-                radix_tree_shrink(root, node_free);
-            goto out;
-        }
+               if (pathp->node->count) {
+                       if (pathp->node == indirect_to_ptr(root->rnode))
+                               radix_tree_shrink(root);
+                       goto out;
+               }
 
-        /* Node with zero slots in use so free it */
-        node_free(pathp->node);
+               /* Node with zero slots in use so free it */
+               to_free = pathp->node;
+               pathp--;
 
-        pathp--;
-    }
-    root->height = 0;
-    root->rnode = NULL;
+       }
+       root->height = 0;
+       root->rnode = NULL;
+       if (to_free)
+               radix_tree_node_free(root, to_free);
 
- out:
-    return slot;
+out:
+       return slot;
 }
 EXPORT_SYMBOL(radix_tree_delete);
 
 static void
-radix_tree_node_destroy(struct radix_tree_node *node, unsigned int height,
-                        void (*slot_free)(void *), void (*node_free)(struct 
radix_tree_node *))
+radix_tree_node_destroy(
+       struct radix_tree_root *root, struct radix_tree_node *node,
+       void (*slot_free)(void *))
 {
-    int i;
+       int i;
 
-    if (height == 0)
-        return;
-    for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) {
-        if (node->slots[i]) {
-            if (height == 1) {
-                slot_free(node->slots[i]);
-                node->slots[i] = NULL;
-                continue;
-            }
-            radix_tree_node_destroy(node->slots[i], height-1,
-                                    slot_free, node_free);
-            node_free(node->slots[i]);
-            node->slots[i] = NULL;
-        }
-    }
+       for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) {
+               struct radix_tree_node *slot = node->slots[i];
+               BUG_ON(radix_tree_is_indirect_ptr(slot));
+               if (slot == NULL)
+                       continue;
+               if (node->height == 1) {
+                       if (slot_free)
+                               slot_free(slot);
+               } else {
+                       radix_tree_node_destroy(root, slot, slot_free);
+               }
+       }
+
+       radix_tree_node_free(root, node);
 }
 
-void radix_tree_destroy(struct radix_tree_root *root,
-                        void (*slot_free)(void *), void (*node_free)(struct 
radix_tree_node *))
+void radix_tree_destroy(
+       struct radix_tree_root *root,
+       void (*slot_free)(void *))
 {
-    if (root->rnode == NULL)
-        return;
-    if (root->height == 0)
-        slot_free(root->rnode);
-    else {
-        radix_tree_node_destroy(root->rnode, root->height,
-                                slot_free, node_free);
-        node_free(root->rnode);
-        root->height = 0;
-    }
-    root->rnode = NULL;
-    /* caller must delete root if desired */
-}
-EXPORT_SYMBOL(radix_tree_destroy);
-
-static unsigned long __init __maxindex(unsigned int height)
-{
-    unsigned int tmp = height * RADIX_TREE_MAP_SHIFT;
-    unsigned long index = (~0UL >> (RADIX_TREE_INDEX_BITS - tmp - 1)) >> 1;
-
-    if (tmp >= RADIX_TREE_INDEX_BITS)
-        index = ~0UL;
-    return index;
+       struct radix_tree_node *node = root->rnode;
+       if (node == NULL)
+               return;
+       if (!radix_tree_is_indirect_ptr(node)) {
+               if (slot_free)
+                       slot_free(node);
+       } else {
+               node = indirect_to_ptr(node);
+               radix_tree_node_destroy(root, node, slot_free);
+       }
+       radix_tree_init(root);
 }
 
-void __init radix_tree_init(void)
+void radix_tree_init(struct radix_tree_root *root)
 {
-    unsigned int i;
+       memset(root, 0, sizeof(*root));
+       root->node_alloc = rcu_node_alloc;
+       root->node_free = rcu_node_free;
+}
 
-    for (i = 0; i < ARRAY_SIZE(height_to_maxindex); i++)
-        height_to_maxindex[i] = __maxindex(i);
+void radix_tree_set_alloc_callbacks(
+       struct radix_tree_root *root,
+       radix_tree_alloc_fn_t *node_alloc,
+       radix_tree_free_fn_t *node_free,
+       void *node_alloc_free_arg)
+{
+       root->node_alloc = node_alloc;
+       root->node_free = node_free;
+       root->node_alloc_free_arg = node_alloc_free_arg;
 }
+
+static __init unsigned long __maxindex(unsigned int height)
+{
+       unsigned int width = height * RADIX_TREE_MAP_SHIFT;
+       int shift = RADIX_TREE_INDEX_BITS - width;
+
+       if (shift < 0)
+               return ~0UL;
+       if (shift >= BITS_PER_LONG)
+               return 0UL;
+       return ~0UL >> shift;
+}
+
+static __init int radix_tree_init_maxindex(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(height_to_maxindex); i++)
+               height_to_maxindex[i] = __maxindex(i);
+
+       return 0;
+}
+/* pre-SMP just so it runs before 'normal' initcalls */
+presmp_initcall(radix_tree_init_maxindex);
diff -r 4b0692880dfa -r 44bfebf40b2b xen/common/tmem.c
--- a/xen/common/tmem.c Thu May 05 17:40:34 2011 +0100
+++ b/xen/common/tmem.c Mon May 09 09:25:23 2011 +0100
@@ -772,15 +772,12 @@
     pgp_free(pgp,0);
 }
 
-FORWARD static rtn_t *rtn_alloc(void *arg);
-FORWARD static void rtn_free(rtn_t *rtn);
-
 static int pgp_add_to_obj(obj_t *obj, uint32_t index, pgp_t *pgp)
 {
     int ret;
 
     ASSERT_SPINLOCK(&obj->obj_spinlock);
-    ret = radix_tree_insert(&obj->tree_root, index, pgp, rtn_alloc, obj);
+    ret = radix_tree_insert(&obj->tree_root, index, pgp);
     if ( !ret )
         obj->pgp_count++;
     return ret;
@@ -795,7 +792,7 @@
     ASSERT_SENTINEL(obj,OBJ);
     ASSERT(obj->pool != NULL);
     ASSERT_SENTINEL(obj->pool,POOL);
-    pgp = radix_tree_delete(&obj->tree_root, index, rtn_free);
+    pgp = radix_tree_delete(&obj->tree_root, index);
     if ( pgp != NULL )
         obj->pgp_count--;
     ASSERT(obj->pgp_count >= 0);
@@ -828,15 +825,12 @@
 }
 
 /* called only indirectly from radix_tree_delete/destroy */
-static void rtn_free(rtn_t *rtn)
+static void rtn_free(rtn_t *rtn, void *arg)
 {
     pool_t *pool;
     objnode_t *objnode;
-    int i;
 
     ASSERT(rtn != NULL);
-    for (i = 0; i < RADIX_TREE_MAP_SIZE; i++)
-        ASSERT(rtn->slots[i] == NULL);
     objnode = container_of(rtn,objnode_t,rtn);
     ASSERT_SENTINEL(objnode,OBJNODE);
     INVERT_SENTINEL(objnode,OBJNODE);
@@ -943,7 +937,7 @@
     ASSERT(pool->client != NULL);
     ASSERT_WRITELOCK(&pool->pool_rwlock);
     if ( obj->tree_root.rnode != NULL ) /* may be a "stump" with no leaves */
-        radix_tree_destroy(&obj->tree_root, pgp_destroy, rtn_free);
+        radix_tree_destroy(&obj->tree_root, pgp_destroy);
     ASSERT((long)obj->objnode_count == 0);
     ASSERT(obj->tree_root.rnode == NULL);
     pool->obj_count--;
@@ -1003,7 +997,8 @@
     if (pool->obj_count > pool->obj_count_max)
         pool->obj_count_max = pool->obj_count;
     atomic_inc_and_max(global_obj_count);
-    INIT_RADIX_TREE(&obj->tree_root,0);
+    radix_tree_init(&obj->tree_root);
+    radix_tree_set_alloc_callbacks(&obj->tree_root, rtn_alloc, rtn_free, obj);
     spin_lock_init(&obj->obj_spinlock);
     obj->pool = pool;
     obj->oid = *oidp;
@@ -1022,7 +1017,7 @@
 static NOINLINE void obj_destroy(obj_t *obj, int no_rebalance)
 {
     ASSERT_WRITELOCK(&obj->pool->pool_rwlock);
-    radix_tree_destroy(&obj->tree_root, pgp_destroy, rtn_free);
+    radix_tree_destroy(&obj->tree_root, pgp_destroy);
     obj_free(obj,no_rebalance);
 }
 
@@ -2925,7 +2920,6 @@
     if ( !tmh_enabled() )
         return 0;
 
-    radix_tree_init();
     if ( tmh_dedup_enabled() )
         for (i = 0; i < 256; i++ )
         {
diff -r 4b0692880dfa -r 44bfebf40b2b xen/include/xen/lib.h
--- a/xen/include/xen/lib.h     Thu May 05 17:40:34 2011 +0100
+++ b/xen/include/xen/lib.h     Mon May 09 09:25:23 2011 +0100
@@ -48,7 +48,8 @@
 #define SWAP(_a, _b) \
    do { typeof(_a) _t = (_a); (_a) = (_b); (_b) = _t; } while ( 0 )
 
-#define DIV_ROUND(x, y) (((x) + (y) / 2) / (y))
+#define DIV_ROUND(n, d) (((n) + (d) / 2) / (d))
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]) + __must_be_array(x))
 
diff -r 4b0692880dfa -r 44bfebf40b2b xen/include/xen/radix-tree.h
--- a/xen/include/xen/radix-tree.h      Thu May 05 17:40:34 2011 +0100
+++ b/xen/include/xen/radix-tree.h      Mon May 09 09:25:23 2011 +0100
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2001 Momchil Velikov
  * Portions Copyright (C) 2001 Christoph Hellwig
- * Adapted for Xen by Dan Magenheimer, Oracle Corp.
+ * Copyright (C) 2006 Nick Piggin
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -20,59 +20,190 @@
 #ifndef _XEN_RADIX_TREE_H
 #define _XEN_RADIX_TREE_H
 
-/* root tags are stored in gfp_mask, shifted by __GFP_BITS_SHIFT */
-struct radix_tree_root {
-    unsigned int height;
-    struct radix_tree_node *rnode;
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/lib.h>
+#include <xen/rcupdate.h>
+
+/*
+ * An indirect pointer (root->rnode pointing to a radix_tree_node, rather
+ * than a data item) is signalled by the low bit set in the root->rnode
+ * pointer.
+ *
+ * In this case root->height is > 0, but the indirect pointer tests are
+ * needed for RCU lookups (because root->height is unreliable). The only
+ * time callers need worry about this is when doing a lookup_slot under
+ * RCU.
+ *
+ * Indirect pointer in fact is also used to tag the last pointer of a node
+ * when it is shrunk, before we rcu free the node. See shrink code for
+ * details.
+ */
+#define RADIX_TREE_INDIRECT_PTR        1
+
+static inline int radix_tree_is_indirect_ptr(void *ptr)
+{
+       return (int)((unsigned long)ptr & RADIX_TREE_INDIRECT_PTR);
+}
+
+/*
+ *** Radix tree structure definitions.
+ *** These are public to allow users to allocate instances of them.
+ *** However all fields are absolutely private.
+ */
+
+#define RADIX_TREE_MAP_SHIFT   6
+#define RADIX_TREE_MAP_SIZE    (1UL << RADIX_TREE_MAP_SHIFT)
+#define RADIX_TREE_MAP_MASK    (RADIX_TREE_MAP_SIZE-1)
+
+struct radix_tree_node {
+       unsigned int    height;         /* Height from the bottom */
+       unsigned int    count;
+       void __rcu      *slots[RADIX_TREE_MAP_SIZE];
 };
 
-#define RADIX_TREE_MAP_SHIFT 6
+typedef struct radix_tree_node *radix_tree_alloc_fn_t(void *);
+typedef void radix_tree_free_fn_t(struct radix_tree_node *, void *);
 
-#define RADIX_TREE_MAP_SIZE (1UL << RADIX_TREE_MAP_SHIFT)
-#define RADIX_TREE_MAP_MASK (RADIX_TREE_MAP_SIZE-1)
+struct radix_tree_root {
+       unsigned int            height;
+       struct radix_tree_node  __rcu *rnode;
 
-#define RADIX_TREE_TAG_LONGS \
- ((RADIX_TREE_MAP_SIZE + BITS_PER_LONG - 1) / BITS_PER_LONG)
-
-struct radix_tree_node {
-    unsigned int count;
-    void  *slots[RADIX_TREE_MAP_SIZE];
+       /* Allow to specify custom node alloc/dealloc routines. */
+       radix_tree_alloc_fn_t *node_alloc;
+       radix_tree_free_fn_t *node_free;
+       void *node_alloc_free_arg;
 };
 
-struct radix_tree_path {
-    struct radix_tree_node *node;
-    int offset;
-};
+/*
+ *** radix-tree API starts here **
+ */
 
-#define RADIX_TREE_INDEX_BITS  (8 /* CHAR_BIT */ * sizeof(unsigned long))
-#define RADIX_TREE_MAX_PATH (RADIX_TREE_INDEX_BITS/RADIX_TREE_MAP_SHIFT + 2)
+void radix_tree_init(struct radix_tree_root *root);
+void radix_tree_set_alloc_callbacks(
+       struct radix_tree_root *root,
+       radix_tree_alloc_fn_t *node_alloc,
+       radix_tree_free_fn_t *node_free,
+       void *node_alloc_free_arg);
 
+void radix_tree_destroy(
+       struct radix_tree_root *root,
+       void (*slot_free)(void *));
 
-#define RADIX_TREE_INIT(mask) {     \
- .height = 0,       \
- .rnode = NULL,       \
+/**
+ * Radix-tree synchronization
+ *
+ * The radix-tree API requires that users provide all synchronisation (with
+ * specific exceptions, noted below).
+ *
+ * Synchronization of access to the data items being stored in the tree, and
+ * management of their lifetimes must be completely managed by API users.
+ *
+ * For API usage, in general,
+ * - any function _modifying_ the tree (inserting or deleting items) must
+ *   exclude other modifications, and exclude any functions reading the tree.
+ * - any function _reading_ the tree (looking up items) must exclude
+ *   modifications to the tree, but may occur concurrently with other readers.
+ *
+ * The notable exceptions to this rule are the following functions:
+ * radix_tree_lookup
+ * radix_tree_lookup_slot
+ * radix_tree_gang_lookup
+ * radix_tree_gang_lookup_slot
+ *
+ * The first 7 functions are able to be called locklessly, using RCU. The
+ * caller must ensure calls to these functions are made within rcu_read_lock()
+ * regions. Other readers (lock-free or otherwise) and modifications may be
+ * running concurrently.
+ *
+ * It is still required that the caller manage the synchronization and 
lifetimes
+ * of the items. So if RCU lock-free lookups are used, typically this would 
mean
+ * that the items have their own locks, or are amenable to lock-free access; 
and
+ * that the items are freed by RCU (or only freed after having been deleted 
from
+ * the radix tree *and* a synchronize_rcu() grace period).
+ *
+ * (Note, rcu_assign_pointer and rcu_dereference are not needed to control
+ * access to data items when inserting into or looking up from the radix tree)
+ */
+
+/**
+ * radix_tree_deref_slot       - dereference a slot
+ * @pslot:     pointer to slot, returned by radix_tree_lookup_slot
+ * Returns:    item that was stored in that slot with any direct pointer flag
+ *             removed.
+ *
+ * For use with radix_tree_lookup_slot().  Caller must hold tree at least read
+ * locked across slot lookup and dereference. Not required if write lock is
+ * held (ie. items cannot be concurrently inserted).
+ *
+ * radix_tree_deref_retry must be used to confirm validity of the pointer if
+ * only the read lock is held.
+ */
+static inline void *radix_tree_deref_slot(void **pslot)
+{
+       return rcu_dereference(*pslot);
 }
 
-#define RADIX_TREE(name, mask) \
- struct radix_tree_root name = RADIX_TREE_INIT(mask)
+/**
+ * radix_tree_deref_retry      - check radix_tree_deref_slot
+ * @arg:       pointer returned by radix_tree_deref_slot
+ * Returns:    0 if retry is not required, otherwise retry is required
+ *
+ * radix_tree_deref_retry must be used with radix_tree_deref_slot.
+ */
+static inline int radix_tree_deref_retry(void *arg)
+{
+       return unlikely((unsigned long)arg & RADIX_TREE_INDIRECT_PTR);
+}
 
-#define INIT_RADIX_TREE(root, mask)     \
-do {         \
- (root)->height = 0;      \
- (root)->rnode = NULL;      \
-} while (0)
+/**
+ * radix_tree_replace_slot     - replace item in a slot
+ * @pslot:     pointer to slot, returned by radix_tree_lookup_slot
+ * @item:      new item to store in the slot.
+ *
+ * For use with radix_tree_lookup_slot().  Caller must hold tree write locked
+ * across slot lookup and replacement.
+ */
+static inline void radix_tree_replace_slot(void **pslot, void *item)
+{
+       BUG_ON(radix_tree_is_indirect_ptr(item));
+       rcu_assign_pointer(*pslot, item);
+}
 
-int radix_tree_insert(struct radix_tree_root *root, unsigned long index,
-                      void *item, struct radix_tree_node *(*node_alloc)(void 
*), void *arg);
+
+/**
+ * radix_tree_{int_to_ptr,ptr_to_int}:
+ * 
+ * Allow storage of signed integers in radix-tree slots. We use an encoding
+ * in which the bottom two bits of the slot pointer are reserved (bit 0 for
+ * the indirect-pointer tag; bit 1 always set to prevent an in-use
+ * integer-valued slot from being NULL and thus mistakenly being reaped).
+ */
+static inline void *radix_tree_int_to_ptr(int val)
+{
+    ASSERT((val <= (LONG_MAX >> 2)) && (val >= (LONG_MIN >> 2)));
+    return (void *)(((long)val << 2) | 0x2ul);
+}
+
+static inline int radix_tree_ptr_to_int(void *ptr)
+{
+    ASSERT(((long)ptr & 0x3) == 0x2);
+    return (int)((long)ptr >> 2);
+}
+
+int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
 void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
 void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long);
-void radix_tree_destroy(struct radix_tree_root *root,
-                        void (*slot_free)(void *), void (*node_free)(struct 
radix_tree_node *));
-void *radix_tree_delete(struct radix_tree_root *root, unsigned long index,
-                        void(*node_free)(struct radix_tree_node *));
+void *radix_tree_delete(struct radix_tree_root *, unsigned long);
 unsigned int
 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
-                       unsigned long first_index, unsigned int max_items);
-void radix_tree_init(void);
+                       unsigned long first_index, unsigned int max_items);
+unsigned int
+radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
+                       unsigned long first_index, unsigned int max_items);
+unsigned long radix_tree_next_hole(struct radix_tree_root *root,
+                               unsigned long index, unsigned long max_scan);
+unsigned long radix_tree_prev_hole(struct radix_tree_root *root,
+                               unsigned long index, unsigned long max_scan);
 
 #endif /* _XEN_RADIX_TREE_H */
diff -r 4b0692880dfa -r 44bfebf40b2b xen/include/xen/rcupdate.h
--- a/xen/include/xen/rcupdate.h        Thu May 05 17:40:34 2011 +0100
+++ b/xen/include/xen/rcupdate.h        Mon May 09 09:25:23 2011 +0100
@@ -38,6 +38,8 @@
 #include <xen/cpumask.h>
 #include <xen/preempt.h>
 
+#define __rcu
+
 /**
  * struct rcu_head - callback structure for use with RCU
  * @next: next update requests in a list

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.