summaryrefslogtreecommitdiff
path: root/kern/rdxtree.c
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2017-01-26 23:17:52 +0100
committerRichard Braun <rbraun@sceen.net>2017-01-26 23:17:52 +0100
commit29c9d176f0ac8854ec29dc1c586bd53ddc3d7553 (patch)
treef4799382a67be8d868ba28969c0d1ee13a2c2838 /kern/rdxtree.c
parent7f32abc5bb79a3aa920b9468d4c6f391c497b2ad (diff)
kern/{llsync,rdxtree}: don't use llsync until it's ready
Diffstat (limited to 'kern/rdxtree.c')
-rw-r--r--kern/rdxtree.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/kern/rdxtree.c b/kern/rdxtree.c
index 4bce0569..90676e04 100644
--- a/kern/rdxtree.c
+++ b/kern/rdxtree.c
@@ -160,12 +160,8 @@ rdxtree_node_create(struct rdxtree_node **nodep, unsigned short height)
}
static void
-rdxtree_node_destroy(struct work *work)
+rdxtree_node_destroy(struct rdxtree_node *node)
{
- struct rdxtree_node *node;
-
- node = structof(work, struct rdxtree_node, work);
-
/* See rdxtree_shrink() */
if (node->nr_entries != 0) {
assert(node->nr_entries == 1);
@@ -179,11 +175,30 @@ rdxtree_node_destroy(struct work *work)
}
static void
+rdxtree_node_destroy_deferred(struct work *work)
+{
+ struct rdxtree_node *node;
+
+ node = structof(work, struct rdxtree_node, work);
+ rdxtree_node_destroy(node);
+}
+
+static void
rdxtree_node_schedule_destruction(struct rdxtree_node *node)
{
assert(node->parent == NULL);
- work_init(&node->work, rdxtree_node_destroy);
+ work_init(&node->work, rdxtree_node_destroy_deferred);
+
+ /*
+ * This assumes that llsync is initialized before scheduling is started
+ * so that there can be no read-side reference when destroying the node.
+ */
+ if (!llsync_ready()) {
+ rdxtree_node_destroy(node);
+ return;
+ }
+
llsync_defer(&node->work);
}