Re: [PATCH v2 11/11] perf/uprobe: Add uretprobe timer
From: Peter Zijlstra <peterz@infradead.org>
Date: 2024-07-11 16:06:55
Also in:
lkml
On Thu, Jul 11, 2024 at 05:55:42PM +0200, Peter Zijlstra wrote:
quoted hunk ↗ jump to hunk
On Thu, Jul 11, 2024 at 05:00:54PM +0200, Peter Zijlstra wrote:quoted
Let me ponder that a little, I *can* make it work, but all 'solutions' I've come up with so far are really rather vile.This is the least horrible solution I could come up with... ------ a/include/linux/uprobes.h +++ b/include/linux/uprobes.h@@ -83,6 +83,7 @@ struct uprobe_task { struct timer_list ri_timer; struct callback_head ri_task_work; + bool ri_work_pending; struct task_struct *task; }; --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c@@ -1797,9 +1797,8 @@ void uprobe_free_utask(struct task_struc t->utask = NULL; } -static void return_instance_task_work(struct callback_head *head) +static void __return_instance_put(struct uprobe_task *utask) { - struct uprobe_task *utask = container_of(head, struct uprobe_task, ri_task_work); struct return_instance *ri; for (ri = utask->return_instances; ri; ri = ri->next) {@@ -1815,9 +1814,43 @@ static void return_instance_task_work(st } } +static void return_instance_task_work(struct callback_head *head) +{ + struct uprobe_task *utask = container_of(head, struct uprobe_task, ri_task_work); + utask->ri_work_pending = false; + __return_instance_put(utask); +} + +static int return_instance_blocked(struct task_struct *p, void *arg) +{ + unsigned int state = READ_ONCE(p->__state); + + if (state == TASK_RUNNING || state == TASK_WAKING) + return 0; + + smp_rmb(); + if (p->on_rq) + return 0; + + /* + * Per __task_needs_rq_locked() we now have: !p->on_cpu and only hold + * p->pi_lock, and can consiter the task fully blocked. + */ + + __return_instance_put(p->utask);
PREEMPT_RT might not like this though, doing the full RI iteration under a raw_spinlock_t... I just can't think of anything saner just now. Oh well, let me go make dinner, perhaps something will come to me.