mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	timers: Fix get_next_timer_interrupt() computation
The tick_nohz_stop_sched_tick() routine is not properly canceling the sched timer when nothing is pending, because get_next_timer_interrupt() is no longer returning KTIME_MAX in that case. This causes periodic interrupts when none are needed. When determining the next interrupt time, we first use __next_timer_interrupt() to get the first expiring timer in the timer wheel. If no timer is found, we return the base clock value plus NEXT_TIMER_MAX_DELTA to indicate there is no timer in the timer wheel. Back in get_next_timer_interrupt(), we set the "expires" value by converting the timer wheel expiry (in ticks) to a nsec value. But we don't want to do this if the timer wheel expiry value indicates no timer; we want to return KTIME_MAX. Prior to commit500462a9de("timers: Switch to a non-cascading wheel") we checked base->active_timers to see if any timers were active, and if not, we didn't touch the expiry value and so properly returned KTIME_MAX. Now we don't have active_timers. To fix this, we now just check the timer wheel expiry value to see if it is "now + NEXT_TIMER_MAX_DELTA", and if it is, we don't try to compute a new value based on it, but instead simply let the KTIME_MAX value in expires remain. Fixes:500462a9de"timers: Switch to a non-cascading wheel" Signed-off-by: Chris Metcalf <cmetcalf@mellanox.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Christoph Lameter <cl@linux.com> Cc: John Stultz <john.stultz@linaro.org> Link: http://lkml.kernel.org/r/1470688147-22287-1-git-send-email-cmetcalf@mellanox.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
		
							parent
							
								
									f005bd7e3b
								
							
						
					
					
						commit
						46c8f0b077
					
				
					 1 changed files with 4 additions and 1 deletions
				
			
		| 
						 | 
					@ -1496,6 +1496,7 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
 | 
				
			||||||
	struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
 | 
						struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
 | 
				
			||||||
	u64 expires = KTIME_MAX;
 | 
						u64 expires = KTIME_MAX;
 | 
				
			||||||
	unsigned long nextevt;
 | 
						unsigned long nextevt;
 | 
				
			||||||
 | 
						bool is_max_delta;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Pretend that there is no timer pending if the cpu is offline.
 | 
						 * Pretend that there is no timer pending if the cpu is offline.
 | 
				
			||||||
| 
						 | 
					@ -1506,6 +1507,7 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock(&base->lock);
 | 
						spin_lock(&base->lock);
 | 
				
			||||||
	nextevt = __next_timer_interrupt(base);
 | 
						nextevt = __next_timer_interrupt(base);
 | 
				
			||||||
 | 
						is_max_delta = (nextevt == base->clk + NEXT_TIMER_MAX_DELTA);
 | 
				
			||||||
	base->next_expiry = nextevt;
 | 
						base->next_expiry = nextevt;
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * We have a fresh next event. Check whether we can forward the base:
 | 
						 * We have a fresh next event. Check whether we can forward the base:
 | 
				
			||||||
| 
						 | 
					@ -1519,7 +1521,8 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
 | 
				
			||||||
		expires = basem;
 | 
							expires = basem;
 | 
				
			||||||
		base->is_idle = false;
 | 
							base->is_idle = false;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		expires = basem + (nextevt - basej) * TICK_NSEC;
 | 
							if (!is_max_delta)
 | 
				
			||||||
 | 
								expires = basem + (nextevt - basej) * TICK_NSEC;
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * If we expect to sleep more than a tick, mark the base idle:
 | 
							 * If we expect to sleep more than a tick, mark the base idle:
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue