]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux...
authorIngo Molnar <mingo@elte.hu>
Sat, 23 Oct 2010 18:05:43 +0000 (20:05 +0200)
committerIngo Molnar <mingo@elte.hu>
Sat, 23 Oct 2010 18:05:43 +0000 (20:05 +0200)
1  2 
include/linux/interrupt.h
kernel/softirq.c

index 414328577cedcdb0c67ccdee0c4c4d06661e2aa5,0ac194946feca910704d0dcac00e6126586f1bcf..07f741a075a78fe242bed11b7bdc9bd712ed557f
@@@ -410,7 -410,7 +410,7 @@@ extern void open_softirq(int nr, void (
  extern void softirq_init(void);
  static inline void __raise_softirq_irqoff(unsigned int nr)
  {
-       trace_softirq_raise((struct softirq_action *)(unsigned long)nr, NULL);
+       trace_softirq_raise(nr);
        or_softirq_pending(1UL << nr);
  }
  
@@@ -647,8 -647,11 +647,8 @@@ static inline void init_irq_proc(void
  struct seq_file;
  int show_interrupts(struct seq_file *p, void *v);
  
 -struct irq_desc;
 -
  extern int early_irq_init(void);
  extern int arch_probe_nr_irqs(void);
  extern int arch_early_irq_init(void);
 -extern int arch_init_chip_data(struct irq_desc *desc, int node);
  
  #endif
diff --combined kernel/softirq.c
index fc978889b1945d2fe6c2520980db3a8410dfdb77,b3cb1dc1579522996ad892547e885ded7ae404dd..e33fd71ed66a301621511eaf85b66cef72afce89
@@@ -76,22 -76,12 +76,22 @@@ void wakeup_softirqd(void
                wake_up_process(tsk);
  }
  
 +/*
 + * preempt_count and SOFTIRQ_OFFSET usage:
 + * - preempt_count is changed by SOFTIRQ_OFFSET on entering or leaving
 + *   softirq processing.
 + * - preempt_count is changed by SOFTIRQ_DISABLE_OFFSET (= 2 * SOFTIRQ_OFFSET)
 + *   on local_bh_disable or local_bh_enable.
 + * This lets us distinguish between whether we are currently processing
 + * softirq and whether we just have bh disabled.
 + */
 +
  /*
   * This one is for softirq.c-internal use,
   * where hardirqs are disabled legitimately:
   */
  #ifdef CONFIG_TRACE_IRQFLAGS
 -static void __local_bh_disable(unsigned long ip)
 +static void __local_bh_disable(unsigned long ip, unsigned int cnt)
  {
        unsigned long flags;
  
         * We must manually increment preempt_count here and manually
         * call the trace_preempt_off later.
         */
 -      preempt_count() += SOFTIRQ_OFFSET;
 +      preempt_count() += cnt;
        /*
         * Were softirqs turned off above:
         */
 -      if (softirq_count() == SOFTIRQ_OFFSET)
 +      if (softirq_count() == cnt)
                trace_softirqs_off(ip);
        raw_local_irq_restore(flags);
  
 -      if (preempt_count() == SOFTIRQ_OFFSET)
 +      if (preempt_count() == cnt)
                trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
  }
  #else /* !CONFIG_TRACE_IRQFLAGS */
 -static inline void __local_bh_disable(unsigned long ip)
 +static inline void __local_bh_disable(unsigned long ip, unsigned int cnt)
  {
 -      add_preempt_count(SOFTIRQ_OFFSET);
 +      add_preempt_count(cnt);
        barrier();
  }
  #endif /* CONFIG_TRACE_IRQFLAGS */
  
  void local_bh_disable(void)
  {
 -      __local_bh_disable((unsigned long)__builtin_return_address(0));
 +      __local_bh_disable((unsigned long)__builtin_return_address(0),
 +                              SOFTIRQ_DISABLE_OFFSET);
  }
  
  EXPORT_SYMBOL(local_bh_disable);
  
 +static void __local_bh_enable(unsigned int cnt)
 +{
 +      WARN_ON_ONCE(in_irq());
 +      WARN_ON_ONCE(!irqs_disabled());
 +
 +      if (softirq_count() == cnt)
 +              trace_softirqs_on((unsigned long)__builtin_return_address(0));
 +      sub_preempt_count(cnt);
 +}
 +
  /*
   * Special-case - softirqs can safely be enabled in
   * cond_resched_softirq(), or by __do_softirq(),
   */
  void _local_bh_enable(void)
  {
 -      WARN_ON_ONCE(in_irq());
 -      WARN_ON_ONCE(!irqs_disabled());
 -
 -      if (softirq_count() == SOFTIRQ_OFFSET)
 -              trace_softirqs_on((unsigned long)__builtin_return_address(0));
 -      sub_preempt_count(SOFTIRQ_OFFSET);
 +      __local_bh_enable(SOFTIRQ_DISABLE_OFFSET);
  }
  
  EXPORT_SYMBOL(_local_bh_enable);
@@@ -163,13 -147,13 +163,13 @@@ static inline void _local_bh_enable_ip(
        /*
         * Are softirqs going to be turned on now:
         */
 -      if (softirq_count() == SOFTIRQ_OFFSET)
 +      if (softirq_count() == SOFTIRQ_DISABLE_OFFSET)
                trace_softirqs_on(ip);
        /*
         * Keep preemption disabled until we are done with
         * softirq processing:
         */
 -      sub_preempt_count(SOFTIRQ_OFFSET - 1);
 +      sub_preempt_count(SOFTIRQ_DISABLE_OFFSET - 1);
  
        if (unlikely(!in_interrupt() && local_softirq_pending()))
                do_softirq();
@@@ -214,8 -198,7 +214,8 @@@ asmlinkage void __do_softirq(void
        pending = local_softirq_pending();
        account_system_vtime(current);
  
 -      __local_bh_disable((unsigned long)__builtin_return_address(0));
 +      __local_bh_disable((unsigned long)__builtin_return_address(0),
 +                              SOFTIRQ_OFFSET);
        lockdep_softirq_enter();
  
        cpu = smp_processor_id();
@@@ -229,18 -212,20 +229,20 @@@ restart
  
        do {
                if (pending & 1) {
+                       unsigned int vec_nr = h - softirq_vec;
                        int prev_count = preempt_count();
-                       kstat_incr_softirqs_this_cpu(h - softirq_vec);
  
-                       trace_softirq_entry(h, softirq_vec);
+                       kstat_incr_softirqs_this_cpu(vec_nr);
+                       trace_softirq_entry(vec_nr);
                        h->action(h);
-                       trace_softirq_exit(h, softirq_vec);
+                       trace_softirq_exit(vec_nr);
                        if (unlikely(prev_count != preempt_count())) {
-                               printk(KERN_ERR "huh, entered softirq %td %s %p"
+                               printk(KERN_ERR "huh, entered softirq %u %s %p"
                                       "with preempt_count %08x,"
-                                      " exited with %08x?\n", h - softirq_vec,
-                                      softirq_to_name[h - softirq_vec],
-                                      h->action, prev_count, preempt_count());
+                                      " exited with %08x?\n", vec_nr,
+                                      softirq_to_name[vec_nr], h->action,
+                                      prev_count, preempt_count());
                                preempt_count() = prev_count;
                        }
  
        lockdep_softirq_exit();
  
        account_system_vtime(current);
 -      _local_bh_enable();
 +      __local_bh_enable(SOFTIRQ_OFFSET);
  }
  
  #ifndef __ARCH_HAS_DO_SOFTIRQ
@@@ -296,16 -281,10 +298,16 @@@ void irq_enter(void
  
        rcu_irq_enter();
        if (idle_cpu(cpu) && !in_interrupt()) {
 -              __irq_enter();
 +              /*
 +               * Prevent raise_softirq from needlessly waking up ksoftirqd
 +               * here, as softirq will be serviced on return from interrupt.
 +               */
 +              local_bh_disable();
                tick_check_idle(cpu);
 -      } else
 -              __irq_enter();
 +              _local_bh_enable();
 +      }
 +
 +      __irq_enter();
  }
  
  #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
@@@ -719,7 -698,6 +721,7 @@@ static int run_ksoftirqd(void * __bind_
  {
        set_current_state(TASK_INTERRUPTIBLE);
  
 +      current->flags |= PF_KSOFTIRQD;
        while (!kthread_should_stop()) {
                preempt_disable();
                if (!local_softirq_pending()) {
@@@ -910,14 -888,17 +912,14 @@@ int __init __weak early_irq_init(void
        return 0;
  }
  
 +#ifdef CONFIG_GENERIC_HARDIRQS
  int __init __weak arch_probe_nr_irqs(void)
  {
 -      return 0;
 +      return NR_IRQS_LEGACY;
  }
  
  int __init __weak arch_early_irq_init(void)
  {
        return 0;
  }
 -
 -int __weak arch_init_chip_data(struct irq_desc *desc, int node)
 -{
 -      return 0;
 -}
 +#endif