Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/external/bsd/drm2/linux linux: Kludgily make radix tree ...
details: https://anonhg.NetBSD.org/src/rev/af42e783a7a7
branches: trunk
changeset: 1028723:af42e783a7a7
user: riastradh <riastradh%NetBSD.org@localhost>
date: Sun Dec 19 11:51:51 2021 +0000
description:
linux: Kludgily make radix tree safe for RCU
Using a lock is completely stupid (gotta be cpu_simple_lock because
there's no radix_tree_destroy or anything), and the nonsense to do
unvolatile/unconst is garbage, but it will serve to make this safe
for RCU until someone makes our radix tree code RCU-safe (which
Someone^TM should totally do).
diffstat:
sys/external/bsd/drm2/include/linux/radix-tree.h | 10 +-
sys/external/bsd/drm2/linux/linux_radixtree.c | 75 ++++++++++++++++++-----
2 files changed, 65 insertions(+), 20 deletions(-)
diffs (214 lines):
diff -r 21c5e73ea1d0 -r af42e783a7a7 sys/external/bsd/drm2/include/linux/radix-tree.h
--- a/sys/external/bsd/drm2/include/linux/radix-tree.h Sun Dec 19 11:51:43 2021 +0000
+++ b/sys/external/bsd/drm2/include/linux/radix-tree.h Sun Dec 19 11:51:51 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: radix-tree.h,v 1.7 2021/12/19 11:51:43 riastradh Exp $ */
+/* $NetBSD: radix-tree.h,v 1.8 2021/12/19 11:51:51 riastradh Exp $ */
/*-
* Copyright (c) 2021 The NetBSD Foundation, Inc.
@@ -30,6 +30,7 @@
#define _LINUX_RADIX_TREE_H_
#include <sys/radixtree.h>
+#include <sys/lock.h>
#include <linux/gfp.h>
@@ -45,12 +46,13 @@
#define radix_tree_next_slot linux_radix_tree_next_slot
struct radix_tree_root {
- struct radix_tree rtr_tree;
+ struct radix_tree rtr_tree;
+ __cpu_simple_lock_t rtr_lock; /* XXX lame-o */
};
struct radix_tree_iter {
- unsigned long index;
- struct radix_tree *rti_tree;
+ unsigned long index;
+ const struct radix_tree_root *rti_tree;
};
void INIT_RADIX_TREE(struct radix_tree_root *, gfp_t);
diff -r 21c5e73ea1d0 -r af42e783a7a7 sys/external/bsd/drm2/linux/linux_radixtree.c
--- a/sys/external/bsd/drm2/linux/linux_radixtree.c Sun Dec 19 11:51:43 2021 +0000
+++ b/sys/external/bsd/drm2/linux/linux_radixtree.c Sun Dec 19 11:51:51 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_radixtree.c,v 1.1 2021/12/19 11:51:43 riastradh Exp $ */
+/* $NetBSD: linux_radixtree.c,v 1.2 2021/12/19 11:51:51 riastradh Exp $ */
/*-
* Copyright (c) 2021 The NetBSD Foundation, Inc.
@@ -27,16 +27,25 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_radixtree.c,v 1.1 2021/12/19 11:51:43 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_radixtree.c,v 1.2 2021/12/19 11:51:51 riastradh Exp $");
+#include <sys/atomic.h>
+#include <sys/kmem.h>
+#include <sys/lock.h>
#include <sys/radixtree.h>
#include <linux/gfp.h>
#include <linux/radix-tree.h>
+#include <linux/rcupdate.h>
+#include <linux/slab.h>
+
+/* XXX mega-kludgerific */
+#define __UNVOLANST(p) ((void *)(unsigned long)(const volatile void *)(p))
struct kludge {
uint64_t k_key;
void *k_datum;
+ struct rcu_head k_rcu;
};
void
@@ -44,21 +53,30 @@
{
radix_tree_init_tree(&root->rtr_tree);
+ __cpu_simple_lock_init(&root->rtr_lock);
}
int
radix_tree_insert(struct radix_tree_root *root, unsigned long key, void *datum)
{
struct kludge *kludge;
+ int error;
- if ((kludge = kmem_zalloc(sizeof(*kludge), KM_NOSLEEP)) == NULL)
+ /* XXX No way to know whether the caller can sleep or not... */
+ if ((kludge = kzalloc(sizeof(*kludge), GFP_NOWAIT)) == NULL)
return -ENOMEM;
kludge->k_key = key;
kludge->k_datum = datum;
+ membar_exit();
+
+ __cpu_simple_lock(&root->rtr_lock);
+ error = radix_tree_insert_node(&root->rtr_tree, key, kludge);
+ __cpu_simple_unlock(&root->rtr_lock);
+
/* XXX errno NetBSD->Linux */
- return -radix_tree_insert_node(&root->rtr_tree, key, kludge);
+ return -error;
}
void *
@@ -67,12 +85,14 @@
struct kludge *kludge;
void *datum = NULL;
- if ((kludge = radix_tree_remove_node(&root->rtr_tree, key)) == NULL)
+ __cpu_simple_lock(&root->rtr_lock);
+ kludge = radix_tree_remove_node(&root->rtr_tree, key);
+ __cpu_simple_unlock(&root->rtr_lock);
+ if (kludge == NULL)
return NULL;
- /* XXX RCU defer */
datum = kludge->k_datum;
- kmem_free(kludge, sizeof(*kludge));
+ kfree_rcu(kludge, k_rcu);
return datum;
}
@@ -80,8 +100,13 @@
bool
radix_tree_empty(struct radix_tree_root *root)
{
+ bool empty;
- return radix_tree_empty_tree_p(&root->rtr_tree);
+ __cpu_simple_lock(&root->rtr_lock);
+ empty = radix_tree_empty_tree_p(&root->rtr_tree);
+ __cpu_simple_unlock(&root->rtr_lock);
+
+ return empty;
}
void *
@@ -89,9 +114,11 @@
{
struct kludge *kludge;
- kludge = radix_tree_lookup_node(&root->rtr_tree, key);
+ __cpu_simple_lock(__UNVOLANST(&root->rtr_lock));
+ kludge = radix_tree_lookup_node(__UNVOLANST(&root->rtr_tree), key);
+ __cpu_simple_unlock(__UNVOLANST(&root->rtr_lock));
if (kludge == NULL)
- NULL;
+ return NULL;
return kludge->k_datum;
}
@@ -118,16 +145,21 @@
{
void *result;
struct kludge *kludge;
+ unsigned nresults;
KASSERT(flags == 0);
- if (radix_tree_gang_lookup_node(&root->rtr_tree, I->index,
- &result, /*maxresults*/1, /*dense*/false) == 0)
+ __cpu_simple_lock(__UNVOLANST(&root->rtr_lock));
+ nresults = radix_tree_gang_lookup_node(__UNVOLANST(&root->rtr_tree),
+ I->index, &result, /*maxresults*/1, /*dense*/false);
+ __cpu_simple_unlock(__UNVOLANST(&root->rtr_lock));
+ if (nresults == 0)
return NULL;
+ KASSERT(nresults == 1);
kludge = result;
I->index = kludge->k_key;
- I->rti_tree = &root->rtr_tree;
+ I->rti_tree = root;
return &kludge->k_datum;
}
@@ -136,17 +168,25 @@
{
struct kludge *kludge;
void *result;
+ unsigned nresults;
KASSERT(flags == 0);
+
kludge = container_of(slot, struct kludge, k_datum);
- if (radix_tree_gang_lookup_node(I->rtr_tree, kludge->k_key,
- &result, /*maxresults*/1, /*dense*/true) == 0)
+
+ __cpu_simple_lock(__UNVOLANST(&I->rti_tree->rtr_lock));
+ nresults = radix_tree_gang_lookup_node(
+ __UNVOLANST(&I->rti_tree->rtr_tree),
+ kludge->k_key, &result, /*maxresults*/1, /*dense*/true);
+ __cpu_simple_unlock(__UNVOLANST(&I->rti_tree->rtr_lock));
+ if (nresults == 0)
return NULL;
+ KASSERT(nresults == 1);
kludge = result;
I->index = kludge->k_key;
- I->rti_tree = &root->rtr_tree;
+ /* XXX Hope the tree hasn't changed! */
return &kludge->k_datum;
}
@@ -157,6 +197,9 @@
struct kludge *kludge = container_of(slot, struct kludge, k_datum);
struct kludge *kludge0 __diagused;
+ __cpu_simple_lock(&root->rtr_lock);
kludge0 = radix_tree_remove_node(&root->rtr_tree, kludge->k_key);
+ __cpu_simple_unlock(&root->rtr_lock);
+
KASSERT(kludge0 == kludge);
}
Home |
Main Index |
Thread Index |
Old Index