Messages in this thread Patch in this message |  | | Date | Thu, 21 May 2026 23:39:45 +0900 | | Subject | Re: [PATCH v3] kcov: move kcov_remote_data to task_struct for RT and remove local_lock | | From | Tetsuo Handa <> |
| |
On 2026/05/21 22:06, Alexander Potapenko wrote: > I think a deadlock is possible if a softirq is delivered while a > background task is executing kcov_remote_start():
Indeed. Since kcov_remote_start() is called by
static int vhost_run_work_kthread_list(void *data) { kcov_remote_start_common(worker->kcov_handle); work->fn(work); kcov_remote_stop(); }
and it can be preempted by
static void usb_giveback_urb_bh(struct work_struct *work) { static void __usb_hcd_giveback_urb(struct urb *urb) { kcov_remote_start_usb_softirq((u64)urb->dev->bus->busnum); urb->complete(urb); kcov_remote_stop_softirq(); } }
, we need to use _irq{save,restore} version. Any other concerns?
kernel/kcov.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/kernel/kcov.c b/kernel/kcov.c index 965c11a75b36..70ce99c3205d 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -897,6 +897,7 @@ void kcov_remote_start(u64 handle) void *area; unsigned int size; int sequence; + unsigned long flags; /* Don't use in_task() in order to allow consistent checks in RT kernels. */ if (in_hardirq() || in_nmi()) @@ -918,10 +919,10 @@ void kcov_remote_start(u64 handle) if (WARN_ON(in_serving_softirq() && t->kcov_softirq)) return; - spin_lock(&kcov_remote_lock); + spin_lock_irqsave(&kcov_remote_lock, flags); remote = kcov_remote_find(handle); if (!remote) { - spin_unlock(&kcov_remote_lock); + spin_unlock_irqrestore(&kcov_remote_lock, flags); return; } kcov_debug("handle = %llx, context: %s\n", handle, @@ -949,7 +950,7 @@ void kcov_remote_start(u64 handle) area = this_cpu_ptr(&kcov_percpu_data)->irq_area; } #endif - spin_unlock(&kcov_remote_lock); + spin_unlock_irqrestore(&kcov_remote_lock, flags); /* Can only happen when CONFIG_PREEMPT_RT=y or in_task(). */ if (!area) { @@ -1044,6 +1045,7 @@ void kcov_remote_stop(void) void *area; unsigned int size; int sequence; + unsigned long flags; /* Don't use in_task() in order to allow consistent checks in RT kernels. */ if (in_hardirq() || in_nmi()) @@ -1084,9 +1086,9 @@ void kcov_remote_stop(void) spin_unlock(&kcov->lock); if (IS_ENABLED(CONFIG_PREEMPT_RT) || in_task()) { - spin_lock(&kcov_remote_lock); + spin_lock_irqsave(&kcov_remote_lock, flags); kcov_remote_area_put(area, size); - spin_unlock(&kcov_remote_lock); + spin_unlock_irqrestore(&kcov_remote_lock, flags); } /* Get in kcov_remote_start(). */
|  |