7085 lines · 173.9 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* *  kernel/sched/core.c * *  Core kernel scheduler code and related syscalls * *  Copyright (C) 1991-2002  Linus Torvalds */#include "sched.h" #include <linux/nospec.h> #include <linux/kcov.h> #include <asm/switch_to.h>#include <asm/tlb.h> #include "../workqueue_internal.h"#include "../smpboot.h" #include "pelt.h" #define CREATE_TRACE_POINTS#include <trace/events/sched.h> DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); #if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_JUMP_LABEL)/* * Debugging: various feature bits * * If SCHED_DEBUG is disabled, each compilation unit has its own copy of * sysctl_sched_features, defined in sched.h, to allow constants propagation * at compile time and compiler optimization based on features default. */#define SCHED_FEAT(name, enabled)	\	(1UL << __SCHED_FEAT_##name) * enabled |const_debug unsigned int sysctl_sched_features =#include "features.h"	0;#undef SCHED_FEAT#endif /* * Number of tasks to iterate in a single balance run. * Limited because this is done with IRQs disabled. */const_debug unsigned int sysctl_sched_nr_migrate = 32; /* * period over which we measure -rt task CPU usage in us. * default: 1s */unsigned int sysctl_sched_rt_period = 1000000; __read_mostly int scheduler_running; /* * part of the period that we allow rt tasks to run in us. * default: 0.95s */int sysctl_sched_rt_runtime = 950000; /* * __task_rq_lock - lock the rq @p resides on. */struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags *rf)	__acquires(rq->lock){	struct rq *rq; 	lockdep_assert_held(&p->pi_lock); 	for (;;) {		rq = task_rq(p);		raw_spin_lock(&rq->lock);		if (likely(rq == task_rq(p) && !task_on_rq_migrating(p))) {			rq_pin_lock(rq, rf);			return rq;		}		raw_spin_unlock(&rq->lock); 		while (unlikely(task_on_rq_migrating(p)))			cpu_relax();	}} /* * task_rq_lock - lock p->pi_lock and lock the rq @p resides on. */struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf)	__acquires(p->pi_lock)	__acquires(rq->lock){	struct rq *rq; 	for (;;) {		raw_spin_lock_irqsave(&p->pi_lock, rf->flags);		rq = task_rq(p);		raw_spin_lock(&rq->lock);		/*		 *	move_queued_task()		task_rq_lock()		 *		 *	ACQUIRE (rq->lock)		 *	[S] ->on_rq = MIGRATING		[L] rq = task_rq()		 *	WMB (__set_task_cpu())		ACQUIRE (rq->lock);		 *	[S] ->cpu = new_cpu		[L] task_rq()		 *					[L] ->on_rq		 *	RELEASE (rq->lock)		 *		 * If we observe the old CPU in task_rq_lock(), the acquire of		 * the old rq->lock will fully serialize against the stores.		 *		 * If we observe the new CPU in task_rq_lock(), the address		 * dependency headed by '[L] rq = task_rq()' and the acquire		 * will pair with the WMB to ensure we then also see migrating.		 */		if (likely(rq == task_rq(p) && !task_on_rq_migrating(p))) {			rq_pin_lock(rq, rf);			return rq;		}		raw_spin_unlock(&rq->lock);		raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags); 		while (unlikely(task_on_rq_migrating(p)))			cpu_relax();	}} /* * RQ-clock updating methods: */ static void update_rq_clock_task(struct rq *rq, s64 delta){/* * In theory, the compile should just see 0 here, and optimize out the call * to sched_rt_avg_update. But I don't trust it... */	s64 __maybe_unused steal = 0, irq_delta = 0; #ifdef CONFIG_IRQ_TIME_ACCOUNTING	irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time; 	/*	 * Since irq_time is only updated on {soft,}irq_exit, we might run into	 * this case when a previous update_rq_clock() happened inside a	 * {soft,}irq region.	 *	 * When this happens, we stop ->clock_task and only update the	 * prev_irq_time stamp to account for the part that fit, so that a next	 * update will consume the rest. This ensures ->clock_task is	 * monotonic.	 *	 * It does however cause some slight miss-attribution of {soft,}irq	 * time, a more accurate solution would be to update the irq_time using	 * the current rq->clock timestamp, except that would require using	 * atomic ops.	 */	if (irq_delta > delta)		irq_delta = delta; 	rq->prev_irq_time += irq_delta;	delta -= irq_delta;#endif#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING	if (static_key_false((&paravirt_steal_rq_enabled))) {		steal = paravirt_steal_clock(cpu_of(rq));		steal -= rq->prev_steal_time_rq; 		if (unlikely(steal > delta))			steal = delta; 		rq->prev_steal_time_rq += steal;		delta -= steal;	}#endif 	rq->clock_task += delta; #ifdef CONFIG_HAVE_SCHED_AVG_IRQ	if ((irq_delta + steal) && sched_feat(NONTASK_CAPACITY))		update_irq_load_avg(rq, irq_delta + steal);#endif	update_rq_clock_pelt(rq, delta);} void update_rq_clock(struct rq *rq){	s64 delta; 	lockdep_assert_held(&rq->lock); 	if (rq->clock_update_flags & RQCF_ACT_SKIP)		return; #ifdef CONFIG_SCHED_DEBUG	if (sched_feat(WARN_DOUBLE_CLOCK))		SCHED_WARN_ON(rq->clock_update_flags & RQCF_UPDATED);	rq->clock_update_flags |= RQCF_UPDATED;#endif 	delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;	if (delta < 0)		return;	rq->clock += delta;	update_rq_clock_task(rq, delta);}  #ifdef CONFIG_SCHED_HRTICK/* * Use HR-timers to deliver accurate preemption points. */ static void hrtick_clear(struct rq *rq){	if (hrtimer_active(&rq->hrtick_timer))		hrtimer_cancel(&rq->hrtick_timer);} /* * High-resolution timer tick. * Runs from hardirq context with interrupts disabled. */static enum hrtimer_restart hrtick(struct hrtimer *timer){	struct rq *rq = container_of(timer, struct rq, hrtick_timer);	struct rq_flags rf; 	WARN_ON_ONCE(cpu_of(rq) != smp_processor_id()); 	rq_lock(rq, &rf);	update_rq_clock(rq);	rq->curr->sched_class->task_tick(rq, rq->curr, 1);	rq_unlock(rq, &rf); 	return HRTIMER_NORESTART;} #ifdef CONFIG_SMP static void __hrtick_restart(struct rq *rq){	struct hrtimer *timer = &rq->hrtick_timer; 	hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED);} /* * called from hardirq (IPI) context */static void __hrtick_start(void *arg){	struct rq *rq = arg;	struct rq_flags rf; 	rq_lock(rq, &rf);	__hrtick_restart(rq);	rq->hrtick_csd_pending = 0;	rq_unlock(rq, &rf);} /* * Called to set the hrtick timer state. * * called with rq->lock held and irqs disabled */void hrtick_start(struct rq *rq, u64 delay){	struct hrtimer *timer = &rq->hrtick_timer;	ktime_t time;	s64 delta; 	/*	 * Don't schedule slices shorter than 10000ns, that just	 * doesn't make sense and can cause timer DoS.	 */	delta = max_t(s64, delay, 10000LL);	time = ktime_add_ns(timer->base->get_time(), delta); 	hrtimer_set_expires(timer, time); 	if (rq == this_rq()) {		__hrtick_restart(rq);	} else if (!rq->hrtick_csd_pending) {		smp_call_function_single_async(cpu_of(rq), &rq->hrtick_csd);		rq->hrtick_csd_pending = 1;	}} #else/* * Called to set the hrtick timer state. * * called with rq->lock held and irqs disabled */void hrtick_start(struct rq *rq, u64 delay){	/*	 * Don't schedule slices shorter than 10000ns, that just	 * doesn't make sense. Rely on vruntime for fairness.	 */	delay = max_t(u64, delay, 10000LL);	hrtimer_start(&rq->hrtick_timer, ns_to_ktime(delay),		      HRTIMER_MODE_REL_PINNED);}#endif /* CONFIG_SMP */ static void hrtick_rq_init(struct rq *rq){#ifdef CONFIG_SMP	rq->hrtick_csd_pending = 0; 	rq->hrtick_csd.flags = 0;	rq->hrtick_csd.func = __hrtick_start;	rq->hrtick_csd.info = rq;#endif 	hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);	rq->hrtick_timer.function = hrtick;}#else	/* CONFIG_SCHED_HRTICK */static inline void hrtick_clear(struct rq *rq){} static inline void hrtick_rq_init(struct rq *rq){}#endif	/* CONFIG_SCHED_HRTICK */ /* * cmpxchg based fetch_or, macro so it works for different integer types */#define fetch_or(ptr, mask)						\	({								\		typeof(ptr) _ptr = (ptr);				\		typeof(mask) _mask = (mask);				\		typeof(*_ptr) _old, _val = *_ptr;			\									\		for (;;) {						\			_old = cmpxchg(_ptr, _val, _val | _mask);	\			if (_old == _val)				\				break;					\			_val = _old;					\		}							\	_old;								\}) #if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG)/* * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG, * this avoids any races wrt polling state changes and thereby avoids * spurious IPIs. */static bool set_nr_and_not_polling(struct task_struct *p){	struct thread_info *ti = task_thread_info(p);	return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG);} /* * Atomically set TIF_NEED_RESCHED if TIF_POLLING_NRFLAG is set. * * If this returns true, then the idle task promises to call * sched_ttwu_pending() and reschedule soon. */static bool set_nr_if_polling(struct task_struct *p){	struct thread_info *ti = task_thread_info(p);	typeof(ti->flags) old, val = READ_ONCE(ti->flags); 	for (;;) {		if (!(val & _TIF_POLLING_NRFLAG))			return false;		if (val & _TIF_NEED_RESCHED)			return true;		old = cmpxchg(&ti->flags, val, val | _TIF_NEED_RESCHED);		if (old == val)			break;		val = old;	}	return true;} #elsestatic bool set_nr_and_not_polling(struct task_struct *p){	set_tsk_need_resched(p);	return true;} #ifdef CONFIG_SMPstatic bool set_nr_if_polling(struct task_struct *p){	return false;}#endif#endif static bool __wake_q_add(struct wake_q_head *head, struct task_struct *task){	struct wake_q_node *node = &task->wake_q; 	/*	 * Atomically grab the task, if ->wake_q is !nil already it means	 * its already queued (either by us or someone else) and will get the	 * wakeup due to that.	 *	 * In order to ensure that a pending wakeup will observe our pending	 * state, even in the failed case, an explicit smp_mb() must be used.	 */	smp_mb__before_atomic();	if (unlikely(cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL)))		return false; 	/*	 * The head is context local, there can be no concurrency.	 */	*head->lastp = node;	head->lastp = &node->next;	return true;} /** * wake_q_add() - queue a wakeup for 'later' waking. * @head: the wake_q_head to add @task to * @task: the task to queue for 'later' wakeup * * Queue a task for later wakeup, most likely by the wake_up_q() call in the * same context, _HOWEVER_ this is not guaranteed, the wakeup can come * instantly. * * This function must be used as-if it were wake_up_process(); IOW the task * must be ready to be woken at this location. */void wake_q_add(struct wake_q_head *head, struct task_struct *task){	if (__wake_q_add(head, task))		get_task_struct(task);} /** * wake_q_add_safe() - safely queue a wakeup for 'later' waking. * @head: the wake_q_head to add @task to * @task: the task to queue for 'later' wakeup * * Queue a task for later wakeup, most likely by the wake_up_q() call in the * same context, _HOWEVER_ this is not guaranteed, the wakeup can come * instantly. * * This function must be used as-if it were wake_up_process(); IOW the task * must be ready to be woken at this location. * * This function is essentially a task-safe equivalent to wake_q_add(). Callers * that already hold reference to @task can call the 'safe' version and trust * wake_q to do the right thing depending whether or not the @task is already * queued for wakeup. */void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task){	if (!__wake_q_add(head, task))		put_task_struct(task);} void wake_up_q(struct wake_q_head *head){	struct wake_q_node *node = head->first; 	while (node != WAKE_Q_TAIL) {		struct task_struct *task; 		task = container_of(node, struct task_struct, wake_q);		BUG_ON(!task);		/* Task can safely be re-inserted now: */		node = node->next;		task->wake_q.next = NULL; 		/*		 * wake_up_process() executes a full barrier, which pairs with		 * the queueing in wake_q_add() so as not to miss wakeups.		 */		wake_up_process(task);		put_task_struct(task);	}} /* * resched_curr - mark rq's current task 'to be rescheduled now'. * * On UP this means the setting of the need_resched flag, on SMP it * might also involve a cross-CPU call to trigger the scheduler on * the target CPU. */void resched_curr(struct rq *rq){	struct task_struct *curr = rq->curr;	int cpu; 

Lines 1–500 of 7085.