Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
time: Fix accumulation bug triggered by long delay.
posix-cpu-timers: Reset expire cache when no timer is running
timer stats: Fix del_timer_sync() and try_to_del_timer_sync()
clockevents: Sanitize min_delta_ns adjustment and prevent overflows

+54 -17
+2
include/linux/clockchips.h
··· 73 73 * @list: list head for the management code 74 74 * @mode: operating mode assigned by the management code 75 75 * @next_event: local storage for the next event in oneshot mode 76 + * @retries: number of forced programming retries 76 77 */ 77 78 struct clock_event_device { 78 79 const char *name; ··· 94 93 struct list_head list; 95 94 enum clock_event_mode mode; 96 95 ktime_t next_event; 96 + unsigned long retries; 97 97 }; 98 98 99 99 /*
+7 -3
kernel/posix-cpu-timers.c
··· 1061 1061 } 1062 1062 } 1063 1063 1064 - static void stop_process_timers(struct task_struct *tsk) 1064 + static void stop_process_timers(struct signal_struct *sig) 1065 1065 { 1066 - struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; 1066 + struct thread_group_cputimer *cputimer = &sig->cputimer; 1067 1067 unsigned long flags; 1068 1068 1069 1069 if (!cputimer->running) ··· 1072 1072 spin_lock_irqsave(&cputimer->lock, flags); 1073 1073 cputimer->running = 0; 1074 1074 spin_unlock_irqrestore(&cputimer->lock, flags); 1075 + 1076 + sig->cputime_expires.prof_exp = cputime_zero; 1077 + sig->cputime_expires.virt_exp = cputime_zero; 1078 + sig->cputime_expires.sched_exp = 0; 1075 1079 } 1076 1080 1077 1081 static u32 onecputick; ··· 1137 1133 list_empty(&timers[CPUCLOCK_VIRT]) && 1138 1134 cputime_eq(sig->it[CPUCLOCK_VIRT].expires, cputime_zero) && 1139 1135 list_empty(&timers[CPUCLOCK_SCHED])) { 1140 - stop_process_timers(tsk); 1136 + stop_process_timers(sig); 1141 1137 return; 1142 1138 } 1143 1139
+40 -12
kernel/time/tick-oneshot.c
··· 22 22 23 23 #include "tick-internal.h" 24 24 25 + /* Limit min_delta to a jiffie */ 26 + #define MIN_DELTA_LIMIT (NSEC_PER_SEC / HZ) 27 + 28 + static int tick_increase_min_delta(struct clock_event_device *dev) 29 + { 30 + /* Nothing to do if we already reached the limit */ 31 + if (dev->min_delta_ns >= MIN_DELTA_LIMIT) 32 + return -ETIME; 33 + 34 + if (dev->min_delta_ns < 5000) 35 + dev->min_delta_ns = 5000; 36 + else 37 + dev->min_delta_ns += dev->min_delta_ns >> 1; 38 + 39 + if (dev->min_delta_ns > MIN_DELTA_LIMIT) 40 + dev->min_delta_ns = MIN_DELTA_LIMIT; 41 + 42 + printk(KERN_WARNING "CE: %s increased min_delta_ns to %llu nsec\n", 43 + dev->name ? dev->name : "?", 44 + (unsigned long long) dev->min_delta_ns); 45 + return 0; 46 + } 47 + 25 48 /** 26 49 * tick_program_event internal worker function 27 50 */ ··· 60 37 if (!ret || !force) 61 38 return ret; 62 39 40 + dev->retries++; 63 41 /* 64 - * We tried 2 times to program the device with the given 65 - * min_delta_ns. If that's not working then we double it 42 + * We tried 3 times to program the device with the given 43 + * min_delta_ns. If that's not working then we increase it 66 44 * and emit a warning. 67 45 */ 68 46 if (++i > 2) { 69 47 /* Increase the min. delta and try again */ 70 - if (!dev->min_delta_ns) 71 - dev->min_delta_ns = 5000; 72 - else 73 - dev->min_delta_ns += dev->min_delta_ns >> 1; 74 - 75 - printk(KERN_WARNING 76 - "CE: %s increasing min_delta_ns to %llu nsec\n", 77 - dev->name ? dev->name : "?", 78 - (unsigned long long) dev->min_delta_ns << 1); 79 - 48 + if (tick_increase_min_delta(dev)) { 49 + /* 50 + * Get out of the loop if min_delta_ns 51 + * hit the limit already. That's 52 + * better than staying here forever. 53 + * 54 + * We clear next_event so we have a 55 + * chance that the box survives. 56 + */ 57 + printk(KERN_WARNING 58 + "CE: Reprogramming failure. Giving up\n"); 59 + dev->next_event.tv64 = KTIME_MAX; 60 + return -ETIME; 61 + } 80 62 i = 0; 81 63 } 82 64
+2 -1
kernel/time/timekeeping.c
··· 818 818 shift = min(shift, maxshift); 819 819 while (offset >= timekeeper.cycle_interval) { 820 820 offset = logarithmic_accumulation(offset, shift); 821 - shift--; 821 + if(offset < timekeeper.cycle_interval<<shift) 822 + shift--; 822 823 } 823 824 824 825 /* correct the clock when NTP error is too big */
+2 -1
kernel/time/timer_list.c
··· 228 228 SEQ_printf(m, " event_handler: "); 229 229 print_name_offset(m, dev->event_handler); 230 230 SEQ_printf(m, "\n"); 231 + SEQ_printf(m, " retries: %lu\n", dev->retries); 231 232 } 232 233 233 234 static void timer_list_show_tickdevices(struct seq_file *m) ··· 258 257 u64 now = ktime_to_ns(ktime_get()); 259 258 int cpu; 260 259 261 - SEQ_printf(m, "Timer List Version: v0.5\n"); 260 + SEQ_printf(m, "Timer List Version: v0.6\n"); 262 261 SEQ_printf(m, "HRTIMER_MAX_CLOCK_BASES: %d\n", HRTIMER_MAX_CLOCK_BASES); 263 262 SEQ_printf(m, "now at %Ld nsecs\n", (unsigned long long)now); 264 263
+1
kernel/timer.c
··· 880 880 if (base->running_timer == timer) 881 881 goto out; 882 882 883 + timer_stats_timer_clear_start_info(timer); 883 884 ret = 0; 884 885 if (timer_pending(timer)) { 885 886 detach_timer(timer, 1);