__attribute__((visibility("protected")))
struct cds_ja_shadow_node *rcuja_shadow_lookup_lock(struct cds_lfht *ht,
struct cds_ja_node *node);
+
__attribute__((visibility("protected")))
void rcuja_shadow_unlock(struct cds_ja_shadow_node *shadow_node);
+
__attribute__((visibility("protected")))
int rcuja_shadow_set(struct cds_lfht *ht,
struct cds_ja_node *new_node,
struct cds_ja_shadow_node *inherit_from);
-__attribute__((visibility("protected")))
/* rcuja_shadow_clear flags */
enum {
RCUJA_SHADOW_CLEAR_FREE_LOCK = (1U << 1),
};
+__attribute__((visibility("protected")))
int rcuja_shadow_clear(struct cds_lfht *ht,
struct cds_ja_node *node,
unsigned int flags);
+
+__attribute__((visibility("protected")))
+void rcuja_shadow_prune(struct cds_lfht *ht,
+ unsigned int flags);
+
__attribute__((visibility("protected")))
struct cds_lfht *rcuja_create_ht(const struct rcu_flavor_struct *flavor);
+
__attribute__((visibility("protected")))
-void rcuja_delete_ht(struct cds_lfht *ht);
+int rcuja_delete_ht(struct cds_lfht *ht);
#endif /* _URCU_RCUJA_INTERNAL_H */
return ret;
}
+/*
+ * Delete all shadow nodes and nodes from hash table, along with their
+ * associated lock.
+ */
+__attribute__((visibility("protected")))
+void rcuja_shadow_prune(struct cds_lfht *ht,
+ unsigned int flags)
+{
+ const struct rcu_flavor_struct *flavor;
+ struct cds_ja_shadow_node *shadow_node;
+ struct cds_lfht_iter iter;
+ int ret, lockret;
+
+ flavor = cds_lfht_rcu_flavor(ht);
+ 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) {
+ 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);
+ }
+ lockret = pthread_mutex_unlock(shadow_node->lock);
+ assert(!lockret);
+ }
+ flavor->read_unlock();
+}
+
__attribute__((visibility("protected")))
struct cds_lfht *rcuja_create_ht(const struct rcu_flavor_struct *flavor)
{
}
__attribute__((visibility("protected")))
-void rcuja_delete_ht(struct cds_lfht *ht)
+int rcuja_delete_ht(struct cds_lfht *ht)
{
- int ret;
-
- ret = cds_lfht_destroy(ht, NULL);
- assert(!ret);
+ return cds_lfht_destroy(ht, NULL);
}
__attribute__((constructor))
rcuja_shadow_unlock(shadow_node);
return ret;
}
+
+struct cds_ja *_cds_ja_new(const struct rcu_flavor_struct *flavor)
+{
+ struct cds_ja *ja;
+
+ ja = calloc(sizeof(*ja), 1);
+ if (!ja)
+ goto ja_error;
+ /* ja->root is NULL */
+ ja->ht = rcuja_create_ht(flavor);
+ if (!ja->ht)
+ goto ht_error;
+ return ja;
+
+ht_error:
+ free(ja);
+ja_error:
+ return NULL;
+}
+
+/*
+ * There should be no more concurrent add to the judy array while it is
+ * being destroyed (ensured by the caller).
+ */
+int cds_ja_destroy(struct cds_ja *ja)
+{
+ rcuja_shadow_prune(ja->ht,
+ RCUJA_SHADOW_CLEAR_FREE_NODE | RCUJA_SHADOW_CLEAR_FREE_LOCK);
+ return rcuja_delete_ht(ja->ht);
+}