Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
Linus Torvalds [Thu, 24 Jul 2008 19:55:01 +0000 (12:55 -0700)]
* 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  nohz: adjust tick_nohz_stop_sched_tick() call of s390 as well
  nohz: prevent tick stop outside of the idle loop

1  2 
arch/sparc64/kernel/process.c
arch/x86/kernel/process_64.c
kernel/time/tick-sched.c

@@@ -15,6 -15,7 +15,6 @@@
  #include <linux/module.h>
  #include <linux/sched.h>
  #include <linux/kernel.h>
 -#include <linux/kallsyms.h>
  #include <linux/mm.h>
  #include <linux/fs.h>
  #include <linux/smp.h>
@@@ -96,7 -97,7 +96,7 @@@ void cpu_idle(void
        set_thread_flag(TIF_POLLING_NRFLAG);
  
        while(1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
  
                while (!need_resched() && !cpu_is_offline(cpu))
                        sparc64_yield(cpu);
@@@ -210,7 -211,7 +210,7 @@@ static void show_regwindow(struct pt_re
        printk("i4: %016lx i5: %016lx i6: %016lx i7: %016lx\n",
               rwk->ins[4], rwk->ins[5], rwk->ins[6], rwk->ins[7]);
        if (regs->tstate & TSTATE_PRIV)
 -              print_symbol("I7: <%s>\n", rwk->ins[7]);
 +              printk("I7: <%pS>\n", (void *) rwk->ins[7]);
  }
  
  #ifdef CONFIG_SMP
@@@ -231,7 -232,7 +231,7 @@@ void __show_regs(struct pt_regs * regs
  #endif
        printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x    %s\n", regs->tstate,
               regs->tpc, regs->tnpc, regs->y, print_tainted());
 -      print_symbol("TPC: <%s>\n", regs->tpc);
 +      printk("TPC: <%pS>\n", (void *) regs->tpc);
        printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n",
               regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
               regs->u_regs[3]);
        printk("o4: %016lx o5: %016lx sp: %016lx ret_pc: %016lx\n",
               regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
               regs->u_regs[15]);
 -      print_symbol("RPC: <%s>\n", regs->u_regs[15]);
 +      printk("RPC: <%pS>\n", (void *) regs->u_regs[15]);
        show_regwindow(regs);
  #ifdef CONFIG_SMP
        spin_unlock(&regdump_lock);
@@@ -345,6 -346,9 +345,6 @@@ static void sysrq_handle_globreg(int ke
  {
        struct thread_info *tp = current_thread_info();
        struct pt_regs *regs = get_irq_regs();
 -#ifdef CONFIG_KALLSYMS
 -      char buffer[KSYM_SYMBOL_LEN];
 -#endif
        unsigned long flags;
        int this_cpu, cpu;
  
                       gp->tstate, gp->tpc, gp->tnpc,
                       ((tp && tp->task) ? tp->task->comm : "NULL"),
                       ((tp && tp->task) ? tp->task->pid : -1));
 -#ifdef CONFIG_KALLSYMS
 +
                if (gp->tstate & TSTATE_PRIV) {
 -                      sprint_symbol(buffer, gp->tpc);
 -                      printk("             TPC[%s] ", buffer);
 -                      sprint_symbol(buffer, gp->o7);
 -                      printk("O7[%s] ", buffer);
 -                      sprint_symbol(buffer, gp->i7);
 -                      printk("I7[%s]\n", buffer);
 -              } else
 -#endif
 -              {
 +                      printk("             TPC[%pS] O7[%pS] I7[%pS]\n",
 +                             (void *) gp->tpc,
 +                             (void *) gp->o7,
 +                             (void *) gp->i7);
 +              } else {
                        printk("             TPC[%lx] O7[%lx] I7[%lx]\n",
                               gp->tpc, gp->o7, gp->i7);
                }
@@@ -683,9 -691,9 +683,9 @@@ int copy_thread(int nr, unsigned long c
                  ((unsigned long) child_sf) - STACK_BIAS;
  
                /* Special case, if we are spawning a kernel thread from
 -               * a userspace task (via KMOD, NFS, or similar) we must
 -               * disable performance counters in the child because the
 -               * address space and protection realm are changing.
 +               * a userspace task (usermode helper, NFS or similar), we
 +               * must disable performance counters in the child because
 +               * the address space and protection realm are changing.
                 */
                if (t->flags & _TIF_PERFCTR) {
                        t->user_cntd0 = t->user_cntd1 = NULL;
@@@ -120,7 -120,7 +120,7 @@@ void cpu_idle(void
        current_thread_info()->status |= TS_POLLING;
        /* endless idle loop with no priority at all */
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched()) {
  
                        rmb();
@@@ -537,8 -537,8 +537,8 @@@ static inline void __switch_to_xtra(str
  struct task_struct *
  __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
  {
 -      struct thread_struct *prev = &prev_p->thread,
 -                               *next = &next_p->thread;
 +      struct thread_struct *prev = &prev_p->thread;
 +      struct thread_struct *next = &next_p->thread;
        int cpu = smp_processor_id();
        struct tss_struct *tss = &per_cpu(init_tss, cpu);
        unsigned fsindex, gsindex;
  
        /* 
         * Switch FS and GS.
 +       *
 +       * Segment register != 0 always requires a reload.  Also
 +       * reload when it has changed.  When prev process used 64bit
 +       * base always reload to avoid an information leak.
         */
 -      { 
 -              /* segment register != 0 always requires a reload. 
 -                 also reload when it has changed. 
 -                 when prev process used 64bit base always reload
 -                 to avoid an information leak. */
 -              if (unlikely(fsindex | next->fsindex | prev->fs)) {
 -                      loadsegment(fs, next->fsindex);
 -                      /* check if the user used a selector != 0
 -                       * if yes clear 64bit base, since overloaded base
 -                         * is always mapped to the Null selector
 -                         */
 -                      if (fsindex)
 +      if (unlikely(fsindex | next->fsindex | prev->fs)) {
 +              loadsegment(fs, next->fsindex);
 +              /* 
 +               * Check if the user used a selector != 0; if yes
 +               *  clear 64bit base, since overloaded base is always
 +               *  mapped to the Null selector
 +               */
 +              if (fsindex)
                        prev->fs = 0;                           
 -              }
 -              /* when next process has a 64bit base use it */
 -              if (next->fs) 
 -                      wrmsrl(MSR_FS_BASE, next->fs); 
 -              prev->fsindex = fsindex;
 -
 -              if (unlikely(gsindex | next->gsindex | prev->gs)) {
 -                      load_gs_index(next->gsindex);
 -                      if (gsindex)
 +      }
 +      /* when next process has a 64bit base use it */
 +      if (next->fs)
 +              wrmsrl(MSR_FS_BASE, next->fs);
 +      prev->fsindex = fsindex;
 +
 +      if (unlikely(gsindex | next->gsindex | prev->gs)) {
 +              load_gs_index(next->gsindex);
 +              if (gsindex)
                        prev->gs = 0;                           
 -              }
 -              if (next->gs)
 -                      wrmsrl(MSR_KERNEL_GS_BASE, next->gs); 
 -              prev->gsindex = gsindex;
        }
 +      if (next->gs)
 +              wrmsrl(MSR_KERNEL_GS_BASE, next->gs);
 +      prev->gsindex = gsindex;
  
        /* Must be after DS reload */
        unlazy_fpu(prev_p);
        write_pda(pcurrent, next_p); 
  
        write_pda(kernelstack,
 -      (unsigned long)task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
 +                (unsigned long)task_stack_page(next_p) +
 +                THREAD_SIZE - PDA_STACKOFFSET);
  #ifdef CONFIG_CC_STACKPROTECTOR
        write_pda(stack_canary, next_p->stack_canary);
        /*
diff --combined kernel/time/tick-sched.c
@@@ -140,6 -140,8 +140,6 @@@ void tick_nohz_update_jiffies(void
        if (!ts->tick_stopped)
                return;
  
 -      touch_softlockup_watchdog();
 -
        cpu_clear(cpu, nohz_cpu_mask);
        now = ktime_get();
        ts->idle_waketime = now;
        local_irq_save(flags);
        tick_do_update_jiffies64(now);
        local_irq_restore(flags);
 +
 +      touch_softlockup_watchdog();
  }
  
  void tick_nohz_stop_idle(int cpu)
@@@ -195,7 -195,7 +195,7 @@@ u64 get_cpu_idle_time_us(int cpu, u64 *
   * Called either from the idle loop or from irq_exit() when an idle period was
   * just interrupted by an interrupt which did not cause a reschedule.
   */
- void tick_nohz_stop_sched_tick(void)
+ void tick_nohz_stop_sched_tick(int inidle)
  {
        unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags;
        struct tick_sched *ts;
        if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
                goto end;
  
+       if (!inidle && !ts->inidle)
+               goto end;
+       ts->inidle = 1;
        if (need_resched())
                goto end;
  
@@@ -373,11 -378,14 +378,14 @@@ void tick_nohz_restart_sched_tick(void
        local_irq_disable();
        tick_nohz_stop_idle(cpu);
  
-       if (!ts->tick_stopped) {
+       if (!ts->inidle || !ts->tick_stopped) {
+               ts->inidle = 0;
                local_irq_enable();
                return;
        }
  
+       ts->inidle = 0;
        rcu_exit_nohz();
  
        /* Update jiffies first */