X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=rcuja%2Frcuja-shadow-nodes.c;h=b27812e3a74429efaaa945603499a7004421a1e8;hb=refs%2Fheads%2Furcu%2Frcuja-range;hp=983adef09a9928e9e839f7c022a7c120b99eea5c;hpb=3d8fe30760fd4fb67ce24b5aa011ab75f680a904;p=userspace-rcu.git diff --git a/rcuja/rcuja-shadow-nodes.c b/rcuja/rcuja-shadow-nodes.c index 983adef..b27812e 100644 --- a/rcuja/rcuja-shadow-nodes.c +++ b/rcuja/rcuja-shadow-nodes.c @@ -3,7 +3,7 @@ * * Userspace RCU library - RCU Judy Array Shadow Node Hash Table * - * Copyright 2012 - Mathieu Desnoyers + * Copyright 2012-2013 - Mathieu Desnoyers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,16 +24,15 @@ #include #include #include +#include +#include +#include #include #include #include -#include #include -#include -#include #include "rcuja-internal.h" -#include "bitfield.h" static unsigned long hash_seed; @@ -223,7 +222,7 @@ __attribute__((visibility("protected"))) struct cds_ja_shadow_node *rcuja_shadow_set(struct cds_lfht *ht, struct cds_ja_inode_flag *new_node_flag, struct cds_ja_shadow_node *inherit_from, - struct cds_ja *ja) + struct cds_ja *ja, int level) { struct cds_ja_shadow_node *shadow_node; struct cds_lfht_node *ret_node; @@ -240,6 +239,7 @@ struct cds_ja_shadow_node *rcuja_shadow_set(struct cds_lfht *ht, */ if (inherit_from) { shadow_node->lock = inherit_from->lock; + shadow_node->level = inherit_from->level; } else { shadow_node->lock = calloc(sizeof(*shadow_node->lock), 1); if (!shadow_node->lock) { @@ -247,6 +247,7 @@ struct cds_ja_shadow_node *rcuja_shadow_set(struct cds_lfht *ht, return NULL; } pthread_mutex_init(shadow_node->lock, NULL); + shadow_node->level = level; } flavor = cds_lfht_rcu_flavor(ht); @@ -278,7 +279,7 @@ void free_shadow_node_and_node(struct rcu_head *head) { struct cds_ja_shadow_node *shadow_node = caa_container_of(head, struct cds_ja_shadow_node, head); - free(ja_node_ptr(shadow_node->node_flag)); + free_cds_ja_node(shadow_node->ja, ja_node_ptr(shadow_node->node_flag)); free(shadow_node); } @@ -297,7 +298,7 @@ void free_shadow_node_and_node_and_lock(struct rcu_head *head) struct cds_ja_shadow_node *shadow_node = caa_container_of(head, struct cds_ja_shadow_node, head); assert(shadow_node->level); - free(ja_node_ptr(shadow_node->node_flag)); + free_cds_ja_node(shadow_node->ja, ja_node_ptr(shadow_node->node_flag)); free(shadow_node->lock); free(shadow_node); } @@ -339,26 +340,27 @@ int rcuja_shadow_clear(struct cds_lfht *ht, * don't let RCU JA use a node being removed. */ ret = cds_lfht_del(ht, lookup_node); - if (!ret) { - if ((flags & RCUJA_SHADOW_CLEAR_FREE_NODE) - && shadow_node->level) { - if (flags & RCUJA_SHADOW_CLEAR_FREE_LOCK) { - flavor->update_call_rcu(&shadow_node->head, - free_shadow_node_and_node_and_lock); - } else { - flavor->update_call_rcu(&shadow_node->head, - free_shadow_node_and_node); - } + if (ret) + goto unlock; + if ((flags & RCUJA_SHADOW_CLEAR_FREE_NODE) + && shadow_node->level) { + if (flags & RCUJA_SHADOW_CLEAR_FREE_LOCK) { + flavor->update_call_rcu(&shadow_node->head, + free_shadow_node_and_node_and_lock); } else { - if (flags & RCUJA_SHADOW_CLEAR_FREE_LOCK) { - flavor->update_call_rcu(&shadow_node->head, - free_shadow_node_and_lock); - } else { - flavor->update_call_rcu(&shadow_node->head, - free_shadow_node); - } + flavor->update_call_rcu(&shadow_node->head, + free_shadow_node_and_node); + } + } else { + if (flags & RCUJA_SHADOW_CLEAR_FREE_LOCK) { + flavor->update_call_rcu(&shadow_node->head, + free_shadow_node_and_lock); + } else { + flavor->update_call_rcu(&shadow_node->head, + free_shadow_node); } } +unlock: if (lookup_shadow) { lockret = pthread_mutex_unlock(shadow_node->lock); assert(!lockret); @@ -375,8 +377,7 @@ rcu_unlock: */ __attribute__((visibility("protected"))) void rcuja_shadow_prune(struct cds_lfht *ht, - unsigned int flags, - void (*free_node_cb)(struct rcu_head *head)) + unsigned int flags) { const struct rcu_flavor_struct *flavor; struct cds_ja_shadow_node *shadow_node; @@ -384,37 +385,37 @@ void rcuja_shadow_prune(struct cds_lfht *ht, int ret, lockret; flavor = cds_lfht_rcu_flavor(ht); + /* + * Read-side lock is needed to ensure hash table node existence + * vs concurrent resize. + */ flavor->read_lock(); cds_lfht_for_each_entry(ht, &iter, shadow_node, ht_node) { lockret = pthread_mutex_lock(shadow_node->lock); assert(!lockret); ret = cds_lfht_del(ht, &shadow_node->ht_node); - if (!ret) { - if ((flags & RCUJA_SHADOW_CLEAR_FREE_NODE) - && shadow_node->level) { - if (shadow_node->level == shadow_node->ja->tree_depth - 1) { - rcuja_free_all_children(shadow_node, - shadow_node->node_flag, - free_node_cb); - } - if (flags & RCUJA_SHADOW_CLEAR_FREE_LOCK) { - flavor->update_call_rcu(&shadow_node->head, - free_shadow_node_and_node_and_lock); - } else { - flavor->update_call_rcu(&shadow_node->head, - free_shadow_node_and_node); - } + if (ret) + goto unlock; + if ((flags & RCUJA_SHADOW_CLEAR_FREE_NODE) + && shadow_node->level) { + if (flags & RCUJA_SHADOW_CLEAR_FREE_LOCK) { + flavor->update_call_rcu(&shadow_node->head, + free_shadow_node_and_node_and_lock); } else { - if (flags & RCUJA_SHADOW_CLEAR_FREE_LOCK) { - flavor->update_call_rcu(&shadow_node->head, - free_shadow_node_and_lock); - } else { - flavor->update_call_rcu(&shadow_node->head, - free_shadow_node); - } + flavor->update_call_rcu(&shadow_node->head, + free_shadow_node_and_node); + } + } else { + if (flags & RCUJA_SHADOW_CLEAR_FREE_LOCK) { + flavor->update_call_rcu(&shadow_node->head, + free_shadow_node_and_lock); + } else { + flavor->update_call_rcu(&shadow_node->head, + free_shadow_node); } } + unlock: lockret = pthread_mutex_unlock(shadow_node->lock); assert(!lockret); }