#include <urcu-defer.h>
/* TODO: error handling testing for -ENOMEM */
-struct rcu_rbtree_node *rbtree_alloc(void)
+void *rbtree_alloc(size_t size)
{
- return calloc(1, sizeof(struct rcu_rbtree_node));
+ return malloc(size);
}
-void rbtree_free(struct rcu_head *head)
+void rbtree_free(void *ptr)
{
- struct rcu_rbtree_node *node =
- caa_container_of(head, struct rcu_rbtree_node, head);
- free(node);
+ free(ptr);
}
int tree_comp(void *a, void *b)
rcu_copy_mutex_lock();
for (i = 0; i < NR_RAND; i++) {
- node = rbtree_alloc();
//key[i] = (void *)(unsigned long)(rand() % 2048);
key[i] = (void *)(unsigned long)(((unsigned long) rand() * 4) % 2048);
//For more collisions
//key[i] = (void *)(unsigned long)(rand() % 6);
- node->begin = key[i];
+ //node->begin = key[i];
//node->end = (void *)((unsigned long) key[i] + 1);
- node->end = (void *)((unsigned long) key[i] + 4);
+ //node->end = (void *)((unsigned long) key[i] + 4);
rcu_read_lock();
- rcu_rbtree_insert(&rbtree, node);
+ rcu_rbtree_insert(&rbtree, key[i],
+ (void *)((unsigned long) key[i] + 4));
rcu_read_unlock();
}
rcu_copy_mutex_unlock();
assert(!rcu_rbtree_is_nil(&rbtree, node));
rcu_rbtree_remove(&rbtree, node);
rcu_read_unlock();
- call_rcu(&node->head, rbtree_free);
}
rcu_copy_mutex_unlock();
rcu_read_lock();
/* Insert items looked up by readers */
for (i = 0; i < global_items; i++) {
- node = rbtree_alloc();
global_key[i] = (void *)(unsigned long)(((unsigned long) rand() * 4) % 2048);
//global_key[i] = (void *)(unsigned long)(rand() % 2048);
//For more collisions
//global_key[i] = (void *)(unsigned long)(rand() % 6);
- node->begin = global_key[i];
+ //node->begin = global_key[i];
//node->end = (void *)((unsigned long) global_key[i] + 1);
- node->end = (void *)((unsigned long) global_key[i] + 4);
- rcu_rbtree_insert(&rbtree, node);
+ //node->end = (void *)((unsigned long) global_key[i] + 4);
+ rcu_rbtree_insert(&rbtree, global_key[i],
+ (void *)((unsigned long) global_key[i] + 4));
}
rcu_read_unlock();
node = rcu_rbtree_search(&rbtree, rbtree.root, global_key[i]);
assert(!rcu_rbtree_is_nil(&rbtree, node));
rcu_rbtree_remove(&rbtree, node);
- call_rcu(&node->head, rbtree_free);
}
rcu_read_unlock();
rcu_unregister_thread();
return x->decay_next;
}
+static
+void _rcu_rbtree_free(struct rcu_head *head)
+{
+ struct rcu_rbtree_node *node =
+ caa_container_of(head, struct rcu_rbtree_node, head);
+ node->rbtree->rbfree(node);
+}
+
static
struct rcu_rbtree_node *dup_decay_node(struct rcu_rbtree *rbtree,
struct rcu_rbtree_node *x)
if (rcu_rbtree_is_nil(rbtree, x))
return x;
- xc = rbtree->rballoc();
- memcpy(xc, x, sizeof(struct rcu_rbtree_node));
+ xc = rbtree->rballoc(sizeof(*xc));
+ memcpy(xc, x, sizeof(*xc));
xc->decay_next = NULL;
set_decay(x, xc);
- call_rcu(&x->head, rbtree->rbfree);
+ call_rcu(&x->head, _rcu_rbtree_free);
return xc;
}
* Returns 0 on success, or < 0 on error.
*/
int rcu_rbtree_insert(struct rcu_rbtree *rbtree,
- struct rcu_rbtree_node *z)
+ void *begin, void *end)
{
- struct rcu_rbtree_node *x, *y;
+ struct rcu_rbtree_node *x, *y, *z;
+
+ z = rbtree->rballoc(sizeof(*z));
+ z->begin = begin;
+ z->end = end;
dbg_printf("insert %p\n", z->begin);
assert(!is_decay(rbtree->root));
z->color = COLOR_RED;
z->decay_next = NULL;
z->max_end = z->end;
+ z->rbtree = rbtree;
if (rcu_rbtree_is_nil(rbtree, y)) {
set_parent(z, y, IS_RIGHT); /* pos arbitrary for root node */
* Commit all _CMM_STORE_SHARED().
*/
cmm_smp_wmc();
+ call_rcu(&z->head, _rcu_rbtree_free);
return 0;
}
typedef int (*rcu_rbtree_comp)(void *a, void *b);
/*
- * Node allocation and deletion functions.
+ * Allocation and deletion functions.
*/
-typedef struct rcu_rbtree_node *(*rcu_rbtree_alloc)(void);
-typedef void (*rcu_rbtree_free)(struct rcu_head *head);
+typedef void *(*rcu_rbtree_alloc)(size_t size);
+typedef void (*rcu_rbtree_free)(void *ptr);
/*
* struct rcu_rbtree_node must be aligned at least on 2 bytes.
* Set "high" to key + 1 to insert single-value nodes.
*/
struct rcu_rbtree_node {
- /* must be set upon insertion */
+ /* internally reserved */
void *begin; /* Start of range (inclusive) */
void *end; /* range end (exclusive) */
-
- /* internally reserved */
void *max_end; /* max range end of node and children */
/* parent uses low bit for "0 -> is left, 1 -> is right" */
unsigned long parent;
/* _left and _right must be updated with set_left(), set_right() */
struct rcu_rbtree_node *_left, *_right;
struct rcu_rbtree_node *decay_next;
+ struct rcu_rbtree *rbtree;
struct rcu_head head; /* For delayed free */
unsigned int color:1;
};
* Caller must have exclusive write access and hold RCU read-side lock.
*/
int rcu_rbtree_insert(struct rcu_rbtree *rbtree,
- struct rcu_rbtree_node *node);
+ void *begin, void *end);
/*
* Remove node from tree.
* "node".
* Returns 0 on success. May fail with -ENOMEM.
*
- * The caller is responsible for freeing the node after a grace period.
* Caller must have exclusive write access and hold RCU read-side lock
* across "search" and "remove".
*/