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 Implement rcu_barrier to wait fo...



details:   https://anonhg.NetBSD.org/src/rev/970830a6da78
branches:  trunk
changeset: 1027943:970830a6da78
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sun Dec 19 01:19:45 2021 +0000

description:
Implement rcu_barrier to wait for call_rcu callbacks.

gc.cv has multiple purposes now, so use cv_broadcast instead of
cv_signal.

diffstat:

 sys/external/bsd/drm2/include/linux/rcupdate.h |   4 +-
 sys/external/bsd/drm2/linux/linux_rcu.c        |  51 +++++++++++++++++++++++--
 2 files changed, 50 insertions(+), 5 deletions(-)

diffs (145 lines):

diff -r 90fe9edaa06b -r 970830a6da78 sys/external/bsd/drm2/include/linux/rcupdate.h
--- a/sys/external/bsd/drm2/include/linux/rcupdate.h    Sun Dec 19 01:19:37 2021 +0000
+++ b/sys/external/bsd/drm2/include/linux/rcupdate.h    Sun Dec 19 01:19:45 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rcupdate.h,v 1.10 2021/12/19 01:18:09 riastradh Exp $  */
+/*     $NetBSD: rcupdate.h,v 1.11 2021/12/19 01:19:45 riastradh Exp $  */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -72,12 +72,14 @@
 };
 
 #define        call_rcu                linux_call_rcu
+#define        rcu_barrier             linux_rcu_barrier
 #define        synchronize_rcu         linux_synchronize_rcu
 
 int    linux_rcu_gc_init(void);
 void   linux_rcu_gc_fini(void);
 
 void   call_rcu(struct rcu_head *, void (*)(struct rcu_head *));
+void   rcu_barrier(void);
 void   synchronize_rcu(void);
 
 static inline void
diff -r 90fe9edaa06b -r 970830a6da78 sys/external/bsd/drm2/linux/linux_rcu.c
--- a/sys/external/bsd/drm2/linux/linux_rcu.c   Sun Dec 19 01:19:37 2021 +0000
+++ b/sys/external/bsd/drm2/linux/linux_rcu.c   Sun Dec 19 01:19:45 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_rcu.c,v 1.5 2021/07/21 06:34:52 skrll Exp $      */
+/*     $NetBSD: linux_rcu.c,v 1.6 2021/12/19 01:19:45 riastradh Exp $  */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_rcu.c,v 1.5 2021/07/21 06:34:52 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_rcu.c,v 1.6 2021/12/19 01:19:45 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -46,6 +46,8 @@
 SDT_PROBE_DEFINE0(sdt, linux, rcu, synchronize__start);
 SDT_PROBE_DEFINE1(sdt, linux, rcu, synchronize__cpu, "unsigned"/*cpu*/);
 SDT_PROBE_DEFINE0(sdt, linux, rcu, synchronize__done);
+SDT_PROBE_DEFINE0(sdt, linux, rcu, barrier__start);
+SDT_PROBE_DEFINE0(sdt, linux, rcu, barrier__done);
 SDT_PROBE_DEFINE2(sdt, linux, rcu, call__queue,
     "struct rcu_head *"/*head*/, "void (*)(struct rcu_head *)"/*callback*/);
 SDT_PROBE_DEFINE2(sdt, linux, rcu, call__run,
@@ -58,6 +60,7 @@
        kcondvar_t      cv;
        struct rcu_head *first;
        struct lwp      *lwp;
+       uint64_t        gen;
        bool            dying;
 } gc __cacheline_aligned;
 
@@ -68,6 +71,13 @@
        SDT_PROBE1(sdt, linux, rcu, synchronize__cpu,  cpu_index(curcpu()));
 }
 
+/*
+ * synchronize_rcu()
+ *
+ *     Wait for any pending RCU read section on every CPU to complete
+ *     by triggering on every CPU activity that is blocked by an RCU
+ *     read section.
+ */
 void
 synchronize_rcu(void)
 {
@@ -77,6 +87,36 @@
        SDT_PROBE0(sdt, linux, rcu, synchronize__done);
 }
 
+/*
+ * rcu_barrier()
+ *
+ *     Wait for all pending RCU callbacks to complete.
+ *
+ *     Does not imply, and is not implied by, synchronize_rcu.
+ */
+void
+rcu_barrier(void)
+{
+       uint64_t gen;
+
+       SDT_PROBE0(sdt, linux, rcu, barrier__start);
+       mutex_enter(&gc.lock);
+       if (gc.first != NULL) {
+               gen = gc.gen;
+               do {
+                       cv_wait(&gc.cv, &gc.lock);
+               } while (gc.gen == gen);
+       }
+       mutex_exit(&gc.lock);
+       SDT_PROBE0(sdt, linux, rcu, barrier__done);
+}
+
+/*
+ * call_rcu(head, callback)
+ *
+ *     Arrange to call callback(head) after any pending RCU read
+ *     sections on every CPU is complete.  Return immediately.
+ */
 void
 call_rcu(struct rcu_head *head, void (*callback)(struct rcu_head *))
 {
@@ -86,7 +126,7 @@
        mutex_enter(&gc.lock);
        head->rcuh_next = gc.first;
        gc.first = head;
-       cv_signal(&gc.cv);
+       cv_broadcast(&gc.cv);
        SDT_PROBE2(sdt, linux, rcu, call__queue,  head, callback);
        mutex_exit(&gc.lock);
 }
@@ -127,6 +167,8 @@
                        }
 
                        mutex_enter(&gc.lock);
+                       gc.gen++;               /* done running */
+                       cv_broadcast(&gc.cv);   /* notify rcu_barrier */
                }
 
                /* If we're asked to close shop, do so.  */
@@ -146,6 +188,7 @@
        mutex_init(&gc.lock, MUTEX_DEFAULT, IPL_VM);
        cv_init(&gc.cv, "lnxrcugc");
        gc.first = NULL;
+       gc.gen = 0;
        gc.dying = false;
 
        error = kthread_create(PRI_NONE,
@@ -168,7 +211,7 @@
 
        mutex_enter(&gc.lock);
        gc.dying = true;
-       cv_signal(&gc.cv);
+       cv_broadcast(&gc.cv);
        mutex_exit(&gc.lock);
 
        kthread_join(gc.lwp);



Home | Main Index | Thread Index | Old Index