1590 lines · 40.8 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* *  Copyright(C) 2005-2006, Linutronix GmbH, Thomas Gleixner <tglx@kernel.org> *  Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar *  Copyright(C) 2006-2007  Timesys Corp., Thomas Gleixner * *  NOHZ implementation for low and high resolution timers * *  Started by: Thomas Gleixner and Ingo Molnar */#include <linux/compiler.h>#include <linux/cpu.h>#include <linux/err.h>#include <linux/hrtimer.h>#include <linux/interrupt.h>#include <linux/kernel_stat.h>#include <linux/percpu.h>#include <linux/nmi.h>#include <linux/profile.h>#include <linux/sched/signal.h>#include <linux/sched/clock.h>#include <linux/sched/stat.h>#include <linux/sched/nohz.h>#include <linux/sched/loadavg.h>#include <linux/module.h>#include <linux/irq_work.h>#include <linux/posix-timers.h>#include <linux/context_tracking.h>#include <linux/mm.h> #include <asm/irq_regs.h> #include "tick-internal.h" #include <trace/events/timer.h> /* * Per-CPU nohz control structure */static DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched); struct tick_sched *tick_get_tick_sched(int cpu){	return &per_cpu(tick_cpu_sched, cpu);} /* * The time when the last jiffy update happened. Write access must hold * jiffies_lock and jiffies_seq. tick_nohz_next_event() needs to get a * consistent view of jiffies and last_jiffies_update. */static ktime_t last_jiffies_update; /* * Must be called with interrupts disabled ! */static void tick_do_update_jiffies64(ktime_t now){	unsigned long ticks = 1;	ktime_t delta, nextp; 	/*	 * 64-bit can do a quick check without holding the jiffies lock and	 * without looking at the sequence count. The smp_load_acquire()	 * pairs with the update done later in this function.	 *	 * 32-bit cannot do that because the store of 'tick_next_period'	 * consists of two 32-bit stores, and the first store could be	 * moved by the CPU to a random point in the future.	 */	if (IS_ENABLED(CONFIG_64BIT)) {		if (ktime_before(now, smp_load_acquire(&tick_next_period)))			return;	} else {		unsigned int seq; 		/*		 * Avoid contention on 'jiffies_lock' and protect the quick		 * check with the sequence count.		 */		do {			seq = read_seqcount_begin(&jiffies_seq);			nextp = tick_next_period;		} while (read_seqcount_retry(&jiffies_seq, seq)); 		if (ktime_before(now, nextp))			return;	} 	/* Quick check failed, i.e. update is required. */	raw_spin_lock(&jiffies_lock);	/*	 * Re-evaluate with the lock held. Another CPU might have done the	 * update already.	 */	if (ktime_before(now, tick_next_period)) {		raw_spin_unlock(&jiffies_lock);		return;	} 	write_seqcount_begin(&jiffies_seq); 	delta = ktime_sub(now, tick_next_period);	if (unlikely(delta >= TICK_NSEC)) {		/* Slow path for long idle sleep times */		s64 incr = TICK_NSEC; 		ticks += ktime_divns(delta, incr); 		last_jiffies_update = ktime_add_ns(last_jiffies_update,						   incr * ticks);	} else {		last_jiffies_update = ktime_add_ns(last_jiffies_update,						   TICK_NSEC);	} 	/* Advance jiffies to complete the 'jiffies_seq' protected job */	jiffies_64 += ticks; 	/* Keep the tick_next_period variable up to date */	nextp = ktime_add_ns(last_jiffies_update, TICK_NSEC); 	if (IS_ENABLED(CONFIG_64BIT)) {		/*		 * Pairs with smp_load_acquire() in the lockless quick		 * check above, and ensures that the update to 'jiffies_64' is		 * not reordered vs. the store to 'tick_next_period', neither		 * by the compiler nor by the CPU.		 */		smp_store_release(&tick_next_period, nextp);	} else {		/*		 * A plain store is good enough on 32-bit, as the quick check		 * above is protected by the sequence count.		 */		tick_next_period = nextp;	} 	/*	 * Release the sequence count. calc_global_load() below is not	 * protected by it, but 'jiffies_lock' needs to be held to prevent	 * concurrent invocations.	 */	write_seqcount_end(&jiffies_seq); 	calc_global_load(); 	raw_spin_unlock(&jiffies_lock);	update_wall_time();} /* * Initialize and return retrieve the jiffies update. */static ktime_t tick_init_jiffy_update(void){	ktime_t period; 	raw_spin_lock(&jiffies_lock);	write_seqcount_begin(&jiffies_seq); 	/* Have we started the jiffies update yet ? */	if (last_jiffies_update == 0) {		u32 rem; 		/*		 * Ensure that the tick is aligned to a multiple of		 * TICK_NSEC.		 */		div_u64_rem(tick_next_period, TICK_NSEC, &rem);		if (rem)			tick_next_period += TICK_NSEC - rem; 		last_jiffies_update = tick_next_period;	}	period = last_jiffies_update; 	write_seqcount_end(&jiffies_seq);	raw_spin_unlock(&jiffies_lock); 	return period;} static inline int tick_sched_flag_test(struct tick_sched *ts,				       unsigned long flag){	return !!(ts->flags & flag);} static inline void tick_sched_flag_set(struct tick_sched *ts,				       unsigned long flag){	lockdep_assert_irqs_disabled();	ts->flags |= flag;} static inline void tick_sched_flag_clear(struct tick_sched *ts,					 unsigned long flag){	lockdep_assert_irqs_disabled();	ts->flags &= ~flag;} /* * Allow only one non-timekeeper CPU at a time update jiffies from * the timer tick. * * Returns true if update was run. */static bool tick_limited_update_jiffies64(struct tick_sched *ts, ktime_t now){	static atomic_t in_progress;	int inp; 	inp = atomic_read(&in_progress);	if (inp || !atomic_try_cmpxchg(&in_progress, &inp, 1))		return false; 	if (ts->last_tick_jiffies == jiffies)		tick_do_update_jiffies64(now);	atomic_set(&in_progress, 0);	return true;} #define MAX_STALLED_JIFFIES 5 static void tick_sched_do_timer(struct tick_sched *ts, ktime_t now){	int tick_cpu, cpu = smp_processor_id(); 	/*	 * Check if the do_timer duty was dropped. We don't care about	 * concurrency: This happens only when the CPU in charge went	 * into a long sleep. If two CPUs happen to assign themselves to	 * this duty, then the jiffies update is still serialized by	 * 'jiffies_lock'.	 *	 * If nohz_full is enabled, this should not happen because the	 * 'tick_do_timer_cpu' CPU never relinquishes.	 */	tick_cpu = READ_ONCE(tick_do_timer_cpu); 	if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && unlikely(tick_cpu == TICK_DO_TIMER_NONE)) {#ifdef CONFIG_NO_HZ_FULL		WARN_ON_ONCE(tick_nohz_full_running);#endif		WRITE_ONCE(tick_do_timer_cpu, cpu);		tick_cpu = cpu;	} 	/* Check if jiffies need an update */	if (tick_cpu == cpu)		tick_do_update_jiffies64(now); 	/*	 * If the jiffies update stalled for too long (timekeeper in stop_machine()	 * or VMEXIT'ed for several msecs), force an update.	 */	if (ts->last_tick_jiffies != jiffies) {		ts->stalled_jiffies = 0;		ts->last_tick_jiffies = READ_ONCE(jiffies);	} else {		if (++ts->stalled_jiffies >= MAX_STALLED_JIFFIES) {			if (tick_limited_update_jiffies64(ts, now)) {				ts->stalled_jiffies = 0;				ts->last_tick_jiffies = READ_ONCE(jiffies);			}		}	} 	if (tick_sched_flag_test(ts, TS_FLAG_INIDLE))		ts->got_idle_tick = 1;} static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs){	/*	 * When we are idle and the tick is stopped, we have to touch	 * the watchdog as we might not schedule for a really long	 * time. This happens on completely idle SMP systems while	 * waiting on the login prompt. We also increment the "start of	 * idle" jiffy stamp so the idle accounting adjustment we do	 * when we go busy again does not account too many ticks.	 */	if (IS_ENABLED(CONFIG_NO_HZ_COMMON) &&	    tick_sched_flag_test(ts, TS_FLAG_STOPPED)) {		touch_softlockup_watchdog_sched();		/*		 * In case the current tick fired too early past its expected		 * expiration, make sure we don't bypass the next clock reprogramming		 * to the same deadline.		 */		ts->next_tick = 0;	} 	update_process_times(user_mode(regs));	profile_tick(CPU_PROFILING);} /* * We rearm the timer until we get disabled by the idle code. * Called with interrupts disabled. */static enum hrtimer_restart tick_nohz_handler(struct hrtimer *timer){	struct tick_sched *ts =	container_of(timer, struct tick_sched, sched_timer);	struct pt_regs *regs = get_irq_regs();	ktime_t now = ktime_get(); 	tick_sched_do_timer(ts, now); 	/*	 * Do not call when we are not in IRQ context and have	 * no valid 'regs' pointer	 */	if (regs)		tick_sched_handle(ts, regs);	else		ts->next_tick = 0; 	/*	 * In dynticks mode, tick reprogram is deferred:	 * - to the idle task if in dynticks-idle	 * - to IRQ exit if in full-dynticks.	 */	if (unlikely(tick_sched_flag_test(ts, TS_FLAG_STOPPED)))		return HRTIMER_NORESTART; 	hrtimer_forward(timer, now, TICK_NSEC); 	return HRTIMER_RESTART;} #ifdef CONFIG_NO_HZ_FULLcpumask_var_t tick_nohz_full_mask;EXPORT_SYMBOL_GPL(tick_nohz_full_mask);bool tick_nohz_full_running;EXPORT_SYMBOL_GPL(tick_nohz_full_running);static atomic_t tick_dep_mask; static bool check_tick_dependency(atomic_t *dep){	int val = atomic_read(dep); 	if (likely(!tracepoint_enabled(tick_stop)))		return !!val; 	if (val & TICK_DEP_MASK_POSIX_TIMER) {		trace_tick_stop(0, TICK_DEP_MASK_POSIX_TIMER);		return true;	} 	if (val & TICK_DEP_MASK_PERF_EVENTS) {		trace_tick_stop(0, TICK_DEP_MASK_PERF_EVENTS);		return true;	} 	if (val & TICK_DEP_MASK_SCHED) {		trace_tick_stop(0, TICK_DEP_MASK_SCHED);		return true;	} 	if (val & TICK_DEP_MASK_CLOCK_UNSTABLE) {		trace_tick_stop(0, TICK_DEP_MASK_CLOCK_UNSTABLE);		return true;	} 	if (val & TICK_DEP_MASK_RCU) {		trace_tick_stop(0, TICK_DEP_MASK_RCU);		return true;	} 	if (val & TICK_DEP_MASK_RCU_EXP) {		trace_tick_stop(0, TICK_DEP_MASK_RCU_EXP);		return true;	} 	return false;} static bool can_stop_full_tick(int cpu, struct tick_sched *ts){	lockdep_assert_irqs_disabled(); 	if (unlikely(!cpu_online(cpu)))		return false; 	if (check_tick_dependency(&tick_dep_mask))		return false; 	if (check_tick_dependency(&ts->tick_dep_mask))		return false; 	if (check_tick_dependency(&current->tick_dep_mask))		return false; 	if (check_tick_dependency(&current->signal->tick_dep_mask))		return false; 	return true;} static void nohz_full_kick_func(struct irq_work *work){	/* Empty, the tick restart happens on tick_nohz_irq_exit() */} static DEFINE_PER_CPU(struct irq_work, nohz_full_kick_work) =	IRQ_WORK_INIT_HARD(nohz_full_kick_func); /* * Kick this CPU if it's full dynticks in order to force it to * re-evaluate its dependency on the tick and restart it if necessary. * This kick, unlike tick_nohz_full_kick_cpu() and tick_nohz_full_kick_all(), * is NMI safe. */static void tick_nohz_full_kick(void){	if (!tick_nohz_full_cpu(smp_processor_id()))		return; 	irq_work_queue(this_cpu_ptr(&nohz_full_kick_work));} /* * Kick the CPU if it's full dynticks in order to force it to * re-evaluate its dependency on the tick and restart it if necessary. */void tick_nohz_full_kick_cpu(int cpu){	if (!tick_nohz_full_cpu(cpu))		return; 	irq_work_queue_on(&per_cpu(nohz_full_kick_work, cpu), cpu);} static void tick_nohz_kick_task(struct task_struct *tsk){	int cpu; 	/*	 * If the task is not running, run_posix_cpu_timers()	 * has nothing to elapse, and an IPI can then be optimized out.	 *	 * activate_task()                      STORE p->tick_dep_mask	 *   STORE p->on_rq	 * __schedule() (switch to task 'p')    smp_mb() (atomic_fetch_or())	 *   LOCK rq->lock                      LOAD p->on_rq	 *   smp_mb__after_spin_lock()	 *   tick_nohz_task_switch()	 *     LOAD p->tick_dep_mask	 *	 * XXX given a task picks up the dependency on schedule(), should we	 * only care about tasks that are currently on the CPU instead of all	 * that are on the runqueue?	 *	 * That is, does this want to be: task_on_cpu() / task_curr()?	 */	if (!sched_task_on_rq(tsk))		return; 	/*	 * If the task concurrently migrates to another CPU,	 * we guarantee it sees the new tick dependency upon	 * schedule.	 *	 * set_task_cpu(p, cpu);	 *   STORE p->cpu = @cpu	 * __schedule() (switch to task 'p')	 *   LOCK rq->lock	 *   smp_mb__after_spin_lock()          STORE p->tick_dep_mask	 *   tick_nohz_task_switch()            smp_mb() (atomic_fetch_or())	 *      LOAD p->tick_dep_mask           LOAD p->cpu	 */	cpu = task_cpu(tsk); 	preempt_disable();	if (cpu_online(cpu))		tick_nohz_full_kick_cpu(cpu);	preempt_enable();} /* * Kick all full dynticks CPUs in order to force these to re-evaluate * their dependency on the tick and restart it if necessary. */static void tick_nohz_full_kick_all(void){	int cpu; 	if (!tick_nohz_full_running)		return; 	preempt_disable();	for_each_cpu_and(cpu, tick_nohz_full_mask, cpu_online_mask)		tick_nohz_full_kick_cpu(cpu);	preempt_enable();} static void tick_nohz_dep_set_all(atomic_t *dep,

Lines 1–500 of 1590.