]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'core/urgent' into core/locking
authorIngo Molnar <mingo@kernel.org>
Wed, 27 Nov 2013 10:09:19 +0000 (11:09 +0100)
committerIngo Molnar <mingo@kernel.org>
Wed, 27 Nov 2013 10:09:19 +0000 (11:09 +0100)
Prepare for dependent patch.

Signed-off-by: Ingo Molnar <mingo@kernel.org>
1  2 
kernel/softirq.c
lib/Kconfig

diff --combined kernel/softirq.c
index 11025ccc06dd1e2211ca62dcbcea7ce1b05418dd,eb0acf44b0639d9e52a1f4811dca7c3e61d5b32a..f84aa48c0e6663de619daa869f6a1274e0cc5b50
@@@ -6,6 -6,8 +6,6 @@@
   *    Distribute under GPLv2.
   *
   *    Rewritten. Old one was good in 2.2, but in 2.3 it was immoral. --ANK (990903)
 - *
 - *    Remote softirq infrastructure is by Jens Axboe.
   */
  
  #include <linux/export.h>
@@@ -211,14 -213,52 +211,52 @@@ EXPORT_SYMBOL(local_bh_enable_ip)
  #define MAX_SOFTIRQ_TIME  msecs_to_jiffies(2)
  #define MAX_SOFTIRQ_RESTART 10
  
+ #ifdef CONFIG_TRACE_IRQFLAGS
+ /*
+  * Convoluted means of passing __do_softirq() a message through the various
+  * architecture execute_on_stack() bits.
+  *
+  * When we run softirqs from irq_exit() and thus on the hardirq stack we need
+  * to keep the lockdep irq context tracking as tight as possible in order to
+  * not miss-qualify lock contexts and miss possible deadlocks.
+  */
+ static DEFINE_PER_CPU(int, softirq_from_hardirq);
+ static inline void lockdep_softirq_from_hardirq(void)
+ {
+       this_cpu_write(softirq_from_hardirq, 1);
+ }
+ static inline void lockdep_softirq_start(void)
+ {
+       if (this_cpu_read(softirq_from_hardirq))
+               trace_hardirq_exit();
+       lockdep_softirq_enter();
+ }
+ static inline void lockdep_softirq_end(void)
+ {
+       lockdep_softirq_exit();
+       if (this_cpu_read(softirq_from_hardirq)) {
+               this_cpu_write(softirq_from_hardirq, 0);
+               trace_hardirq_enter();
+       }
+ }
+ #else
+ static inline void lockdep_softirq_from_hardirq(void) { }
+ static inline void lockdep_softirq_start(void) { }
+ static inline void lockdep_softirq_end(void) { }
+ #endif
  asmlinkage void __do_softirq(void)
  {
-       struct softirq_action *h;
-       __u32 pending;
        unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
-       int cpu;
        unsigned long old_flags = current->flags;
        int max_restart = MAX_SOFTIRQ_RESTART;
+       struct softirq_action *h;
+       __u32 pending;
+       int cpu;
  
        /*
         * Mask out PF_MEMALLOC s current task context is borrowed for the
        account_irq_enter_time(current);
  
        __local_bh_disable(_RET_IP_, SOFTIRQ_OFFSET);
-       lockdep_softirq_enter();
+       lockdep_softirq_start();
  
        cpu = smp_processor_id();
  restart:
                wakeup_softirqd();
        }
  
-       lockdep_softirq_exit();
+       lockdep_softirq_end();
        account_irq_exit_time(current);
        __local_bh_enable(SOFTIRQ_OFFSET);
        WARN_ON_ONCE(in_interrupt());
        tsk_restore_flags(current, old_flags, PF_MEMALLOC);
  }
  
  asmlinkage void do_softirq(void)
  {
        __u32 pending;
@@@ -330,6 -367,7 +365,7 @@@ void irq_enter(void
  static inline void invoke_softirq(void)
  {
        if (!force_irqthreads) {
+               lockdep_softirq_from_hardirq();
  #ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK
                /*
                 * We can safely execute softirq on the current stack if
@@@ -375,13 -413,13 +411,13 @@@ void irq_exit(void
  #endif
  
        account_irq_exit_time(current);
-       trace_hardirq_exit();
        preempt_count_sub(HARDIRQ_OFFSET);
        if (!in_interrupt() && local_softirq_pending())
                invoke_softirq();
  
        tick_irq_exit();
        rcu_irq_exit();
+       trace_hardirq_exit(); /* must be last! */
  }
  
  /*
@@@ -625,17 -663,146 +661,17 @@@ void tasklet_hrtimer_init(struct taskle
  }
  EXPORT_SYMBOL_GPL(tasklet_hrtimer_init);
  
 -/*
 - * Remote softirq bits
 - */
 -
 -DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);
 -EXPORT_PER_CPU_SYMBOL(softirq_work_list);
 -
 -static void __local_trigger(struct call_single_data *cp, int softirq)
 -{
 -      struct list_head *head = &__get_cpu_var(softirq_work_list[softirq]);
 -
 -      list_add_tail(&cp->list, head);
 -
 -      /* Trigger the softirq only if the list was previously empty.  */
 -      if (head->next == &cp->list)
 -              raise_softirq_irqoff(softirq);
 -}
 -
 -#ifdef CONFIG_USE_GENERIC_SMP_HELPERS
 -static void remote_softirq_receive(void *data)
 -{
 -      struct call_single_data *cp = data;
 -      unsigned long flags;
 -      int softirq;
 -
 -      softirq = *(int *)cp->info;
 -      local_irq_save(flags);
 -      __local_trigger(cp, softirq);
 -      local_irq_restore(flags);
 -}
 -
 -static int __try_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
 -{
 -      if (cpu_online(cpu)) {
 -              cp->func = remote_softirq_receive;
 -              cp->info = &softirq;
 -              cp->flags = 0;
 -
 -              __smp_call_function_single(cpu, cp, 0);
 -              return 0;
 -      }
 -      return 1;
 -}
 -#else /* CONFIG_USE_GENERIC_SMP_HELPERS */
 -static int __try_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
 -{
 -      return 1;
 -}
 -#endif
 -
 -/**
 - * __send_remote_softirq - try to schedule softirq work on a remote cpu
 - * @cp: private SMP call function data area
 - * @cpu: the remote cpu
 - * @this_cpu: the currently executing cpu
 - * @softirq: the softirq for the work
 - *
 - * Attempt to schedule softirq work on a remote cpu.  If this cannot be
 - * done, the work is instead queued up on the local cpu.
 - *
 - * Interrupts must be disabled.
 - */
 -void __send_remote_softirq(struct call_single_data *cp, int cpu, int this_cpu, int softirq)
 -{
 -      if (cpu == this_cpu || __try_remote_softirq(cp, cpu, softirq))
 -              __local_trigger(cp, softirq);
 -}
 -EXPORT_SYMBOL(__send_remote_softirq);
 -
 -/**
 - * send_remote_softirq - try to schedule softirq work on a remote cpu
 - * @cp: private SMP call function data area
 - * @cpu: the remote cpu
 - * @softirq: the softirq for the work
 - *
 - * Like __send_remote_softirq except that disabling interrupts and
 - * computing the current cpu is done for the caller.
 - */
 -void send_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
 -{
 -      unsigned long flags;
 -      int this_cpu;
 -
 -      local_irq_save(flags);
 -      this_cpu = smp_processor_id();
 -      __send_remote_softirq(cp, cpu, this_cpu, softirq);
 -      local_irq_restore(flags);
 -}
 -EXPORT_SYMBOL(send_remote_softirq);
 -
 -static int remote_softirq_cpu_notify(struct notifier_block *self,
 -                                             unsigned long action, void *hcpu)
 -{
 -      /*
 -       * If a CPU goes away, splice its entries to the current CPU
 -       * and trigger a run of the softirq
 -       */
 -      if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
 -              int cpu = (unsigned long) hcpu;
 -              int i;
 -
 -              local_irq_disable();
 -              for (i = 0; i < NR_SOFTIRQS; i++) {
 -                      struct list_head *head = &per_cpu(softirq_work_list[i], cpu);
 -                      struct list_head *local_head;
 -
 -                      if (list_empty(head))
 -                              continue;
 -
 -                      local_head = &__get_cpu_var(softirq_work_list[i]);
 -                      list_splice_init(head, local_head);
 -                      raise_softirq_irqoff(i);
 -              }
 -              local_irq_enable();
 -      }
 -
 -      return NOTIFY_OK;
 -}
 -
 -static struct notifier_block remote_softirq_cpu_notifier = {
 -      .notifier_call  = remote_softirq_cpu_notify,
 -};
 -
  void __init softirq_init(void)
  {
        int cpu;
  
        for_each_possible_cpu(cpu) {
 -              int i;
 -
                per_cpu(tasklet_vec, cpu).tail =
                        &per_cpu(tasklet_vec, cpu).head;
                per_cpu(tasklet_hi_vec, cpu).tail =
                        &per_cpu(tasklet_hi_vec, cpu).head;
 -              for (i = 0; i < NR_SOFTIRQS; i++)
 -                      INIT_LIST_HEAD(&per_cpu(softirq_work_list[i], cpu));
        }
  
 -      register_hotcpu_notifier(&remote_softirq_cpu_notifier);
 -
        open_softirq(TASKLET_SOFTIRQ, tasklet_action);
        open_softirq(HI_SOFTIRQ, tasklet_hi_action);
  }
