summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0001-perf-Move-irq_work_queue-where-the-event-is-prepared.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/0001-perf-Move-irq_work_queue-where-the-event-is-prepared.patch')
-rw-r--r--debian/patches-rt/0001-perf-Move-irq_work_queue-where-the-event-is-prepared.patch42
1 files changed, 42 insertions, 0 deletions
diff --git a/debian/patches-rt/0001-perf-Move-irq_work_queue-where-the-event-is-prepared.patch b/debian/patches-rt/0001-perf-Move-irq_work_queue-where-the-event-is-prepared.patch
new file mode 100644
index 000000000..08a2950a4
--- /dev/null
+++ b/debian/patches-rt/0001-perf-Move-irq_work_queue-where-the-event-is-prepared.patch
@@ -0,0 +1,42 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue, 12 Mar 2024 19:01:49 +0100
+Subject: [PATCH 1/4] perf: Move irq_work_queue() where the event is prepared.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.8/older/patches-6.8.2-rt11.tar.xz
+
+Only if perf_event::pending_sigtrap is zero, the irq_work accounted by
+increminging perf_event::nr_pending. The member perf_event::pending_addr
+might be overwritten by a subsequent event if the signal was not yet
+delivered and is expected. The irq_work will not be enqeueued again
+because it has a check to be only enqueued once.
+
+Move irq_work_queue() to where the counter is incremented and
+perf_event::pending_sigtrap is set to make it more obvious that the
+irq_work is scheduled once.
+
+Tested-by: Marco Elver <elver@google.com>
+Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Reported-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Link: https://lore.kernel.org/r/20240312180814.3373778-2-bigeasy@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/events/core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -9595,6 +9595,7 @@ static int __perf_event_overflow(struct
+ if (!event->pending_sigtrap) {
+ event->pending_sigtrap = pending_id;
+ local_inc(&event->ctx->nr_pending);
++ irq_work_queue(&event->pending_irq);
+ } else if (event->attr.exclude_kernel && valid_sample) {
+ /*
+ * Should not be able to return to user space without
+@@ -9614,7 +9615,6 @@ static int __perf_event_overflow(struct
+ event->pending_addr = 0;
+ if (valid_sample && (data->sample_flags & PERF_SAMPLE_ADDR))
+ event->pending_addr = data->addr;
+- irq_work_queue(&event->pending_irq);
+ }
+
+ READ_ONCE(event->overflow_handler)(event, data, regs);