linux/kernel/irq_work.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra
   4 *
   5 * Provides a framework for enqueueing and running callbacks from hardirq
   6 * context. The enqueueing is NMI-safe.
   7 */
   8
   9#include <linux/bug.h>
  10#include <linux/kernel.h>
  11#include <linux/export.h>
  12#include <linux/irq_work.h>
  13#include <linux/percpu.h>
  14#include <linux/hardirq.h>
  15#include <linux/irqflags.h>
  16#include <linux/sched.h>
  17#include <linux/tick.h>
  18#include <linux/cpu.h>
  19#include <linux/notifier.h>
  20#include <linux/smp.h>
  21#include <linux/smpboot.h>
  22#include <asm/processor.h>
  23#include <linux/kasan.h>
  24
  25static DEFINE_PER_CPU(struct llist_head, raised_list);
  26static DEFINE_PER_CPU(struct llist_head, lazy_list);
  27static DEFINE_PER_CPU(struct task_struct *, irq_workd);
  28
  29static void wake_irq_workd(void)
  30{
  31        struct task_struct *tsk = __this_cpu_read(irq_workd);
  32
  33        if (!llist_empty(this_cpu_ptr(&lazy_list)) && tsk)
  34                wake_up_process(tsk);
  35}
  36
  37#ifdef CONFIG_SMP
  38static void irq_work_wake(struct irq_work *entry)
  39{
  40        wake_irq_workd();
  41}
  42
  43static DEFINE_PER_CPU(struct irq_work, irq_work_wakeup) =
  44        IRQ_WORK_INIT_HARD(irq_work_wake);
  45#endif
  46
  47static int irq_workd_should_run(unsigned int cpu)
  48{
  49        return !llist_empty(this_cpu_ptr(&lazy_list));
  50}
  51
  52/*
  53 * Claim the entry so that no one else will poke at it.
  54 */
  55static bool irq_work_claim(struct irq_work *work)
  56{
  57        int oflags;
  58
  59        oflags = atomic_fetch_or(IRQ_WORK_CLAIMED | CSD_TYPE_IRQ_WORK, &work->node.a_flags);
  60        /*
  61         * If the work is already pending, no need to raise the IPI.
  62         * The pairing smp_mb() in irq_work_single() makes sure
  63         * everything we did before is visible.
  64         */
  65        if (oflags & IRQ_WORK_PENDING)
  66                return false;
  67        return true;
  68}
  69
  70void __weak arch_irq_work_raise(void)
  71{
  72        /*
  73         * Lame architectures will get the timer tick callback
  74         */
  75}
  76
  77/* Enqueue on current CPU, work must already be claimed and preempt disabled */
  78static void __irq_work_queue_local(struct irq_work *work)
  79{
  80        struct llist_head *list;
  81        bool rt_lazy_work = false;
  82        bool lazy_work = false;
  83        int work_flags;
  84
  85        work_flags = atomic_read(&work->node.a_flags);
  86        if (work_flags & IRQ_WORK_LAZY)
  87                lazy_work = true;
  88        else if (IS_ENABLED(CONFIG_PREEMPT_RT) &&
  89                 !(work_flags & IRQ_WORK_HARD_IRQ))
  90                rt_lazy_work = true;
  91
  92        if (lazy_work || rt_lazy_work)
  93                list = this_cpu_ptr(&lazy_list);
  94        else
  95                list = this_cpu_ptr(&raised_list);
  96
  97        if (!llist_add(&work->node.llist, list))
  98                return;
  99
 100        /* If the work is "lazy", handle it from next tick if any */
 101        if (!lazy_work || tick_nohz_tick_stopped())
 102                arch_irq_work_raise();
 103}
 104
 105/* Enqueue the irq work @work on the current CPU */
 106bool irq_work_queue(struct irq_work *work)
 107{
 108        /* Only queue if not already pending */
 109        if (!irq_work_claim(work))
 110                return false;
 111
 112        /* Queue the entry and raise the IPI if needed. */
 113        preempt_disable();
 114        __irq_work_queue_local(work);
 115        preempt_enable();
 116
 117        return true;
 118}
 119EXPORT_SYMBOL_GPL(irq_work_queue);
 120
 121/*
 122 * Enqueue the irq_work @work on @cpu unless it's already pending
 123 * somewhere.
 124 *
 125 * Can be re-enqueued while the callback is still in progress.
 126 */
 127bool irq_work_queue_on(struct irq_work *work, int cpu)
 128{
 129#ifndef CONFIG_SMP
 130        return irq_work_queue(work);
 131
 132#else /* CONFIG_SMP: */
 133        /* All work should have been flushed before going offline */
 134        WARN_ON_ONCE(cpu_is_offline(cpu));
 135
 136        /* Only queue if not already pending */
 137        if (!irq_work_claim(work))
 138                return false;
 139
 140        kasan_record_aux_stack(work);
 141
 142        preempt_disable();
 143        if (cpu != smp_processor_id()) {
 144                /* Arch remote IPI send/receive backend aren't NMI safe */
 145                WARN_ON_ONCE(in_nmi());
 146
 147                /*
 148                 * On PREEMPT_RT the items which are not marked as
 149                 * IRQ_WORK_HARD_IRQ are added to the lazy list and a HARD work
 150                 * item is used on the remote CPU to wake the thread.
 151                 */
 152                if (IS_ENABLED(CONFIG_PREEMPT_RT) &&
 153                    !(atomic_read(&work->node.a_flags) & IRQ_WORK_HARD_IRQ)) {
 154
 155                        if (!llist_add(&work->node.llist, &per_cpu(lazy_list, cpu)))
 156                                goto out;
 157
 158                        work = &per_cpu(irq_work_wakeup, cpu);
 159                        if (!irq_work_claim(work))
 160                                goto out;
 161                }
 162
 163                __smp_call_single_queue(cpu, &work->node.llist);
 164        } else {
 165                __irq_work_queue_local(work);
 166        }
 167out:
 168        preempt_enable();
 169
 170        return true;
 171#endif /* CONFIG_SMP */
 172}
 173
 174bool irq_work_needs_cpu(void)
 175{
 176        struct llist_head *raised, *lazy;
 177
 178        raised = this_cpu_ptr(&raised_list);
 179        lazy = this_cpu_ptr(&lazy_list);
 180
 181        if (llist_empty(raised) || arch_irq_work_has_interrupt())
 182                if (llist_empty(lazy))
 183                        return false;
 184
 185        /* All work should have been flushed before going offline */
 186        WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
 187
 188        return true;
 189}
 190
 191void irq_work_single(void *arg)
 192{
 193        struct irq_work *work = arg;
 194        int flags;
 195
 196        /*
 197         * Clear the PENDING bit, after this point the @work can be re-used.
 198         * The PENDING bit acts as a lock, and we own it, so we can clear it
 199         * without atomic ops.
 200         */
 201        flags = atomic_read(&work->node.a_flags);
 202        flags &= ~IRQ_WORK_PENDING;
 203        atomic_set(&work->node.a_flags, flags);
 204
 205        /*
 206         * See irq_work_claim().
 207         */
 208        smp_mb();
 209
 210        lockdep_irq_work_enter(flags);
 211        work->func(work);
 212        lockdep_irq_work_exit(flags);
 213
 214        /*
 215         * Clear the BUSY bit, if set, and return to the free state if no-one
 216         * else claimed it meanwhile.
 217         */
 218        (void)atomic_cmpxchg(&work->node.a_flags, flags, flags & ~IRQ_WORK_BUSY);
 219
 220        if ((IS_ENABLED(CONFIG_PREEMPT_RT) && !irq_work_is_hard(work)) ||
 221            !arch_irq_work_has_interrupt())
 222                rcuwait_wake_up(&work->irqwait);
 223}
 224
 225static void irq_work_run_list(struct llist_head *list)
 226{
 227        struct irq_work *work, *tmp;
 228        struct llist_node *llnode;
 229
 230        /*
 231         * On PREEMPT_RT IRQ-work which is not marked as HARD will be processed
 232         * in a per-CPU thread in preemptible context. Only the items which are
 233         * marked as IRQ_WORK_HARD_IRQ will be processed in hardirq context.
 234         */
 235        BUG_ON(!irqs_disabled() && !IS_ENABLED(CONFIG_PREEMPT_RT));
 236
 237        if (llist_empty(list))
 238                return;
 239
 240        llnode = llist_del_all(list);
 241        llist_for_each_entry_safe(work, tmp, llnode, node.llist)
 242                irq_work_single(work);
 243}
 244
 245/*
 246 * hotplug calls this through:
 247 *  hotplug_cfd() -> flush_smp_call_function_queue()
 248 */
 249void irq_work_run(void)
 250{
 251        irq_work_run_list(this_cpu_ptr(&raised_list));
 252        if (!IS_ENABLED(CONFIG_PREEMPT_RT))
 253                irq_work_run_list(this_cpu_ptr(&lazy_list));
 254        else
 255                wake_irq_workd();
 256}
 257EXPORT_SYMBOL_GPL(irq_work_run);
 258
 259void irq_work_tick(void)
 260{
 261        struct llist_head *raised = this_cpu_ptr(&raised_list);
 262
 263        if (!llist_empty(raised) && !arch_irq_work_has_interrupt())
 264                irq_work_run_list(raised);
 265
 266        if (!IS_ENABLED(CONFIG_PREEMPT_RT))
 267                irq_work_run_list(this_cpu_ptr(&lazy_list));
 268        else
 269                wake_irq_workd();
 270}
 271
 272/*
 273 * Synchronize against the irq_work @entry, ensures the entry is not
 274 * currently in use.
 275 */
 276void irq_work_sync(struct irq_work *work)
 277{
 278        lockdep_assert_irqs_enabled();
 279        might_sleep();
 280
 281        if ((IS_ENABLED(CONFIG_PREEMPT_RT) && !irq_work_is_hard(work)) ||
 282            !arch_irq_work_has_interrupt()) {
 283                rcuwait_wait_event(&work->irqwait, !irq_work_is_busy(work),
 284                                   TASK_UNINTERRUPTIBLE);
 285                return;
 286        }
 287
 288        while (irq_work_is_busy(work))
 289                cpu_relax();
 290}
 291EXPORT_SYMBOL_GPL(irq_work_sync);
 292
 293static void run_irq_workd(unsigned int cpu)
 294{
 295        irq_work_run_list(this_cpu_ptr(&lazy_list));
 296}
 297
 298static void irq_workd_setup(unsigned int cpu)
 299{
 300        sched_set_fifo_low(current);
 301}
 302
 303static struct smp_hotplug_thread irqwork_threads = {
 304        .store                  = &irq_workd,
 305        .setup                  = irq_workd_setup,
 306        .thread_should_run      = irq_workd_should_run,
 307        .thread_fn              = run_irq_workd,
 308        .thread_comm            = "irq_work/%u",
 309};
 310
 311static __init int irq_work_init_threads(void)
 312{
 313        if (IS_ENABLED(CONFIG_PREEMPT_RT))
 314                BUG_ON(smpboot_register_percpu_thread(&irqwork_threads));
 315        return 0;
 316}
 317early_initcall(irq_work_init_threads);
 318