blob: 3e88612fc87e382b65663a3ffd6f13d0c27f2fb7 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/kernel/softirq.c
3 *
4 * Copyright (C) 1992 Linus Torvalds
5 *
Pavel Machekb10db7f2008-01-30 13:30:00 +01006 * Distribute under GPLv2.
7 *
8 * Rewritten. Old one was good in 2.2, but in 2.3 it was immoral. --ANK (990903)
David S. Miller54514a72008-09-23 22:15:57 -07009 *
10 * Remote softirq infrastructure is by Jens Axboe.
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 */
12
Paul Gortmaker9984de12011-05-23 14:51:41 -040013#include <linux/export.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <linux/kernel_stat.h>
15#include <linux/interrupt.h>
16#include <linux/init.h>
17#include <linux/mm.h>
18#include <linux/notifier.h>
19#include <linux/percpu.h>
20#include <linux/cpu.h>
Rafael J. Wysocki83144182007-07-17 04:03:35 -070021#include <linux/freezer.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/kthread.h>
23#include <linux/rcupdate.h>
Steven Rostedt7e49fcc2009-01-22 19:01:40 -050024#include <linux/ftrace.h>
Andrew Morton78eef012006-03-22 00:08:16 -080025#include <linux/smp.h>
Thomas Gleixner3e339b52012-07-16 10:42:37 +000026#include <linux/smpboot.h>
Thomas Gleixner79bf2bb2007-02-16 01:28:03 -080027#include <linux/tick.h>
Heiko Carstensa0e39ed2009-04-29 13:51:39 +020028
29#define CREATE_TRACE_POINTS
Steven Rostedtad8d75f2009-04-14 19:39:12 -040030#include <trace/events/irq.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
32#include <asm/irq.h>
33/*
34 - No shared variables, all the data are CPU local.
35 - If a softirq needs serialization, let it serialize itself
36 by its own spinlocks.
37 - Even if softirq is serialized, only local cpu is marked for
38 execution. Hence, we get something sort of weak cpu binding.
39 Though it is still not clear, will it result in better locality
40 or will not.
41
42 Examples:
43 - NET RX softirq. It is multithreaded and does not require
44 any global serialization.
45 - NET TX softirq. It kicks software netdevice queues, hence
46 it is logically serialized per device, but this serialization
47 is invisible to common code.
48 - Tasklets: serialized wrt itself.
49 */
50
51#ifndef __ARCH_IRQ_STAT
52irq_cpustat_t irq_stat[NR_CPUS] ____cacheline_aligned;
53EXPORT_SYMBOL(irq_stat);
54#endif
55
Alexey Dobriyan978b0112008-09-06 20:04:36 +020056static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
Venkatesh Pallipadi4dd53d82010-12-21 17:09:00 -080058DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Jason Baron5d592b42009-03-12 14:33:36 -040060char *softirq_to_name[NR_SOFTIRQS] = {
Li Zefan5dd4de52009-09-17 17:38:32 +080061 "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL",
Shaohua Li09223372011-06-14 13:26:25 +080062 "TASKLET", "SCHED", "HRTIMER", "RCU"
Jason Baron5d592b42009-03-12 14:33:36 -040063};
64
Linus Torvalds1da177e2005-04-16 15:20:36 -070065/*
66 * we cannot loop indefinitely here to avoid userspace starvation,
67 * but we also don't want to introduce a worst case 1/HZ latency
68 * to the pending events, so lets the scheduler to balance
69 * the softirq load for us.
70 */
Thomas Gleixner676cb022009-07-20 23:33:49 +020071static void wakeup_softirqd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070072{
73 /* Interrupts are disabled: no need to stop preemption */
Christoph Lameter909ea962010-12-08 16:22:55 +010074 struct task_struct *tsk = __this_cpu_read(ksoftirqd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76 if (tsk && tsk->state != TASK_RUNNING)
77 wake_up_process(tsk);
78}
79
80/*
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -070081 * preempt_count and SOFTIRQ_OFFSET usage:
82 * - preempt_count is changed by SOFTIRQ_OFFSET on entering or leaving
83 * softirq processing.
84 * - preempt_count is changed by SOFTIRQ_DISABLE_OFFSET (= 2 * SOFTIRQ_OFFSET)
85 * on local_bh_disable or local_bh_enable.
86 * This lets us distinguish between whether we are currently processing
87 * softirq and whether we just have bh disabled.
88 */
89
90/*
Ingo Molnarde30a2b2006-07-03 00:24:42 -070091 * This one is for softirq.c-internal use,
92 * where hardirqs are disabled legitimately:
93 */
Tim Chen3c829c32006-07-30 03:04:02 -070094#ifdef CONFIG_TRACE_IRQFLAGS
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -070095static void __local_bh_disable(unsigned long ip, unsigned int cnt)
Ingo Molnarde30a2b2006-07-03 00:24:42 -070096{
97 unsigned long flags;
98
99 WARN_ON_ONCE(in_irq());
100
101 raw_local_irq_save(flags);
Steven Rostedt7e49fcc2009-01-22 19:01:40 -0500102 /*
Peter Zijlstrabdb43802013-09-10 12:15:23 +0200103 * The preempt tracer hooks into preempt_count_add and will break
Steven Rostedt7e49fcc2009-01-22 19:01:40 -0500104 * lockdep because it calls back into lockdep after SOFTIRQ_OFFSET
105 * is set and before current->softirq_enabled is cleared.
106 * We must manually increment preempt_count here and manually
107 * call the trace_preempt_off later.
108 */
Peter Zijlstrabdb43802013-09-10 12:15:23 +0200109 __preempt_count_add(cnt);
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700110 /*
111 * Were softirqs turned off above:
112 */
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700113 if (softirq_count() == cnt)
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700114 trace_softirqs_off(ip);
115 raw_local_irq_restore(flags);
Steven Rostedt7e49fcc2009-01-22 19:01:40 -0500116
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700117 if (preempt_count() == cnt)
Steven Rostedt7e49fcc2009-01-22 19:01:40 -0500118 trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700119}
Tim Chen3c829c32006-07-30 03:04:02 -0700120#else /* !CONFIG_TRACE_IRQFLAGS */
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700121static inline void __local_bh_disable(unsigned long ip, unsigned int cnt)
Tim Chen3c829c32006-07-30 03:04:02 -0700122{
Peter Zijlstrabdb43802013-09-10 12:15:23 +0200123 preempt_count_add(cnt);
Tim Chen3c829c32006-07-30 03:04:02 -0700124 barrier();
125}
126#endif /* CONFIG_TRACE_IRQFLAGS */
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700127
128void local_bh_disable(void)
129{
Davidlohr Buesod2e08472013-04-30 11:46:09 -0700130 __local_bh_disable(_RET_IP_, SOFTIRQ_DISABLE_OFFSET);
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700131}
132
133EXPORT_SYMBOL(local_bh_disable);
134
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700135static void __local_bh_enable(unsigned int cnt)
136{
137 WARN_ON_ONCE(in_irq());
138 WARN_ON_ONCE(!irqs_disabled());
139
140 if (softirq_count() == cnt)
Davidlohr Buesod2e08472013-04-30 11:46:09 -0700141 trace_softirqs_on(_RET_IP_);
Peter Zijlstrabdb43802013-09-10 12:15:23 +0200142 preempt_count_sub(cnt);
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700143}
144
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700145/*
146 * Special-case - softirqs can safely be enabled in
147 * cond_resched_softirq(), or by __do_softirq(),
148 * without processing still-pending softirqs:
149 */
150void _local_bh_enable(void)
151{
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700152 __local_bh_enable(SOFTIRQ_DISABLE_OFFSET);
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700153}
154
155EXPORT_SYMBOL(_local_bh_enable);
156
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200157static inline void _local_bh_enable_ip(unsigned long ip)
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700158{
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200159 WARN_ON_ONCE(in_irq() || irqs_disabled());
Tim Chen3c829c32006-07-30 03:04:02 -0700160#ifdef CONFIG_TRACE_IRQFLAGS
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200161 local_irq_disable();
Tim Chen3c829c32006-07-30 03:04:02 -0700162#endif
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700163 /*
164 * Are softirqs going to be turned on now:
165 */
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700166 if (softirq_count() == SOFTIRQ_DISABLE_OFFSET)
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700167 trace_softirqs_on(ip);
168 /*
169 * Keep preemption disabled until we are done with
170 * softirq processing:
171 */
Peter Zijlstrabdb43802013-09-10 12:15:23 +0200172 preempt_count_sub(SOFTIRQ_DISABLE_OFFSET - 1);
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700173
174 if (unlikely(!in_interrupt() && local_softirq_pending()))
175 do_softirq();
176
Peter Zijlstrabdb43802013-09-10 12:15:23 +0200177 preempt_count_dec();
Tim Chen3c829c32006-07-30 03:04:02 -0700178#ifdef CONFIG_TRACE_IRQFLAGS
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200179 local_irq_enable();
Tim Chen3c829c32006-07-30 03:04:02 -0700180#endif
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700181 preempt_check_resched();
182}
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200183
184void local_bh_enable(void)
185{
Davidlohr Buesod2e08472013-04-30 11:46:09 -0700186 _local_bh_enable_ip(_RET_IP_);
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200187}
188EXPORT_SYMBOL(local_bh_enable);
189
190void local_bh_enable_ip(unsigned long ip)
191{
192 _local_bh_enable_ip(ip);
193}
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700194EXPORT_SYMBOL(local_bh_enable_ip);
195
196/*
Ben Greear34376a52013-06-06 14:29:49 -0700197 * We restart softirq processing for at most MAX_SOFTIRQ_RESTART times,
198 * but break the loop if need_resched() is set or after 2 ms.
199 * The MAX_SOFTIRQ_TIME provides a nice upper bound in most cases, but in
200 * certain cases, such as stop_machine(), jiffies may cease to
201 * increment and so we need the MAX_SOFTIRQ_RESTART limit as
202 * well to make sure we eventually return from this method.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 *
Eric Dumazetc10d7362013-01-10 15:26:34 -0800204 * These limits have been established via experimentation.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 * The two things to balance is latency against fairness -
206 * we want to handle softirqs as soon as possible, but they
207 * should not be able to lock up the box.
208 */
Eric Dumazetc10d7362013-01-10 15:26:34 -0800209#define MAX_SOFTIRQ_TIME msecs_to_jiffies(2)
Ben Greear34376a52013-06-06 14:29:49 -0700210#define MAX_SOFTIRQ_RESTART 10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211
212asmlinkage void __do_softirq(void)
213{
214 struct softirq_action *h;
215 __u32 pending;
Eric Dumazetc10d7362013-01-10 15:26:34 -0800216 unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 int cpu;
Mel Gorman907aed42012-07-31 16:44:07 -0700218 unsigned long old_flags = current->flags;
Ben Greear34376a52013-06-06 14:29:49 -0700219 int max_restart = MAX_SOFTIRQ_RESTART;
Mel Gorman907aed42012-07-31 16:44:07 -0700220
221 /*
222 * Mask out PF_MEMALLOC s current task context is borrowed for the
223 * softirq. A softirq handled such as network RX might set PF_MEMALLOC
224 * again if the socket is related to swap
225 */
226 current->flags &= ~PF_MEMALLOC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
228 pending = local_softirq_pending();
Frederic Weisbecker6a616712012-12-16 20:00:34 +0100229 account_irq_enter_time(current);
Paul Mackerras829035fd2006-07-03 00:25:40 -0700230
Davidlohr Buesod2e08472013-04-30 11:46:09 -0700231 __local_bh_disable(_RET_IP_, SOFTIRQ_OFFSET);
Ingo Molnard820ac42009-03-13 01:30:40 +0100232 lockdep_softirq_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 cpu = smp_processor_id();
235restart:
236 /* Reset the pending bitmask before enabling irqs */
Andi Kleen3f744782005-09-12 18:49:24 +0200237 set_softirq_pending(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
Andrew Mortonc70f5d62005-07-30 10:22:49 -0700239 local_irq_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240
241 h = softirq_vec;
242
243 do {
244 if (pending & 1) {
Thomas Gleixnerf4bc6bb2010-10-19 15:00:13 +0200245 unsigned int vec_nr = h - softirq_vec;
Thomas Gleixner8e85b4b2008-10-02 10:50:53 +0200246 int prev_count = preempt_count();
247
Thomas Gleixnerf4bc6bb2010-10-19 15:00:13 +0200248 kstat_incr_softirqs_this_cpu(vec_nr);
249
250 trace_softirq_entry(vec_nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 h->action(h);
Thomas Gleixnerf4bc6bb2010-10-19 15:00:13 +0200252 trace_softirq_exit(vec_nr);
Thomas Gleixner8e85b4b2008-10-02 10:50:53 +0200253 if (unlikely(prev_count != preempt_count())) {
Thomas Gleixnerf4bc6bb2010-10-19 15:00:13 +0200254 printk(KERN_ERR "huh, entered softirq %u %s %p"
Thomas Gleixner8e85b4b2008-10-02 10:50:53 +0200255 "with preempt_count %08x,"
Thomas Gleixnerf4bc6bb2010-10-19 15:00:13 +0200256 " exited with %08x?\n", vec_nr,
257 softirq_to_name[vec_nr], h->action,
258 prev_count, preempt_count());
Peter Zijlstra4a2b4b22013-08-14 14:55:24 +0200259 preempt_count_set(prev_count);
Thomas Gleixner8e85b4b2008-10-02 10:50:53 +0200260 }
261
Paul E. McKenneyd6714c22009-08-22 13:56:46 -0700262 rcu_bh_qs(cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 }
264 h++;
265 pending >>= 1;
266 } while (pending);
267
Andrew Mortonc70f5d62005-07-30 10:22:49 -0700268 local_irq_disable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
270 pending = local_softirq_pending();
Eric Dumazetc10d7362013-01-10 15:26:34 -0800271 if (pending) {
Ben Greear34376a52013-06-06 14:29:49 -0700272 if (time_before(jiffies, end) && !need_resched() &&
273 --max_restart)
Eric Dumazetc10d7362013-01-10 15:26:34 -0800274 goto restart;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 wakeup_softirqd();
Eric Dumazetc10d7362013-01-10 15:26:34 -0800277 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Ingo Molnard820ac42009-03-13 01:30:40 +0100279 lockdep_softirq_exit();
Paul Mackerras829035fd2006-07-03 00:25:40 -0700280
Frederic Weisbecker6a616712012-12-16 20:00:34 +0100281 account_irq_exit_time(current);
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700282 __local_bh_enable(SOFTIRQ_OFFSET);
Mel Gorman907aed42012-07-31 16:44:07 -0700283 tsk_restore_flags(current, old_flags, PF_MEMALLOC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284}
285
286#ifndef __ARCH_HAS_DO_SOFTIRQ
287
288asmlinkage void do_softirq(void)
289{
290 __u32 pending;
291 unsigned long flags;
292
293 if (in_interrupt())
294 return;
295
296 local_irq_save(flags);
297
298 pending = local_softirq_pending();
299
300 if (pending)
301 __do_softirq();
302
303 local_irq_restore(flags);
304}
305
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306#endif
307
Ingo Molnardde4b2b2007-02-16 01:27:45 -0800308/*
309 * Enter an interrupt context.
310 */
311void irq_enter(void)
312{
Venki Pallipadi6378ddb2008-01-30 13:30:04 +0100313 int cpu = smp_processor_id();
Thomas Gleixner719254f2008-10-17 09:59:47 +0200314
Paul E. McKenney64db4cf2008-12-18 21:55:32 +0100315 rcu_irq_enter();
Frederic Weisbecker0a8a2e72012-01-24 18:59:44 +0100316 if (is_idle_task(current) && !in_interrupt()) {
Venkatesh Pallipadid267f872010-10-04 17:03:23 -0700317 /*
318 * Prevent raise_softirq from needlessly waking up ksoftirqd
319 * here, as softirq will be serviced on return from interrupt.
320 */
321 local_bh_disable();
Thomas Gleixner719254f2008-10-17 09:59:47 +0200322 tick_check_idle(cpu);
Venkatesh Pallipadid267f872010-10-04 17:03:23 -0700323 _local_bh_enable();
324 }
325
326 __irq_enter();
Ingo Molnardde4b2b2007-02-16 01:27:45 -0800327}
328
Heiko Carstensb2a00172012-03-05 15:07:25 -0800329static inline void invoke_softirq(void)
330{
Thomas Gleixnerfacd8b82013-02-21 18:17:42 +0100331 if (!force_irqthreads)
Thomas Gleixner8d32a302011-02-23 23:52:23 +0000332 __do_softirq();
Thomas Gleixnerfacd8b82013-02-21 18:17:42 +0100333 else
Thomas Gleixner8d32a302011-02-23 23:52:23 +0000334 wakeup_softirqd();
335}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
Frederic Weisbecker67826ea2013-04-20 17:43:13 +0200337static inline void tick_irq_exit(void)
338{
339#ifdef CONFIG_NO_HZ_COMMON
340 int cpu = smp_processor_id();
341
342 /* Make sure that timer wheel updates are propagated */
343 if ((idle_cpu(cpu) && !need_resched()) || tick_nohz_full_cpu(cpu)) {
344 if (!in_interrupt())
345 tick_nohz_irq_exit();
346 }
347#endif
348}
349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350/*
351 * Exit an interrupt context. Process softirqs if needed and possible:
352 */
353void irq_exit(void)
354{
Thomas Gleixner74eed012013-02-20 22:00:48 +0100355#ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
Frederic Weisbecker4cd5d112013-02-28 20:00:43 +0100356 local_irq_disable();
Thomas Gleixner74eed012013-02-20 22:00:48 +0100357#else
358 WARN_ON_ONCE(!irqs_disabled());
359#endif
360
Frederic Weisbecker6a616712012-12-16 20:00:34 +0100361 account_irq_exit_time(current);
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700362 trace_hardirq_exit();
Peter Zijlstrabdb43802013-09-10 12:15:23 +0200363 preempt_count_sub(HARDIRQ_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 if (!in_interrupt() && local_softirq_pending())
365 invoke_softirq();
Thomas Gleixner79bf2bb2007-02-16 01:28:03 -0800366
Frederic Weisbecker67826ea2013-04-20 17:43:13 +0200367 tick_irq_exit();
Frederic Weisbecker416eb332011-10-07 16:31:02 -0700368 rcu_irq_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369}
370
371/*
372 * This function must run with irqs disabled!
373 */
Harvey Harrison7ad5b3a2008-02-08 04:19:53 -0800374inline void raise_softirq_irqoff(unsigned int nr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375{
376 __raise_softirq_irqoff(nr);
377
378 /*
379 * If we're in an interrupt or softirq, we're done
380 * (this also catches softirq-disabled code). We will
381 * actually run the softirq once we return from
382 * the irq or softirq.
383 *
384 * Otherwise we wake up ksoftirqd to make sure we
385 * schedule the softirq soon.
386 */
387 if (!in_interrupt())
388 wakeup_softirqd();
389}
390
Harvey Harrison7ad5b3a2008-02-08 04:19:53 -0800391void raise_softirq(unsigned int nr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392{
393 unsigned long flags;
394
395 local_irq_save(flags);
396 raise_softirq_irqoff(nr);
397 local_irq_restore(flags);
398}
399
Steven Rostedtf0696862012-01-25 20:18:55 -0500400void __raise_softirq_irqoff(unsigned int nr)
401{
402 trace_softirq_raise(nr);
403 or_softirq_pending(1UL << nr);
404}
405
Carlos R. Mafra962cf362008-05-15 11:15:37 -0300406void open_softirq(int nr, void (*action)(struct softirq_action *))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 softirq_vec[nr].action = action;
409}
410
Peter Zijlstra9ba5f002009-07-22 14:18:35 +0200411/*
412 * Tasklets
413 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414struct tasklet_head
415{
Olof Johansson48f20a92008-03-04 15:23:25 -0800416 struct tasklet_struct *head;
417 struct tasklet_struct **tail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418};
419
Vegard Nossum4620b492008-06-12 23:21:53 +0200420static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);
421static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
Harvey Harrison7ad5b3a2008-02-08 04:19:53 -0800423void __tasklet_schedule(struct tasklet_struct *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424{
425 unsigned long flags;
426
427 local_irq_save(flags);
Olof Johansson48f20a92008-03-04 15:23:25 -0800428 t->next = NULL;
Christoph Lameter909ea962010-12-08 16:22:55 +0100429 *__this_cpu_read(tasklet_vec.tail) = t;
430 __this_cpu_write(tasklet_vec.tail, &(t->next));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 raise_softirq_irqoff(TASKLET_SOFTIRQ);
432 local_irq_restore(flags);
433}
434
435EXPORT_SYMBOL(__tasklet_schedule);
436
Harvey Harrison7ad5b3a2008-02-08 04:19:53 -0800437void __tasklet_hi_schedule(struct tasklet_struct *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438{
439 unsigned long flags;
440
441 local_irq_save(flags);
Olof Johansson48f20a92008-03-04 15:23:25 -0800442 t->next = NULL;
Christoph Lameter909ea962010-12-08 16:22:55 +0100443 *__this_cpu_read(tasklet_hi_vec.tail) = t;
444 __this_cpu_write(tasklet_hi_vec.tail, &(t->next));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 raise_softirq_irqoff(HI_SOFTIRQ);
446 local_irq_restore(flags);
447}
448
449EXPORT_SYMBOL(__tasklet_hi_schedule);
450
Vegard Nossum7c692cb2008-05-21 22:53:13 +0200451void __tasklet_hi_schedule_first(struct tasklet_struct *t)
452{
453 BUG_ON(!irqs_disabled());
454
Christoph Lameter909ea962010-12-08 16:22:55 +0100455 t->next = __this_cpu_read(tasklet_hi_vec.head);
456 __this_cpu_write(tasklet_hi_vec.head, t);
Vegard Nossum7c692cb2008-05-21 22:53:13 +0200457 __raise_softirq_irqoff(HI_SOFTIRQ);
458}
459
460EXPORT_SYMBOL(__tasklet_hi_schedule_first);
461
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462static void tasklet_action(struct softirq_action *a)
463{
464 struct tasklet_struct *list;
465
466 local_irq_disable();
Christoph Lameter909ea962010-12-08 16:22:55 +0100467 list = __this_cpu_read(tasklet_vec.head);
468 __this_cpu_write(tasklet_vec.head, NULL);
469 __this_cpu_write(tasklet_vec.tail, &__get_cpu_var(tasklet_vec).head);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 local_irq_enable();
471
472 while (list) {
473 struct tasklet_struct *t = list;
474
475 list = list->next;
476
477 if (tasklet_trylock(t)) {
478 if (!atomic_read(&t->count)) {
479 if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
480 BUG();
481 t->func(t->data);
482 tasklet_unlock(t);
483 continue;
484 }
485 tasklet_unlock(t);
486 }
487
488 local_irq_disable();
Olof Johansson48f20a92008-03-04 15:23:25 -0800489 t->next = NULL;
Christoph Lameter909ea962010-12-08 16:22:55 +0100490 *__this_cpu_read(tasklet_vec.tail) = t;
491 __this_cpu_write(tasklet_vec.tail, &(t->next));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 __raise_softirq_irqoff(TASKLET_SOFTIRQ);
493 local_irq_enable();
494 }
495}
496
497static void tasklet_hi_action(struct softirq_action *a)
498{
499 struct tasklet_struct *list;
500
501 local_irq_disable();
Christoph Lameter909ea962010-12-08 16:22:55 +0100502 list = __this_cpu_read(tasklet_hi_vec.head);
503 __this_cpu_write(tasklet_hi_vec.head, NULL);
504 __this_cpu_write(tasklet_hi_vec.tail, &__get_cpu_var(tasklet_hi_vec).head);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 local_irq_enable();
506
507 while (list) {
508 struct tasklet_struct *t = list;
509
510 list = list->next;
511
512 if (tasklet_trylock(t)) {
513 if (!atomic_read(&t->count)) {
514 if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
515 BUG();
516 t->func(t->data);
517 tasklet_unlock(t);
518 continue;
519 }
520 tasklet_unlock(t);
521 }
522
523 local_irq_disable();
Olof Johansson48f20a92008-03-04 15:23:25 -0800524 t->next = NULL;
Christoph Lameter909ea962010-12-08 16:22:55 +0100525 *__this_cpu_read(tasklet_hi_vec.tail) = t;
526 __this_cpu_write(tasklet_hi_vec.tail, &(t->next));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 __raise_softirq_irqoff(HI_SOFTIRQ);
528 local_irq_enable();
529 }
530}
531
532
533void tasklet_init(struct tasklet_struct *t,
534 void (*func)(unsigned long), unsigned long data)
535{
536 t->next = NULL;
537 t->state = 0;
538 atomic_set(&t->count, 0);
539 t->func = func;
540 t->data = data;
541}
542
543EXPORT_SYMBOL(tasklet_init);
544
545void tasklet_kill(struct tasklet_struct *t)
546{
547 if (in_interrupt())
548 printk("Attempt to kill tasklet from interrupt\n");
549
550 while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
H Hartley Sweeten79d381c2009-04-16 19:30:18 -0400551 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 yield();
H Hartley Sweeten79d381c2009-04-16 19:30:18 -0400553 } while (test_bit(TASKLET_STATE_SCHED, &t->state));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 }
555 tasklet_unlock_wait(t);
556 clear_bit(TASKLET_STATE_SCHED, &t->state);
557}
558
559EXPORT_SYMBOL(tasklet_kill);
560
Peter Zijlstra9ba5f002009-07-22 14:18:35 +0200561/*
562 * tasklet_hrtimer
563 */
564
565/*
Peter Zijlstrab9c30322010-02-03 18:08:52 +0100566 * The trampoline is called when the hrtimer expires. It schedules a tasklet
567 * to run __tasklet_hrtimer_trampoline() which in turn will call the intended
568 * hrtimer callback, but from softirq context.
Peter Zijlstra9ba5f002009-07-22 14:18:35 +0200569 */
570static enum hrtimer_restart __hrtimer_tasklet_trampoline(struct hrtimer *timer)
571{
572 struct tasklet_hrtimer *ttimer =
573 container_of(timer, struct tasklet_hrtimer, timer);
574
Peter Zijlstrab9c30322010-02-03 18:08:52 +0100575 tasklet_hi_schedule(&ttimer->tasklet);
576 return HRTIMER_NORESTART;
Peter Zijlstra9ba5f002009-07-22 14:18:35 +0200577}
578
579/*
580 * Helper function which calls the hrtimer callback from
581 * tasklet/softirq context
582 */
583static void __tasklet_hrtimer_trampoline(unsigned long data)
584{
585 struct tasklet_hrtimer *ttimer = (void *)data;
586 enum hrtimer_restart restart;
587
588 restart = ttimer->function(&ttimer->timer);
589 if (restart != HRTIMER_NORESTART)
590 hrtimer_restart(&ttimer->timer);
591}
592
593/**
594 * tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks
595 * @ttimer: tasklet_hrtimer which is initialized
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300596 * @function: hrtimer callback function which gets called from softirq context
Peter Zijlstra9ba5f002009-07-22 14:18:35 +0200597 * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME)
598 * @mode: hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL)
599 */
600void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
601 enum hrtimer_restart (*function)(struct hrtimer *),
602 clockid_t which_clock, enum hrtimer_mode mode)
603{
604 hrtimer_init(&ttimer->timer, which_clock, mode);
605 ttimer->timer.function = __hrtimer_tasklet_trampoline;
606 tasklet_init(&ttimer->tasklet, __tasklet_hrtimer_trampoline,
607 (unsigned long)ttimer);
608 ttimer->function = function;
609}
610EXPORT_SYMBOL_GPL(tasklet_hrtimer_init);
611
612/*
613 * Remote softirq bits
614 */
615
David S. Miller54514a72008-09-23 22:15:57 -0700616DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);
617EXPORT_PER_CPU_SYMBOL(softirq_work_list);
618
619static void __local_trigger(struct call_single_data *cp, int softirq)
620{
621 struct list_head *head = &__get_cpu_var(softirq_work_list[softirq]);
622
623 list_add_tail(&cp->list, head);
624
625 /* Trigger the softirq only if the list was previously empty. */
626 if (head->next == &cp->list)
627 raise_softirq_irqoff(softirq);
628}
629
630#ifdef CONFIG_USE_GENERIC_SMP_HELPERS
631static void remote_softirq_receive(void *data)
632{
633 struct call_single_data *cp = data;
634 unsigned long flags;
635 int softirq;
636
liguang3440a1c2013-04-30 15:27:26 -0700637 softirq = *(int *)cp->info;
David S. Miller54514a72008-09-23 22:15:57 -0700638 local_irq_save(flags);
639 __local_trigger(cp, softirq);
640 local_irq_restore(flags);
641}
642
643static int __try_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
644{
645 if (cpu_online(cpu)) {
646 cp->func = remote_softirq_receive;
liguang3440a1c2013-04-30 15:27:26 -0700647 cp->info = &softirq;
David S. Miller54514a72008-09-23 22:15:57 -0700648 cp->flags = 0;
David S. Miller54514a72008-09-23 22:15:57 -0700649
Peter Zijlstra6e275632009-02-25 13:59:48 +0100650 __smp_call_function_single(cpu, cp, 0);
David S. Miller54514a72008-09-23 22:15:57 -0700651 return 0;
652 }
653 return 1;
654}
655#else /* CONFIG_USE_GENERIC_SMP_HELPERS */
656static int __try_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
657{
658 return 1;
659}
660#endif
661
662/**
663 * __send_remote_softirq - try to schedule softirq work on a remote cpu
664 * @cp: private SMP call function data area
665 * @cpu: the remote cpu
666 * @this_cpu: the currently executing cpu
667 * @softirq: the softirq for the work
668 *
669 * Attempt to schedule softirq work on a remote cpu. If this cannot be
670 * done, the work is instead queued up on the local cpu.
671 *
672 * Interrupts must be disabled.
673 */
674void __send_remote_softirq(struct call_single_data *cp, int cpu, int this_cpu, int softirq)
675{
676 if (cpu == this_cpu || __try_remote_softirq(cp, cpu, softirq))
677 __local_trigger(cp, softirq);
678}
679EXPORT_SYMBOL(__send_remote_softirq);
680
681/**
682 * send_remote_softirq - try to schedule softirq work on a remote cpu
683 * @cp: private SMP call function data area
684 * @cpu: the remote cpu
685 * @softirq: the softirq for the work
686 *
687 * Like __send_remote_softirq except that disabling interrupts and
688 * computing the current cpu is done for the caller.
689 */
690void send_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
691{
692 unsigned long flags;
693 int this_cpu;
694
695 local_irq_save(flags);
696 this_cpu = smp_processor_id();
697 __send_remote_softirq(cp, cpu, this_cpu, softirq);
698 local_irq_restore(flags);
699}
700EXPORT_SYMBOL(send_remote_softirq);
701
Paul Gortmaker0db06282013-06-19 14:53:51 -0400702static int remote_softirq_cpu_notify(struct notifier_block *self,
David S. Miller54514a72008-09-23 22:15:57 -0700703 unsigned long action, void *hcpu)
704{
705 /*
706 * If a CPU goes away, splice its entries to the current CPU
707 * and trigger a run of the softirq
708 */
709 if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
710 int cpu = (unsigned long) hcpu;
711 int i;
712
713 local_irq_disable();
714 for (i = 0; i < NR_SOFTIRQS; i++) {
715 struct list_head *head = &per_cpu(softirq_work_list[i], cpu);
716 struct list_head *local_head;
717
718 if (list_empty(head))
719 continue;
720
721 local_head = &__get_cpu_var(softirq_work_list[i]);
722 list_splice_init(head, local_head);
723 raise_softirq_irqoff(i);
724 }
725 local_irq_enable();
726 }
727
728 return NOTIFY_OK;
729}
730
Paul Gortmaker0db06282013-06-19 14:53:51 -0400731static struct notifier_block remote_softirq_cpu_notifier = {
David S. Miller54514a72008-09-23 22:15:57 -0700732 .notifier_call = remote_softirq_cpu_notify,
733};
734
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735void __init softirq_init(void)
736{
Olof Johansson48f20a92008-03-04 15:23:25 -0800737 int cpu;
738
739 for_each_possible_cpu(cpu) {
David S. Miller54514a72008-09-23 22:15:57 -0700740 int i;
741
Olof Johansson48f20a92008-03-04 15:23:25 -0800742 per_cpu(tasklet_vec, cpu).tail =
743 &per_cpu(tasklet_vec, cpu).head;
744 per_cpu(tasklet_hi_vec, cpu).tail =
745 &per_cpu(tasklet_hi_vec, cpu).head;
David S. Miller54514a72008-09-23 22:15:57 -0700746 for (i = 0; i < NR_SOFTIRQS; i++)
747 INIT_LIST_HEAD(&per_cpu(softirq_work_list[i], cpu));
Olof Johansson48f20a92008-03-04 15:23:25 -0800748 }
749
David S. Miller54514a72008-09-23 22:15:57 -0700750 register_hotcpu_notifier(&remote_softirq_cpu_notifier);
751
Carlos R. Mafra962cf362008-05-15 11:15:37 -0300752 open_softirq(TASKLET_SOFTIRQ, tasklet_action);
753 open_softirq(HI_SOFTIRQ, tasklet_hi_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754}
755
Thomas Gleixner3e339b52012-07-16 10:42:37 +0000756static int ksoftirqd_should_run(unsigned int cpu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757{
Thomas Gleixner3e339b52012-07-16 10:42:37 +0000758 return local_softirq_pending();
759}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
Thomas Gleixner3e339b52012-07-16 10:42:37 +0000761static void run_ksoftirqd(unsigned int cpu)
762{
763 local_irq_disable();
764 if (local_softirq_pending()) {
765 __do_softirq();
766 rcu_note_context_switch(cpu);
767 local_irq_enable();
768 cond_resched();
769 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 }
Thomas Gleixner3e339b52012-07-16 10:42:37 +0000771 local_irq_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772}
773
774#ifdef CONFIG_HOTPLUG_CPU
775/*
776 * tasklet_kill_immediate is called to remove a tasklet which can already be
777 * scheduled for execution on @cpu.
778 *
779 * Unlike tasklet_kill, this function removes the tasklet
780 * _immediately_, even if the tasklet is in TASKLET_STATE_SCHED state.
781 *
782 * When this function is called, @cpu must be in the CPU_DEAD state.
783 */
784void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu)
785{
786 struct tasklet_struct **i;
787
788 BUG_ON(cpu_online(cpu));
789 BUG_ON(test_bit(TASKLET_STATE_RUN, &t->state));
790
791 if (!test_bit(TASKLET_STATE_SCHED, &t->state))
792 return;
793
794 /* CPU is dead, so no lock needed. */
Olof Johansson48f20a92008-03-04 15:23:25 -0800795 for (i = &per_cpu(tasklet_vec, cpu).head; *i; i = &(*i)->next) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 if (*i == t) {
797 *i = t->next;
Olof Johansson48f20a92008-03-04 15:23:25 -0800798 /* If this was the tail element, move the tail ptr */
799 if (*i == NULL)
800 per_cpu(tasklet_vec, cpu).tail = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 return;
802 }
803 }
804 BUG();
805}
806
807static void takeover_tasklets(unsigned int cpu)
808{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 /* CPU is dead, so no lock needed. */
810 local_irq_disable();
811
812 /* Find end, append list for that CPU. */
Christian Borntraegere5e41722008-05-01 04:34:23 -0700813 if (&per_cpu(tasklet_vec, cpu).head != per_cpu(tasklet_vec, cpu).tail) {
Christoph Lameter909ea962010-12-08 16:22:55 +0100814 *__this_cpu_read(tasklet_vec.tail) = per_cpu(tasklet_vec, cpu).head;
815 this_cpu_write(tasklet_vec.tail, per_cpu(tasklet_vec, cpu).tail);
Christian Borntraegere5e41722008-05-01 04:34:23 -0700816 per_cpu(tasklet_vec, cpu).head = NULL;
817 per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head;
818 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 raise_softirq_irqoff(TASKLET_SOFTIRQ);
820
Christian Borntraegere5e41722008-05-01 04:34:23 -0700821 if (&per_cpu(tasklet_hi_vec, cpu).head != per_cpu(tasklet_hi_vec, cpu).tail) {
Christoph Lameter909ea962010-12-08 16:22:55 +0100822 *__this_cpu_read(tasklet_hi_vec.tail) = per_cpu(tasklet_hi_vec, cpu).head;
823 __this_cpu_write(tasklet_hi_vec.tail, per_cpu(tasklet_hi_vec, cpu).tail);
Christian Borntraegere5e41722008-05-01 04:34:23 -0700824 per_cpu(tasklet_hi_vec, cpu).head = NULL;
825 per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head;
826 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 raise_softirq_irqoff(HI_SOFTIRQ);
828
829 local_irq_enable();
830}
831#endif /* CONFIG_HOTPLUG_CPU */
832
Paul Gortmaker0db06282013-06-19 14:53:51 -0400833static int cpu_callback(struct notifier_block *nfb,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 unsigned long action,
835 void *hcpu)
836{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 switch (action) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838#ifdef CONFIG_HOTPLUG_CPU
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 case CPU_DEAD:
Thomas Gleixner3e339b52012-07-16 10:42:37 +0000840 case CPU_DEAD_FROZEN:
841 takeover_tasklets((unsigned long)hcpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 break;
843#endif /* CONFIG_HOTPLUG_CPU */
Thomas Gleixner3e339b52012-07-16 10:42:37 +0000844 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 return NOTIFY_OK;
846}
847
Paul Gortmaker0db06282013-06-19 14:53:51 -0400848static struct notifier_block cpu_nfb = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 .notifier_call = cpu_callback
850};
851
Thomas Gleixner3e339b52012-07-16 10:42:37 +0000852static struct smp_hotplug_thread softirq_threads = {
853 .store = &ksoftirqd,
854 .thread_should_run = ksoftirqd_should_run,
855 .thread_fn = run_ksoftirqd,
856 .thread_comm = "ksoftirqd/%u",
857};
858
Eduard - Gabriel Munteanu7babe8d2008-07-25 19:45:11 -0700859static __init int spawn_ksoftirqd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 register_cpu_notifier(&cpu_nfb);
Thomas Gleixner3e339b52012-07-16 10:42:37 +0000862
863 BUG_ON(smpboot_register_percpu_thread(&softirq_threads));
864
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 return 0;
866}
Eduard - Gabriel Munteanu7babe8d2008-07-25 19:45:11 -0700867early_initcall(spawn_ksoftirqd);
Andrew Morton78eef012006-03-22 00:08:16 -0800868
Yinghai Lu43a25632008-12-28 16:01:13 -0800869/*
870 * [ These __weak aliases are kept in a separate compilation unit, so that
871 * GCC does not inline them incorrectly. ]
872 */
873
874int __init __weak early_irq_init(void)
875{
876 return 0;
877}
878
Yinghai Lu4a046d12009-01-12 17:39:24 -0800879int __init __weak arch_probe_nr_irqs(void)
880{
Thomas Gleixnerb683de22010-09-27 20:55:03 +0200881 return NR_IRQS_LEGACY;
Yinghai Lu4a046d12009-01-12 17:39:24 -0800882}
883
Yinghai Lu43a25632008-12-28 16:01:13 -0800884int __init __weak arch_early_irq_init(void)
885{
886 return 0;
887}