diff options
Diffstat (limited to 'kernel/softirq.c')
-rw-r--r-- | kernel/softirq.c | 87 |
1 files changed, 41 insertions, 46 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c index d4d918a91881..56e5dec837f0 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -54,7 +54,7 @@ EXPORT_SYMBOL(irq_stat); | |||
54 | 54 | ||
55 | static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp; | 55 | static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp; |
56 | 56 | ||
57 | static DEFINE_PER_CPU(struct task_struct *, ksoftirqd); | 57 | DEFINE_PER_CPU(struct task_struct *, ksoftirqd); |
58 | 58 | ||
59 | char *softirq_to_name[NR_SOFTIRQS] = { | 59 | char *softirq_to_name[NR_SOFTIRQS] = { |
60 | "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL", | 60 | "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL", |
@@ -70,7 +70,7 @@ char *softirq_to_name[NR_SOFTIRQS] = { | |||
70 | static void wakeup_softirqd(void) | 70 | static void wakeup_softirqd(void) |
71 | { | 71 | { |
72 | /* Interrupts are disabled: no need to stop preemption */ | 72 | /* Interrupts are disabled: no need to stop preemption */ |
73 | struct task_struct *tsk = __get_cpu_var(ksoftirqd); | 73 | struct task_struct *tsk = __this_cpu_read(ksoftirqd); |
74 | 74 | ||
75 | if (tsk && tsk->state != TASK_RUNNING) | 75 | if (tsk && tsk->state != TASK_RUNNING) |
76 | wake_up_process(tsk); | 76 | wake_up_process(tsk); |
@@ -311,9 +311,21 @@ void irq_enter(void) | |||
311 | } | 311 | } |
312 | 312 | ||
313 | #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED | 313 | #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED |
314 | # define invoke_softirq() __do_softirq() | 314 | static inline void invoke_softirq(void) |
315 | { | ||
316 | if (!force_irqthreads) | ||
317 | __do_softirq(); | ||
318 | else | ||
319 | wakeup_softirqd(); | ||
320 | } | ||
315 | #else | 321 | #else |
316 | # define invoke_softirq() do_softirq() | 322 | static inline void invoke_softirq(void) |
323 | { | ||
324 | if (!force_irqthreads) | ||
325 | do_softirq(); | ||
326 | else | ||
327 | wakeup_softirqd(); | ||
328 | } | ||
317 | #endif | 329 | #endif |
318 | 330 | ||
319 | /* | 331 | /* |
@@ -388,8 +400,8 @@ void __tasklet_schedule(struct tasklet_struct *t) | |||
388 | 400 | ||
389 | local_irq_save(flags); | 401 | local_irq_save(flags); |
390 | t->next = NULL; | 402 | t->next = NULL; |
391 | *__get_cpu_var(tasklet_vec).tail = t; | 403 | *__this_cpu_read(tasklet_vec.tail) = t; |
392 | __get_cpu_var(tasklet_vec).tail = &(t->next); | 404 | __this_cpu_write(tasklet_vec.tail, &(t->next)); |
393 | raise_softirq_irqoff(TASKLET_SOFTIRQ); | 405 | raise_softirq_irqoff(TASKLET_SOFTIRQ); |
394 | local_irq_restore(flags); | 406 | local_irq_restore(flags); |
395 | } | 407 | } |
@@ -402,8 +414,8 @@ void __tasklet_hi_schedule(struct tasklet_struct *t) | |||
402 | 414 | ||
403 | local_irq_save(flags); | 415 | local_irq_save(flags); |
404 | t->next = NULL; | 416 | t->next = NULL; |
405 | *__get_cpu_var(tasklet_hi_vec).tail = t; | 417 | *__this_cpu_read(tasklet_hi_vec.tail) = t; |
406 | __get_cpu_var(tasklet_hi_vec).tail = &(t->next); | 418 | __this_cpu_write(tasklet_hi_vec.tail, &(t->next)); |
407 | raise_softirq_irqoff(HI_SOFTIRQ); | 419 | raise_softirq_irqoff(HI_SOFTIRQ); |
408 | local_irq_restore(flags); | 420 | local_irq_restore(flags); |
409 | } | 421 | } |
@@ -414,8 +426,8 @@ void __tasklet_hi_schedule_first(struct tasklet_struct *t) | |||
414 | { | 426 | { |
415 | BUG_ON(!irqs_disabled()); | 427 | BUG_ON(!irqs_disabled()); |
416 | 428 | ||
417 | t->next = __get_cpu_var(tasklet_hi_vec).head; | 429 | t->next = __this_cpu_read(tasklet_hi_vec.head); |
418 | __get_cpu_var(tasklet_hi_vec).head = t; | 430 | __this_cpu_write(tasklet_hi_vec.head, t); |
419 | __raise_softirq_irqoff(HI_SOFTIRQ); | 431 | __raise_softirq_irqoff(HI_SOFTIRQ); |
420 | } | 432 | } |
421 | 433 | ||
@@ -426,9 +438,9 @@ static void tasklet_action(struct softirq_action *a) | |||
426 | struct tasklet_struct *list; | 438 | struct tasklet_struct *list; |
427 | 439 | ||
428 | local_irq_disable(); | 440 | local_irq_disable(); |
429 | list = __get_cpu_var(tasklet_vec).head; | 441 | list = __this_cpu_read(tasklet_vec.head); |
430 | __get_cpu_var(tasklet_vec).head = NULL; | 442 | __this_cpu_write(tasklet_vec.head, NULL); |
431 | __get_cpu_var(tasklet_vec).tail = &__get_cpu_var(tasklet_vec).head; | 443 | __this_cpu_write(tasklet_vec.tail, &__get_cpu_var(tasklet_vec).head); |
432 | local_irq_enable(); | 444 | local_irq_enable(); |
433 | 445 | ||
434 | while (list) { | 446 | while (list) { |
@@ -449,8 +461,8 @@ static void tasklet_action(struct softirq_action *a) | |||
449 | 461 | ||
450 | local_irq_disable(); | 462 | local_irq_disable(); |
451 | t->next = NULL; | 463 | t->next = NULL; |
452 | *__get_cpu_var(tasklet_vec).tail = t; | 464 | *__this_cpu_read(tasklet_vec.tail) = t; |
453 | __get_cpu_var(tasklet_vec).tail = &(t->next); | 465 | __this_cpu_write(tasklet_vec.tail, &(t->next)); |
454 | __raise_softirq_irqoff(TASKLET_SOFTIRQ); | 466 | __raise_softirq_irqoff(TASKLET_SOFTIRQ); |
455 | local_irq_enable(); | 467 | local_irq_enable(); |
456 | } | 468 | } |
@@ -461,9 +473,9 @@ static void tasklet_hi_action(struct softirq_action *a) | |||
461 | struct tasklet_struct *list; | 473 | struct tasklet_struct *list; |
462 | 474 | ||
463 | local_irq_disable(); | 475 | local_irq_disable(); |
464 | list = __get_cpu_var(tasklet_hi_vec).head; | 476 | list = __this_cpu_read(tasklet_hi_vec.head); |
465 | __get_cpu_var(tasklet_hi_vec).head = NULL; | 477 | __this_cpu_write(tasklet_hi_vec.head, NULL); |
466 | __get_cpu_var(tasklet_hi_vec).tail = &__get_cpu_var(tasklet_hi_vec).head; | 478 | __this_cpu_write(tasklet_hi_vec.tail, &__get_cpu_var(tasklet_hi_vec).head); |
467 | local_irq_enable(); | 479 | local_irq_enable(); |
468 | 480 | ||
469 | while (list) { | 481 | while (list) { |
@@ -484,8 +496,8 @@ static void tasklet_hi_action(struct softirq_action *a) | |||
484 | 496 | ||
485 | local_irq_disable(); | 497 | local_irq_disable(); |
486 | t->next = NULL; | 498 | t->next = NULL; |
487 | *__get_cpu_var(tasklet_hi_vec).tail = t; | 499 | *__this_cpu_read(tasklet_hi_vec.tail) = t; |
488 | __get_cpu_var(tasklet_hi_vec).tail = &(t->next); | 500 | __this_cpu_write(tasklet_hi_vec.tail, &(t->next)); |
489 | __raise_softirq_irqoff(HI_SOFTIRQ); | 501 | __raise_softirq_irqoff(HI_SOFTIRQ); |
490 | local_irq_enable(); | 502 | local_irq_enable(); |
491 | } | 503 | } |
@@ -721,7 +733,6 @@ static int run_ksoftirqd(void * __bind_cpu) | |||
721 | { | 733 | { |
722 | set_current_state(TASK_INTERRUPTIBLE); | 734 | set_current_state(TASK_INTERRUPTIBLE); |
723 | 735 | ||
724 | current->flags |= PF_KSOFTIRQD; | ||
725 | while (!kthread_should_stop()) { | 736 | while (!kthread_should_stop()) { |
726 | preempt_disable(); | 737 | preempt_disable(); |
727 | if (!local_softirq_pending()) { | 738 | if (!local_softirq_pending()) { |
@@ -738,7 +749,10 @@ static int run_ksoftirqd(void * __bind_cpu) | |||
738 | don't process */ | 749 | don't process */ |
739 | if (cpu_is_offline((long)__bind_cpu)) | 750 | if (cpu_is_offline((long)__bind_cpu)) |
740 | goto wait_to_die; | 751 | goto wait_to_die; |
741 | do_softirq(); | 752 | local_irq_disable(); |
753 | if (local_softirq_pending()) | ||
754 | __do_softirq(); | ||
755 | local_irq_enable(); | ||
742 | preempt_enable_no_resched(); | 756 | preempt_enable_no_resched(); |
743 | cond_resched(); | 757 | cond_resched(); |
744 | preempt_disable(); | 758 | preempt_disable(); |
@@ -802,16 +816,16 @@ static void takeover_tasklets(unsigned int cpu) | |||
802 | 816 | ||
803 | /* Find end, append list for that CPU. */ | 817 | /* Find end, append list for that CPU. */ |
804 | if (&per_cpu(tasklet_vec, cpu).head != per_cpu(tasklet_vec, cpu).tail) { | 818 | if (&per_cpu(tasklet_vec, cpu).head != per_cpu(tasklet_vec, cpu).tail) { |
805 | *(__get_cpu_var(tasklet_vec).tail) = per_cpu(tasklet_vec, cpu).head; | 819 | *__this_cpu_read(tasklet_vec.tail) = per_cpu(tasklet_vec, cpu).head; |
806 | __get_cpu_var(tasklet_vec).tail = per_cpu(tasklet_vec, cpu).tail; | 820 | this_cpu_write(tasklet_vec.tail, per_cpu(tasklet_vec, cpu).tail); |
807 | per_cpu(tasklet_vec, cpu).head = NULL; | 821 | per_cpu(tasklet_vec, cpu).head = NULL; |
808 | per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head; | 822 | per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head; |
809 | } | 823 | } |
810 | raise_softirq_irqoff(TASKLET_SOFTIRQ); | 824 | raise_softirq_irqoff(TASKLET_SOFTIRQ); |
811 | 825 | ||
812 | if (&per_cpu(tasklet_hi_vec, cpu).head != per_cpu(tasklet_hi_vec, cpu).tail) { | 826 | if (&per_cpu(tasklet_hi_vec, cpu).head != per_cpu(tasklet_hi_vec, cpu).tail) { |
813 | *__get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).head; | 827 | *__this_cpu_read(tasklet_hi_vec.tail) = per_cpu(tasklet_hi_vec, cpu).head; |
814 | __get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).tail; | 828 | __this_cpu_write(tasklet_hi_vec.tail, per_cpu(tasklet_hi_vec, cpu).tail); |
815 | per_cpu(tasklet_hi_vec, cpu).head = NULL; | 829 | per_cpu(tasklet_hi_vec, cpu).head = NULL; |
816 | per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head; | 830 | per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head; |
817 | } | 831 | } |
@@ -853,7 +867,7 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb, | |||
853 | cpumask_any(cpu_online_mask)); | 867 | cpumask_any(cpu_online_mask)); |
854 | case CPU_DEAD: | 868 | case CPU_DEAD: |
855 | case CPU_DEAD_FROZEN: { | 869 | case CPU_DEAD_FROZEN: { |
856 | static struct sched_param param = { | 870 | static const struct sched_param param = { |
857 | .sched_priority = MAX_RT_PRIO-1 | 871 | .sched_priority = MAX_RT_PRIO-1 |
858 | }; | 872 | }; |
859 | 873 | ||
@@ -885,25 +899,6 @@ static __init int spawn_ksoftirqd(void) | |||
885 | } | 899 | } |
886 | early_initcall(spawn_ksoftirqd); | 900 | early_initcall(spawn_ksoftirqd); |
887 | 901 | ||
888 | #ifdef CONFIG_SMP | ||
889 | /* | ||
890 | * Call a function on all processors | ||
891 | */ | ||
892 | int on_each_cpu(void (*func) (void *info), void *info, int wait) | ||
893 | { | ||
894 | int ret = 0; | ||
895 | |||
896 | preempt_disable(); | ||
897 | ret = smp_call_function(func, info, wait); | ||
898 | local_irq_disable(); | ||
899 | func(info); | ||
900 | local_irq_enable(); | ||
901 | preempt_enable(); | ||
902 | return ret; | ||
903 | } | ||
904 | EXPORT_SYMBOL(on_each_cpu); | ||
905 | #endif | ||
906 | |||
907 | /* | 902 | /* |
908 | * [ These __weak aliases are kept in a separate compilation unit, so that | 903 | * [ These __weak aliases are kept in a separate compilation unit, so that |
909 | * GCC does not inline them incorrectly. ] | 904 | * GCC does not inline them incorrectly. ] |