X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=rcuja%2Frcuja-shadow-nodes.c;h=d6e4ff5db5212cbdda78eab45d6876a55bb862bd;hb=df65c98a4b6a3c3ba5e55c448521605fe14b6ec3;hp=e042cf20abf460557166a457eb6d77bef225e4e2;hpb=be9a7474cac017c7d0bed96efdb86e50ed0f6376;p=userspace-rcu.git diff --git a/rcuja/rcuja-shadow-nodes.c b/rcuja/rcuja-shadow-nodes.c index e042cf2..d6e4ff5 100644 --- a/rcuja/rcuja-shadow-nodes.c +++ b/rcuja/rcuja-shadow-nodes.c @@ -176,7 +176,7 @@ int match_pointer(struct cds_lfht_node *node, const void *key) __attribute__((visibility("protected"))) struct cds_ja_shadow_node *rcuja_shadow_lookup_lock(struct cds_lfht *ht, - struct cds_ja_node *node) + struct cds_ja_inode *node) { struct cds_lfht_iter iter; struct cds_lfht_node *lookup_node; @@ -196,6 +196,7 @@ struct cds_ja_shadow_node *rcuja_shadow_lookup_lock(struct cds_lfht *ht, } shadow_node = caa_container_of(lookup_node, struct cds_ja_shadow_node, ht_node); + dbg_printf("Lock %p\n", shadow_node->lock); ret = pthread_mutex_lock(shadow_node->lock); assert(!ret); if (cds_lfht_is_node_deleted(lookup_node)) { @@ -213,13 +214,14 @@ void rcuja_shadow_unlock(struct cds_ja_shadow_node *shadow_node) { int ret; + dbg_printf("Unlock %p\n", shadow_node->lock); ret = pthread_mutex_unlock(shadow_node->lock); assert(!ret); } __attribute__((visibility("protected"))) -int rcuja_shadow_set(struct cds_lfht *ht, - struct cds_ja_node *new_node, +struct cds_ja_shadow_node *rcuja_shadow_set(struct cds_lfht *ht, + struct cds_ja_inode *new_node, struct cds_ja_shadow_node *inherit_from) { struct cds_ja_shadow_node *shadow_node; @@ -228,7 +230,7 @@ int rcuja_shadow_set(struct cds_lfht *ht, shadow_node = calloc(sizeof(*shadow_node), 1); if (!shadow_node) - return -ENOMEM; + return NULL; shadow_node->node = new_node; /* @@ -240,7 +242,7 @@ int rcuja_shadow_set(struct cds_lfht *ht, shadow_node->lock = calloc(sizeof(*shadow_node->lock), 1); if (!shadow_node->lock) { free(shadow_node); - return -ENOMEM; + return NULL; } pthread_mutex_init(shadow_node->lock, NULL); } @@ -256,9 +258,17 @@ int rcuja_shadow_set(struct cds_lfht *ht, if (ret_node != &shadow_node->ht_node) { free(shadow_node); - return -EEXIST; + return NULL; } - return 0; + return shadow_node; +} + +static +void free_shadow_node(struct rcu_head *head) +{ + struct cds_ja_shadow_node *shadow_node = + caa_container_of(head, struct cds_ja_shadow_node, head); + free(shadow_node); } static @@ -270,11 +280,21 @@ void free_shadow_node_and_node(struct rcu_head *head) free(shadow_node); } +static +void free_shadow_node_and_lock(struct rcu_head *head) +{ + struct cds_ja_shadow_node *shadow_node = + caa_container_of(head, struct cds_ja_shadow_node, head); + free(shadow_node->lock); + free(shadow_node); +} + static 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->is_root); free(shadow_node->node); free(shadow_node->lock); free(shadow_node); @@ -282,17 +302,19 @@ void free_shadow_node_and_node_and_lock(struct rcu_head *head) __attribute__((visibility("protected"))) int rcuja_shadow_clear(struct cds_lfht *ht, - struct cds_ja_node *node, + struct cds_ja_inode *node, + struct cds_ja_shadow_node *shadow_node, unsigned int flags) { struct cds_lfht_iter iter; struct cds_lfht_node *lookup_node; - struct cds_ja_shadow_node *shadow_node; const struct rcu_flavor_struct *flavor; int ret, lockret; + int lookup_shadow = 0; flavor = cds_lfht_rcu_flavor(ht); flavor->read_lock(); + cds_lfht_lookup(ht, hash_pointer(node, hash_seed), match_pointer, node, &iter); lookup_node = cds_lfht_iter_get_node(&iter); @@ -300,10 +322,14 @@ int rcuja_shadow_clear(struct cds_lfht *ht, ret = -ENOENT; goto rcu_unlock; } - shadow_node = caa_container_of(lookup_node, - struct cds_ja_shadow_node, ht_node); - lockret = pthread_mutex_lock(shadow_node->lock); - assert(!lockret); + + if (!shadow_node) { + shadow_node = caa_container_of(lookup_node, + struct cds_ja_shadow_node, ht_node); + lockret = pthread_mutex_lock(shadow_node->lock); + assert(!lockret); + lookup_shadow = 1; + } /* * Holding the mutex across deletion, and by also re-checking if @@ -312,17 +338,29 @@ int rcuja_shadow_clear(struct cds_lfht *ht, */ ret = cds_lfht_del(ht, lookup_node); if (!ret) { - assert(flags & RCUJA_SHADOW_CLEAR_FREE_NODE); - if (flags & RCUJA_SHADOW_CLEAR_FREE_LOCK) { - flavor->update_call_rcu(&shadow_node->head, - free_shadow_node_and_node_and_lock); + if ((flags & RCUJA_SHADOW_CLEAR_FREE_NODE) + && !shadow_node->is_root) { + 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); + } } else { - flavor->update_call_rcu(&shadow_node->head, - free_shadow_node_and_node); + 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); + } } } - lockret = pthread_mutex_unlock(shadow_node->lock); - assert(!lockret); + if (lookup_shadow) { + lockret = pthread_mutex_unlock(shadow_node->lock); + assert(!lockret); + } rcu_unlock: flavor->read_unlock(); @@ -350,10 +388,24 @@ void rcuja_shadow_prune(struct cds_lfht *ht, ret = cds_lfht_del(ht, &shadow_node->ht_node); if (!ret) { - assert((flags & RCUJA_SHADOW_CLEAR_FREE_NODE) - && (flags & RCUJA_SHADOW_CLEAR_FREE_LOCK)); - flavor->update_call_rcu(&shadow_node->head, - free_shadow_node_and_node_and_lock); + if ((flags & RCUJA_SHADOW_CLEAR_FREE_NODE) + && !shadow_node->is_root) { + 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); + } + } 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); + } + } } lockret = pthread_mutex_unlock(shadow_node->lock); assert(!lockret);