diff --combined lib/Kconfig
index 06dc74200a5159c5b5458c36e2b71297e638a194,50b47cde8b49f0f6850e44702d0ee6d159a33e3f..3f7fb4de6ee7dd2b15f8de02f2e96a0e02f49728
@@@ -51,6 -51,13 +51,6 @@@ config PERCPU_RWSE
  config ARCH_USE_CMPXCHG_LOCKREF
        bool
  
 -config CMPXCHG_LOCKREF
 -      def_bool y if ARCH_USE_CMPXCHG_LOCKREF
 -      depends on SMP
 -      depends on !GENERIC_LOCKBREAK
 -      depends on !DEBUG_SPINLOCK
 -      depends on !DEBUG_LOCK_ALLOC
 -
  config CRC_CCITT
        tristate "CRC-CCITT functions"
        help
@@@ -182,13 -189,6 +182,13 @@@ config AUDIT_GENERI
        depends on AUDIT && !AUDIT_ARCH
        default y
  
 +config RANDOM32_SELFTEST
 +      bool "PRNG perform self test on init"
 +      default n
 +      help
 +        This option enables the 32 bit PRNG library functions to perform a
 +        self test on initialization.
 +
  #
  # compression support is select'ed if needed
  #
@@@ -342,7 -342,8 +342,8 @@@ config CHECK_SIGNATUR
        bool
  
  config CPUMASK_OFFSTACK
-       bool "Force CPU masks off stack" if DEBUG_PER_CPU_MAPS
+       bool "Force CPU masks off stack"
+       depends on SMP
        help
          Use dynamic allocation for cpumask_var_t, instead of putting
          them on the stack.  This is a bit more expensive, but avoids