summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0346-rcu-Update-rcuwait.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/0346-rcu-Update-rcuwait.patch')
-rw-r--r--debian/patches-rt/0346-rcu-Update-rcuwait.patch176
1 files changed, 176 insertions, 0 deletions
diff --git a/debian/patches-rt/0346-rcu-Update-rcuwait.patch b/debian/patches-rt/0346-rcu-Update-rcuwait.patch
new file mode 100644
index 000000000..c54c65f9c
--- /dev/null
+++ b/debian/patches-rt/0346-rcu-Update-rcuwait.patch
@@ -0,0 +1,176 @@
+From: Daniel Wagner <wagi@monom.org>
+Date: Mon, 24 Oct 2022 10:58:29 +0200
+Subject: [PATCH 346/351] rcu: Update rcuwait
+Origin: https://git.kernel.org/cgit/linux/kernel/git/rt/linux-stable-rt.git/commit?id=6f1be9e81d653b56aeefbff1883d1f762e8b594e
+
+This is an all in one commit backporting updates for rcuwait:
+ - 03f4b48edae7 ("rcuwait: Annotate task_struct with __rcu")
+ - 191a43be61d6 ("rcuwait: Introduce rcuwait_active()")
+ - 5c21f7b322cb ("rcuwait: Introduce prepare_to and finish_rcuwait")
+ - 80fbaf1c3f29 ("rcuwait: Add @state argument to rcuwait_wait_event()")
+ - 9d9a6ebfea32 ("rcuwait: Let rcuwait_wake_up() return whether or not a task was awoken")
+ - 58d4292bd037 ("rcu: Uninline multi-use function: finish_rcuwait()")
+
+Signed-off-by: Daniel Wagner <wagi@monom.org>
+---
+ include/linux/rcuwait.h | 42 +++++++++++++++++++++++++++--------
+ kernel/exit.c | 7 ++++--
+ kernel/locking/percpu-rwsem.c | 2 +-
+ kernel/rcu/update.c | 8 +++++++
+ 4 files changed, 47 insertions(+), 12 deletions(-)
+
+diff --git a/include/linux/rcuwait.h b/include/linux/rcuwait.h
+index 90bfa3279a01..4fe9ecd56aac 100644
+--- a/include/linux/rcuwait.h
++++ b/include/linux/rcuwait.h
+@@ -3,6 +3,7 @@
+ #define _LINUX_RCUWAIT_H_
+
+ #include <linux/rcupdate.h>
++#include <linux/sched/signal.h>
+
+ /*
+ * rcuwait provides a way of blocking and waking up a single
+@@ -18,7 +19,7 @@
+ * awoken.
+ */
+ struct rcuwait {
+- struct task_struct *task;
++ struct task_struct __rcu *task;
+ };
+
+ #define __RCUWAIT_INITIALIZER(name) \
+@@ -29,14 +30,33 @@ static inline void rcuwait_init(struct rcuwait *w)
+ w->task = NULL;
+ }
+
+-extern void rcuwait_wake_up(struct rcuwait *w);
++extern int rcuwait_wake_up(struct rcuwait *w);
++
++/*
++ * Note: this provides no serialization and, just as with waitqueues,
++ * requires care to estimate as to whether or not the wait is active.
++ */
++static inline int rcuwait_active(struct rcuwait *w)
++{
++ return !!rcu_access_pointer(w->task);
++}
+
+ /*
+ * The caller is responsible for locking around rcuwait_wait_event(),
+- * such that writes to @task are properly serialized.
++ * and [prepare_to/finish]_rcuwait() such that writes to @task are
++ * properly serialized.
+ */
+-#define rcuwait_wait_event(w, condition) \
++
++static inline void prepare_to_rcuwait(struct rcuwait *w)
++{
++ rcu_assign_pointer(w->task, current);
++}
++
++extern void finish_rcuwait(struct rcuwait *w);
++
++#define rcuwait_wait_event(w, condition, state) \
+ ({ \
++ int __ret = 0; \
+ /* \
+ * Complain if we are called after do_exit()/exit_notify(), \
+ * as we cannot rely on the rcu critical region for the \
+@@ -44,21 +64,25 @@ extern void rcuwait_wake_up(struct rcuwait *w);
+ */ \
+ WARN_ON(current->exit_state); \
+ \
+- rcu_assign_pointer((w)->task, current); \
++ prepare_to_rcuwait(w); \
+ for (;;) { \
+ /* \
+ * Implicit barrier (A) pairs with (B) in \
+ * rcuwait_wake_up(). \
+ */ \
+- set_current_state(TASK_UNINTERRUPTIBLE); \
++ set_current_state(state); \
+ if (condition) \
+ break; \
+ \
++ if (signal_pending_state(state, current)) { \
++ __ret = -EINTR; \
++ break; \
++ } \
++ \
+ schedule(); \
+ } \
+- \
+- WRITE_ONCE((w)->task, NULL); \
+- __set_current_state(TASK_RUNNING); \
++ finish_rcuwait(w); \
++ __ret; \
+ })
+
+ #endif /* _LINUX_RCUWAIT_H_ */
+diff --git a/kernel/exit.c b/kernel/exit.c
+index 2a414fc71b87..cf68896a94fa 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -291,8 +291,9 @@ struct task_struct *task_rcu_dereference(struct task_struct **ptask)
+ return task;
+ }
+
+-void rcuwait_wake_up(struct rcuwait *w)
++int rcuwait_wake_up(struct rcuwait *w)
+ {
++ int ret = 0;
+ struct task_struct *task;
+
+ rcu_read_lock();
+@@ -316,8 +317,10 @@ void rcuwait_wake_up(struct rcuwait *w)
+ */
+ task = rcu_dereference(w->task);
+ if (task)
+- wake_up_process(task);
++ ret = wake_up_process(task);
+ rcu_read_unlock();
++
++ return ret;
+ }
+
+ /*
+diff --git a/kernel/locking/percpu-rwsem.c b/kernel/locking/percpu-rwsem.c
+index 883cf1b92d90..41787e80dbde 100644
+--- a/kernel/locking/percpu-rwsem.c
++++ b/kernel/locking/percpu-rwsem.c
+@@ -159,7 +159,7 @@ void percpu_down_write(struct percpu_rw_semaphore *sem)
+ */
+
+ /* Wait for all now active readers to complete. */
+- rcuwait_wait_event(&sem->writer, readers_active_check(sem));
++ rcuwait_wait_event(&sem->writer, readers_active_check(sem), TASK_UNINTERRUPTIBLE);
+ }
+ EXPORT_SYMBOL_GPL(percpu_down_write);
+
+diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c
+index ed75addd3ccd..4b2ce6bb94a4 100644
+--- a/kernel/rcu/update.c
++++ b/kernel/rcu/update.c
+@@ -53,6 +53,7 @@
+ #include <linux/rcupdate_wait.h>
+ #include <linux/sched/isolation.h>
+ #include <linux/kprobes.h>
++#include <linux/rcuwait.h>
+
+ #define CREATE_TRACE_POINTS
+
+@@ -375,6 +376,13 @@ void __wait_rcu_gp(bool checktiny, int n, call_rcu_func_t *crcu_array,
+ }
+ EXPORT_SYMBOL_GPL(__wait_rcu_gp);
+
++void finish_rcuwait(struct rcuwait *w)
++{
++ rcu_assign_pointer(w->task, NULL);
++ __set_current_state(TASK_RUNNING);
++}
++EXPORT_SYMBOL_GPL(finish_rcuwait);
++
+ #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
+ void init_rcu_head(struct rcu_head *head)
+ {