13 #include <linux/export.h>
29 #define CREATE_TRACE_POINTS
51 #ifndef __ARCH_IRQ_STAT
61 "HI",
"TIMER",
"NET_TX",
"NET_RX",
"BLOCK",
"BLOCK_IOPOLL",
62 "TASKLET",
"SCHED",
"HRTIMER",
"RCU"
71 static void wakeup_softirqd(
void)
94 #ifdef CONFIG_TRACE_IRQFLAGS
95 static void __local_bh_disable(
unsigned long ip,
unsigned int cnt)
121 static inline void __local_bh_disable(
unsigned long ip,
unsigned int cnt)
130 __local_bh_disable((
unsigned long)__builtin_return_address(0),
136 static void __local_bh_enable(
unsigned int cnt)
158 static inline void _local_bh_enable_ip(
unsigned long ip)
161 #ifdef CONFIG_TRACE_IRQFLAGS
179 #ifdef CONFIG_TRACE_IRQFLAGS
187 _local_bh_enable_ip((
unsigned long)__builtin_return_address(0));
193 _local_bh_enable_ip(ip);
206 #define MAX_SOFTIRQ_RESTART 10
214 unsigned long old_flags =
current->flags;
226 __local_bh_disable((
unsigned long)__builtin_return_address(0),
241 unsigned int vec_nr = h - softirq_vec;
244 kstat_incr_softirqs_this_cpu(vec_nr);
246 trace_softirq_entry(vec_nr);
248 trace_softirq_exit(vec_nr);
251 "with preempt_count %08x,"
252 " exited with %08x?\n", vec_nr,
267 if (pending && --max_restart)
280 #ifndef __ARCH_HAS_DO_SOFTIRQ
323 static inline void invoke_softirq(
void)
326 #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
332 __local_bh_disable((
unsigned long)__builtin_return_address(0),
353 tick_nohz_irq_exit();
390 trace_softirq_raise(nr);
522 void (*
func)(
unsigned long),
unsigned long data)
536 printk(
"Attempt to kill tasklet from interrupt\n");
563 tasklet_hi_schedule(&ttimer->
tasklet);
571 static void __tasklet_hrtimer_trampoline(
unsigned long data)
593 ttimer->
timer.function = __hrtimer_tasklet_trampoline;
595 (
unsigned long)ttimer);
596 ttimer->function =
function;
618 #ifdef CONFIG_USE_GENERIC_SMP_HELPERS
619 static void remote_softirq_receive(
void *data)
628 __local_trigger(cp, softirq);
635 cp->
func = remote_softirq_receive;
640 __smp_call_function_single(cpu, cp, 0);
646 static int __try_remote_softirq(
struct call_single_data *cp,
int cpu,
int softirq)
666 if (cpu == this_cpu || __try_remote_softirq(cp, cpu, softirq))
667 __local_trigger(cp, softirq);
693 unsigned long action,
void *hcpu)
700 int cpu = (
unsigned long) hcpu;
708 if (list_empty(head))
712 list_splice_init(head, local_head);
722 .notifier_call = remote_softirq_cpu_notify,
732 per_cpu(tasklet_vec, cpu).tail =
733 &
per_cpu(tasklet_vec, cpu).head;
734 per_cpu(tasklet_hi_vec, cpu).tail =
735 &
per_cpu(tasklet_hi_vec, cpu).head;
737 INIT_LIST_HEAD(&
per_cpu(softirq_work_list[i], cpu));
746 static int ksoftirqd_should_run(
unsigned int cpu)
751 static void run_ksoftirqd(
unsigned int cpu)
764 #ifdef CONFIG_HOTPLUG_CPU
785 for (i = &
per_cpu(tasklet_vec, cpu).head; *
i; i = &(*i)->
next) {
797 static void takeover_tasklets(
unsigned int cpu)
811 if (&
per_cpu(tasklet_hi_vec, cpu).head !=
per_cpu(tasklet_hi_vec, cpu).tail) {
815 per_cpu(tasklet_hi_vec, cpu).tail = &
per_cpu(tasklet_hi_vec, cpu).head;
824 unsigned long action,
828 #ifdef CONFIG_HOTPLUG_CPU
831 takeover_tasklets((
unsigned long)hcpu);
839 .notifier_call = cpu_callback
844 .thread_should_run = ksoftirqd_should_run,
845 .thread_fn = run_ksoftirqd,
846 .thread_comm =
"ksoftirqd/%u",
849 static __init int spawn_ksoftirqd(
void)
851 register_cpu_notifier(&cpu_nfb);
869 #ifdef CONFIG_GENERIC_HARDIRQS