mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'sched-core-2025-07-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull scheduler updates from Ingo Molnar:
"Core scheduler changes:
- Better tracking of maximum lag of tasks in presence of different
slices duration, for better handling of lag in the fair scheduler
(Vincent Guittot)
- Clean up and standardize #if/#else/#endif markers throughout the
entire scheduler code base (Ingo Molnar)
- Make SMP unconditional: build the SMP scheduler's data structures
and logic on UP kernel too, even though they are not used, to
simplify the scheduler and remove around 200 #ifdef/[#else]/#endif
blocks from the scheduler (Ingo Molnar)
- Reorganize cgroup bandwidth control interface handling for better
interfacing with sched_ext (Tejun Heo)
Balancing:
- Bump sd->max_newidle_lb_cost when newidle balance fails (Chris
Mason)
- Remove sched_domain_topology_level::flags to simplify the code
(Prateek Nayak)
- Simplify and clean up build_sched_topology() (Li Chen)
- Optimize build_sched_topology() on large machines (Li Chen)
Real-time scheduling:
- Add initial version of proxy execution: a mechanism for
mutex-owning tasks to inherit the scheduling context of higher
priority waiters.
Currently limited to a single runqueue and conditional on
CONFIG_EXPERT, and other limitations (John Stultz, Peter Zijlstra,
Valentin Schneider)
- Deadline scheduler (Juri Lelli):
- Fix dl_servers initialization order (Juri Lelli)
- Fix DL scheduler's root domain reinitialization logic (Juri
Lelli)
- Fix accounting bugs after global limits change (Juri Lelli)
- Fix scalability regression by implementing less agressive
dl_server handling (Peter Zijlstra)
PSI:
- Improve scalability by optimizing psi_group_change() cpu_clock()
usage (Peter Zijlstra)
Rust changes:
- Make Task, CondVar and PollCondVar methods inline to avoid
unnecessary function calls (Kunwu Chan, Panagiotis Foliadis)
- Add might_sleep() support for Rust code: Rust's "#[track_caller]"
mechanism is used so that Rust's might_sleep() doesn't need to be
defined as a macro (Fujita Tomonori)
- Introduce file_from_location() (Boqun Feng)
Debugging & instrumentation:
- Make clangd usable with scheduler source code files again (Peter
Zijlstra)
- tools: Add root_domains_dump.py which dumps root domains info (Juri
Lelli)
- tools: Add dl_bw_dump.py for printing bandwidth accounting info
(Juri Lelli)
Misc cleanups & fixes:
- Remove play_idle() (Feng Lee)
- Fix check_preemption_disabled() (Sebastian Andrzej Siewior)
- Do not call __put_task_struct() on RT if pi_blocked_on is set (Luis
Claudio R. Goncalves)
- Correct the comment in place_entity() (wang wei)"
* tag 'sched-core-2025-07-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (84 commits)
sched/idle: Remove play_idle()
sched: Do not call __put_task_struct() on rt if pi_blocked_on is set
sched: Start blocked_on chain processing in find_proxy_task()
sched: Fix proxy/current (push,pull)ability
sched: Add an initial sketch of the find_proxy_task() function
sched: Fix runtime accounting w/ split exec & sched contexts
sched: Move update_curr_task logic into update_curr_se
locking/mutex: Add p->blocked_on wrappers for correctness checks
locking/mutex: Rework task_struct::blocked_on
sched: Add CONFIG_SCHED_PROXY_EXEC & boot argument to enable/disable
sched/topology: Remove sched_domain_topology_level::flags
x86/smpboot: avoid SMT domain attach/destroy if SMT is not enabled
x86/smpboot: moves x86_topology to static initialize and truncate
x86/smpboot: remove redundant CONFIG_SCHED_SMT
smpboot: introduce SDTL_INIT() helper to tidy sched topology setup
tools/sched: Add dl_bw_dump.py for printing bandwidth accounting info
tools/sched: Add root_domains_dump.py which dumps root domains info
sched/deadline: Fix accounting after global limits change
sched/deadline: Reset extra_bw to max_bw when clearing root domains
sched/deadline: Initialize dl_servers after SMP
...
This commit is contained in:
@@ -6410,6 +6410,11 @@
|
||||
sa1100ir [NET]
|
||||
See drivers/net/irda/sa1100_ir.c.
|
||||
|
||||
sched_proxy_exec= [KNL]
|
||||
Enables or disables "proxy execution" style
|
||||
solution to mutex-based priority inversion.
|
||||
Format: <bool>
|
||||
|
||||
sched_verbose [KNL,EARLY] Enables verbose scheduler debug messages.
|
||||
|
||||
schedstats= [KNL,X86] Enable or disable scheduled statistics.
|
||||
|
||||
@@ -22319,6 +22319,7 @@ F: include/linux/wait.h
|
||||
F: include/uapi/linux/sched.h
|
||||
F: kernel/fork.c
|
||||
F: kernel/sched/
|
||||
F: tools/sched/
|
||||
|
||||
SCHEDULER - SCHED_EXT
|
||||
R: Tejun Heo <tj@kernel.org>
|
||||
|
||||
+10
-15
@@ -1700,28 +1700,23 @@ static void __init build_sched_topology(void)
|
||||
#ifdef CONFIG_SCHED_SMT
|
||||
if (has_big_cores) {
|
||||
pr_info("Big cores detected but using small core scheduling\n");
|
||||
powerpc_topology[i++] = (struct sched_domain_topology_level){
|
||||
smallcore_smt_mask, powerpc_smt_flags, SD_INIT_NAME(SMT)
|
||||
};
|
||||
powerpc_topology[i++] =
|
||||
SDTL_INIT(smallcore_smt_mask, powerpc_smt_flags, SMT);
|
||||
} else {
|
||||
powerpc_topology[i++] = (struct sched_domain_topology_level){
|
||||
cpu_smt_mask, powerpc_smt_flags, SD_INIT_NAME(SMT)
|
||||
};
|
||||
powerpc_topology[i++] = SDTL_INIT(cpu_smt_mask, powerpc_smt_flags, SMT);
|
||||
}
|
||||
#endif
|
||||
if (shared_caches) {
|
||||
powerpc_topology[i++] = (struct sched_domain_topology_level){
|
||||
shared_cache_mask, powerpc_shared_cache_flags, SD_INIT_NAME(CACHE)
|
||||
};
|
||||
powerpc_topology[i++] =
|
||||
SDTL_INIT(shared_cache_mask, powerpc_shared_cache_flags, CACHE);
|
||||
}
|
||||
|
||||
if (has_coregroup_support()) {
|
||||
powerpc_topology[i++] = (struct sched_domain_topology_level){
|
||||
cpu_mc_mask, powerpc_shared_proc_flags, SD_INIT_NAME(MC)
|
||||
};
|
||||
powerpc_topology[i++] =
|
||||
SDTL_INIT(cpu_mc_mask, powerpc_shared_proc_flags, MC);
|
||||
}
|
||||
powerpc_topology[i++] = (struct sched_domain_topology_level){
|
||||
cpu_cpu_mask, powerpc_shared_proc_flags, SD_INIT_NAME(PKG)
|
||||
};
|
||||
|
||||
powerpc_topology[i++] = SDTL_INIT(cpu_cpu_mask, powerpc_shared_proc_flags, PKG);
|
||||
|
||||
/* There must be one trailing NULL entry left. */
|
||||
BUG_ON(i >= ARRAY_SIZE(powerpc_topology) - 1);
|
||||
|
||||
@@ -531,11 +531,11 @@ static const struct cpumask *cpu_drawer_mask(int cpu)
|
||||
}
|
||||
|
||||
static struct sched_domain_topology_level s390_topology[] = {
|
||||
{ cpu_thread_mask, cpu_smt_flags, SD_INIT_NAME(SMT) },
|
||||
{ cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
|
||||
{ cpu_book_mask, SD_INIT_NAME(BOOK) },
|
||||
{ cpu_drawer_mask, SD_INIT_NAME(DRAWER) },
|
||||
{ cpu_cpu_mask, SD_INIT_NAME(PKG) },
|
||||
SDTL_INIT(cpu_thread_mask, cpu_smt_flags, SMT),
|
||||
SDTL_INIT(cpu_coregroup_mask, cpu_core_flags, MC),
|
||||
SDTL_INIT(cpu_book_mask, NULL, BOOK),
|
||||
SDTL_INIT(cpu_drawer_mask, NULL, DRAWER),
|
||||
SDTL_INIT(cpu_cpu_mask, NULL, PKG),
|
||||
{ NULL, },
|
||||
};
|
||||
|
||||
|
||||
+24
-27
@@ -478,44 +478,41 @@ static int x86_cluster_flags(void)
|
||||
*/
|
||||
static bool x86_has_numa_in_package;
|
||||
|
||||
static struct sched_domain_topology_level x86_topology[6];
|
||||
static struct sched_domain_topology_level x86_topology[] = {
|
||||
SDTL_INIT(cpu_smt_mask, cpu_smt_flags, SMT),
|
||||
#ifdef CONFIG_SCHED_CLUSTER
|
||||
SDTL_INIT(cpu_clustergroup_mask, x86_cluster_flags, CLS),
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_MC
|
||||
SDTL_INIT(cpu_coregroup_mask, x86_core_flags, MC),
|
||||
#endif
|
||||
SDTL_INIT(cpu_cpu_mask, x86_sched_itmt_flags, PKG),
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static void __init build_sched_topology(void)
|
||||
{
|
||||
int i = 0;
|
||||
struct sched_domain_topology_level *topology = x86_topology;
|
||||
|
||||
#ifdef CONFIG_SCHED_SMT
|
||||
x86_topology[i++] = (struct sched_domain_topology_level){
|
||||
cpu_smt_mask, cpu_smt_flags, SD_INIT_NAME(SMT)
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CLUSTER
|
||||
x86_topology[i++] = (struct sched_domain_topology_level){
|
||||
cpu_clustergroup_mask, x86_cluster_flags, SD_INIT_NAME(CLS)
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_MC
|
||||
x86_topology[i++] = (struct sched_domain_topology_level){
|
||||
cpu_coregroup_mask, x86_core_flags, SD_INIT_NAME(MC)
|
||||
};
|
||||
#endif
|
||||
/*
|
||||
* When there is NUMA topology inside the package skip the PKG domain
|
||||
* since the NUMA domains will auto-magically create the right spanning
|
||||
* domains based on the SLIT.
|
||||
* When there is NUMA topology inside the package invalidate the
|
||||
* PKG domain since the NUMA domains will auto-magically create the
|
||||
* right spanning domains based on the SLIT.
|
||||
*/
|
||||
if (!x86_has_numa_in_package) {
|
||||
x86_topology[i++] = (struct sched_domain_topology_level){
|
||||
cpu_cpu_mask, x86_sched_itmt_flags, SD_INIT_NAME(PKG)
|
||||
};
|
||||
if (x86_has_numa_in_package) {
|
||||
unsigned int pkgdom = ARRAY_SIZE(x86_topology) - 2;
|
||||
|
||||
memset(&x86_topology[pkgdom], 0, sizeof(x86_topology[pkgdom]));
|
||||
}
|
||||
|
||||
/*
|
||||
* There must be one trailing NULL entry left.
|
||||
* Drop the SMT domains if there is only one thread per-core
|
||||
* since it'll get degenerated by the scheduler anyways.
|
||||
*/
|
||||
BUG_ON(i >= ARRAY_SIZE(x86_topology)-1);
|
||||
if (cpu_smt_num_threads <= 1)
|
||||
++topology;
|
||||
|
||||
set_sched_topology(x86_topology);
|
||||
set_sched_topology(topology);
|
||||
}
|
||||
|
||||
void set_cpu_sibling_map(int cpu)
|
||||
|
||||
@@ -187,11 +187,6 @@ static inline void arch_cpu_finalize_init(void) { }
|
||||
|
||||
void play_idle_precise(u64 duration_ns, u64 latency_ns);
|
||||
|
||||
static inline void play_idle(unsigned long duration_us)
|
||||
{
|
||||
play_idle_precise(duration_us * NSEC_PER_USEC, U64_MAX);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
void cpuhp_report_idle_dead(void);
|
||||
#else
|
||||
|
||||
@@ -369,8 +369,6 @@ static inline void preempt_notifier_init(struct preempt_notifier *notifier,
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/*
|
||||
* Migrate-Disable and why it is undesired.
|
||||
*
|
||||
@@ -429,13 +427,6 @@ static inline void preempt_notifier_init(struct preempt_notifier *notifier,
|
||||
extern void migrate_disable(void);
|
||||
extern void migrate_enable(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline void migrate_disable(void) { }
|
||||
static inline void migrate_enable(void) { }
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
/**
|
||||
* preempt_disable_nested - Disable preemption inside a normally preempt disabled section
|
||||
*
|
||||
|
||||
@@ -84,11 +84,9 @@ enum psi_aggregators {
|
||||
struct psi_group_cpu {
|
||||
/* 1st cacheline updated by the scheduler */
|
||||
|
||||
/* Aggregator needs to know of concurrent changes */
|
||||
seqcount_t seq ____cacheline_aligned_in_smp;
|
||||
|
||||
/* States of the tasks belonging to this group */
|
||||
unsigned int tasks[NR_PSI_TASK_COUNTS];
|
||||
unsigned int tasks[NR_PSI_TASK_COUNTS]
|
||||
____cacheline_aligned_in_smp;
|
||||
|
||||
/* Aggregate pressure state derived from the tasks */
|
||||
u32 state_mask;
|
||||
|
||||
+86
-62
@@ -34,6 +34,7 @@
|
||||
#include <linux/sched/prio.h>
|
||||
#include <linux/sched/types.h>
|
||||
#include <linux/signal_types.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/syscall_user_dispatch_types.h>
|
||||
#include <linux/mm_types_task.h>
|
||||
#include <linux/netdevice_xmit.h>
|
||||
@@ -395,15 +396,10 @@ enum uclamp_id {
|
||||
UCLAMP_CNT
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
extern struct root_domain def_root_domain;
|
||||
extern struct mutex sched_domains_mutex;
|
||||
extern void sched_domains_mutex_lock(void);
|
||||
extern void sched_domains_mutex_unlock(void);
|
||||
#else
|
||||
static inline void sched_domains_mutex_lock(void) { }
|
||||
static inline void sched_domains_mutex_unlock(void) { }
|
||||
#endif
|
||||
|
||||
struct sched_param {
|
||||
int sched_priority;
|
||||
@@ -584,7 +580,15 @@ struct sched_entity {
|
||||
u64 sum_exec_runtime;
|
||||
u64 prev_sum_exec_runtime;
|
||||
u64 vruntime;
|
||||
s64 vlag;
|
||||
union {
|
||||
/*
|
||||
* When !@on_rq this field is vlag.
|
||||
* When cfs_rq->curr == se (which implies @on_rq)
|
||||
* this field is vprot. See protect_slice().
|
||||
*/
|
||||
s64 vlag;
|
||||
u64 vprot;
|
||||
};
|
||||
u64 slice;
|
||||
|
||||
u64 nr_migrations;
|
||||
@@ -600,7 +604,6 @@ struct sched_entity {
|
||||
unsigned long runnable_weight;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* Per entity load average tracking.
|
||||
*
|
||||
@@ -608,7 +611,6 @@ struct sched_entity {
|
||||
* collide with read-mostly values above.
|
||||
*/
|
||||
struct sched_avg avg;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct sched_rt_entity {
|
||||
@@ -701,6 +703,7 @@ struct sched_dl_entity {
|
||||
unsigned int dl_defer : 1;
|
||||
unsigned int dl_defer_armed : 1;
|
||||
unsigned int dl_defer_running : 1;
|
||||
unsigned int dl_server_idle : 1;
|
||||
|
||||
/*
|
||||
* Bandwidth enforcement timer. Each -deadline task has its
|
||||
@@ -838,7 +841,6 @@ struct task_struct {
|
||||
struct alloc_tag *alloc_tag;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
int on_cpu;
|
||||
struct __call_single_node wake_entry;
|
||||
unsigned int wakee_flips;
|
||||
@@ -854,7 +856,6 @@ struct task_struct {
|
||||
*/
|
||||
int recent_used_cpu;
|
||||
int wake_cpu;
|
||||
#endif
|
||||
int on_rq;
|
||||
|
||||
int prio;
|
||||
@@ -913,9 +914,7 @@ struct task_struct {
|
||||
cpumask_t *user_cpus_ptr;
|
||||
cpumask_t cpus_mask;
|
||||
void *migration_pending;
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned short migration_disabled;
|
||||
#endif
|
||||
unsigned short migration_flags;
|
||||
|
||||
#ifdef CONFIG_PREEMPT_RCU
|
||||
@@ -947,10 +946,8 @@ struct task_struct {
|
||||
struct sched_info sched_info;
|
||||
|
||||
struct list_head tasks;
|
||||
#ifdef CONFIG_SMP
|
||||
struct plist_node pushable_tasks;
|
||||
struct rb_node pushable_dl_tasks;
|
||||
#endif
|
||||
|
||||
struct mm_struct *mm;
|
||||
struct mm_struct *active_mm;
|
||||
@@ -1234,10 +1231,7 @@ struct task_struct {
|
||||
struct rt_mutex_waiter *pi_blocked_on;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_MUTEXES
|
||||
/* Mutex deadlock detection: */
|
||||
struct mutex_waiter *blocked_on;
|
||||
#endif
|
||||
struct mutex *blocked_on; /* lock we're blocked on */
|
||||
|
||||
#ifdef CONFIG_DETECT_HUNG_TASK_BLOCKER
|
||||
/*
|
||||
@@ -1662,6 +1656,19 @@ struct task_struct {
|
||||
randomized_struct_fields_end
|
||||
} __attribute__ ((aligned (64)));
|
||||
|
||||
#ifdef CONFIG_SCHED_PROXY_EXEC
|
||||
DECLARE_STATIC_KEY_TRUE(__sched_proxy_exec);
|
||||
static inline bool sched_proxy_exec(void)
|
||||
{
|
||||
return static_branch_likely(&__sched_proxy_exec);
|
||||
}
|
||||
#else
|
||||
static inline bool sched_proxy_exec(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define TASK_REPORT_IDLE (TASK_REPORT + 1)
|
||||
#define TASK_REPORT_MAX (TASK_REPORT_IDLE << 1)
|
||||
|
||||
@@ -1776,12 +1783,8 @@ extern struct pid *cad_pid;
|
||||
|
||||
static __always_inline bool is_percpu_thread(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
return (current->flags & PF_NO_SETAFFINITY) &&
|
||||
(current->nr_cpus_allowed == 1);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Per-process atomic flags. */
|
||||
@@ -1846,7 +1849,6 @@ extern int cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpu
|
||||
extern int task_can_attach(struct task_struct *p);
|
||||
extern int dl_bw_alloc(int cpu, u64 dl_bw);
|
||||
extern void dl_bw_free(int cpu, u64 dl_bw);
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/* do_set_cpus_allowed() - consider using set_cpus_allowed_ptr() instead */
|
||||
extern void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask);
|
||||
@@ -1864,33 +1866,6 @@ extern void release_user_cpus_ptr(struct task_struct *p);
|
||||
extern int dl_task_check_affinity(struct task_struct *p, const struct cpumask *mask);
|
||||
extern void force_compatible_cpus_allowed_ptr(struct task_struct *p);
|
||||
extern void relax_compatible_cpus_allowed_ptr(struct task_struct *p);
|
||||
#else
|
||||
static inline void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
|
||||
{
|
||||
}
|
||||
static inline int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)
|
||||
{
|
||||
/* Opencoded cpumask_test_cpu(0, new_mask) to avoid dependency on cpumask.h */
|
||||
if ((*cpumask_bits(new_mask) & 1) == 0)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
static inline int dup_user_cpus_ptr(struct task_struct *dst, struct task_struct *src, int node)
|
||||
{
|
||||
if (src->user_cpus_ptr)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
static inline void release_user_cpus_ptr(struct task_struct *p)
|
||||
{
|
||||
WARN_ON(p->user_cpus_ptr);
|
||||
}
|
||||
|
||||
static inline int dl_task_check_affinity(struct task_struct *p, const struct cpumask *mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern int yield_to(struct task_struct *p, bool preempt);
|
||||
extern void set_user_nice(struct task_struct *p, long nice);
|
||||
@@ -1979,11 +1954,7 @@ extern int wake_up_state(struct task_struct *tsk, unsigned int state);
|
||||
extern int wake_up_process(struct task_struct *tsk);
|
||||
extern void wake_up_new_task(struct task_struct *tsk);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
extern void kick_process(struct task_struct *tsk);
|
||||
#else
|
||||
static inline void kick_process(struct task_struct *tsk) { }
|
||||
#endif
|
||||
|
||||
extern void __set_task_comm(struct task_struct *tsk, const char *from, bool exec);
|
||||
#define set_task_comm(tsk, from) ({ \
|
||||
@@ -2010,7 +1981,6 @@ extern void __set_task_comm(struct task_struct *tsk, const char *from, bool exec
|
||||
buf; \
|
||||
})
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static __always_inline void scheduler_ipi(void)
|
||||
{
|
||||
/*
|
||||
@@ -2020,9 +1990,6 @@ static __always_inline void scheduler_ipi(void)
|
||||
*/
|
||||
preempt_fold_need_resched();
|
||||
}
|
||||
#else
|
||||
static inline void scheduler_ipi(void) { }
|
||||
#endif
|
||||
|
||||
extern unsigned long wait_task_inactive(struct task_struct *, unsigned int match_state);
|
||||
|
||||
@@ -2165,6 +2132,67 @@ extern int __cond_resched_rwlock_write(rwlock_t *lock);
|
||||
__cond_resched_rwlock_write(lock); \
|
||||
})
|
||||
|
||||
#ifndef CONFIG_PREEMPT_RT
|
||||
static inline struct mutex *__get_task_blocked_on(struct task_struct *p)
|
||||
{
|
||||
struct mutex *m = p->blocked_on;
|
||||
|
||||
if (m)
|
||||
lockdep_assert_held_once(&m->wait_lock);
|
||||
return m;
|
||||
}
|
||||
|
||||
static inline void __set_task_blocked_on(struct task_struct *p, struct mutex *m)
|
||||
{
|
||||
WARN_ON_ONCE(!m);
|
||||
/* The task should only be setting itself as blocked */
|
||||
WARN_ON_ONCE(p != current);
|
||||
/* Currently we serialize blocked_on under the mutex::wait_lock */
|
||||
lockdep_assert_held_once(&m->wait_lock);
|
||||
/*
|
||||
* Check ensure we don't overwrite existing mutex value
|
||||
* with a different mutex. Note, setting it to the same
|
||||
* lock repeatedly is ok.
|
||||
*/
|
||||
WARN_ON_ONCE(p->blocked_on && p->blocked_on != m);
|
||||
p->blocked_on = m;
|
||||
}
|
||||
|
||||
static inline void set_task_blocked_on(struct task_struct *p, struct mutex *m)
|
||||
{
|
||||
guard(raw_spinlock_irqsave)(&m->wait_lock);
|
||||
__set_task_blocked_on(p, m);
|
||||
}
|
||||
|
||||
static inline void __clear_task_blocked_on(struct task_struct *p, struct mutex *m)
|
||||
{
|
||||
WARN_ON_ONCE(!m);
|
||||
/* Currently we serialize blocked_on under the mutex::wait_lock */
|
||||
lockdep_assert_held_once(&m->wait_lock);
|
||||
/*
|
||||
* There may be cases where we re-clear already cleared
|
||||
* blocked_on relationships, but make sure we are not
|
||||
* clearing the relationship with a different lock.
|
||||
*/
|
||||
WARN_ON_ONCE(m && p->blocked_on && p->blocked_on != m);
|
||||
p->blocked_on = NULL;
|
||||
}
|
||||
|
||||
static inline void clear_task_blocked_on(struct task_struct *p, struct mutex *m)
|
||||
{
|
||||
guard(raw_spinlock_irqsave)(&m->wait_lock);
|
||||
__clear_task_blocked_on(p, m);
|
||||
}
|
||||
#else
|
||||
static inline void __clear_task_blocked_on(struct task_struct *p, struct rt_mutex *m)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void clear_task_blocked_on(struct task_struct *p, struct rt_mutex *m)
|
||||
{
|
||||
}
|
||||
#endif /* !CONFIG_PREEMPT_RT */
|
||||
|
||||
static __always_inline bool need_resched(void)
|
||||
{
|
||||
return unlikely(tif_need_resched());
|
||||
@@ -2204,8 +2232,6 @@ extern bool sched_task_on_rq(struct task_struct *p);
|
||||
extern unsigned long get_wchan(struct task_struct *p);
|
||||
extern struct task_struct *cpu_curr_snapshot(int cpu);
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
/*
|
||||
* In order to reduce various lock holder preemption latencies provide an
|
||||
* interface to see if a vCPU is currently running or not.
|
||||
@@ -2228,7 +2254,6 @@ extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
|
||||
#define TASK_SIZE_OF(tsk) TASK_SIZE
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static inline bool owner_on_cpu(struct task_struct *owner)
|
||||
{
|
||||
/*
|
||||
@@ -2240,7 +2265,6 @@ static inline bool owner_on_cpu(struct task_struct *owner)
|
||||
|
||||
/* Returns effective CPU energy utilization, as seen by the scheduler */
|
||||
unsigned long sched_cpu_util(int cpu);
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
#ifdef CONFIG_SCHED_CORE
|
||||
extern void sched_core_free(struct task_struct *tsk);
|
||||
|
||||
@@ -29,15 +29,11 @@ static inline bool dl_time_before(u64 a, u64 b)
|
||||
return (s64)(a - b) < 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
struct root_domain;
|
||||
extern void dl_add_task_root_domain(struct task_struct *p);
|
||||
extern void dl_clear_root_domain(struct root_domain *rd);
|
||||
extern void dl_clear_root_domain_cpu(int cpu);
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
extern u64 dl_cookie;
|
||||
extern bool dl_bw_visited(int cpu, u64 cookie);
|
||||
|
||||
|
||||
@@ -11,11 +11,7 @@ enum cpu_idle_type {
|
||||
CPU_MAX_IDLE_TYPES
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
extern void wake_up_if_idle(int cpu);
|
||||
#else
|
||||
static inline void wake_up_if_idle(int cpu) { }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Idle thread specific functions to determine the need_resched
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* This is the interface between the scheduler and nohz/dynticks:
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
|
||||
#ifdef CONFIG_NO_HZ_COMMON
|
||||
extern void nohz_balance_enter_idle(int cpu);
|
||||
extern int get_nohz_timer_target(void);
|
||||
#else
|
||||
@@ -23,7 +23,7 @@ static inline void calc_load_nohz_remote(struct rq *rq) { }
|
||||
static inline void calc_load_nohz_stop(void) { }
|
||||
#endif /* CONFIG_NO_HZ_COMMON */
|
||||
|
||||
#if defined(CONFIG_NO_HZ_COMMON) && defined(CONFIG_SMP)
|
||||
#ifdef CONFIG_NO_HZ_COMMON
|
||||
extern void wake_up_nohz_cpu(int cpu);
|
||||
#else
|
||||
static inline void wake_up_nohz_cpu(int cpu) { }
|
||||
|
||||
@@ -153,14 +153,6 @@ SD_FLAG(SD_ASYM_PACKING, SDF_NEEDS_GROUPS)
|
||||
*/
|
||||
SD_FLAG(SD_PREFER_SIBLING, SDF_NEEDS_GROUPS)
|
||||
|
||||
/*
|
||||
* sched_groups of this level overlap
|
||||
*
|
||||
* SHARED_PARENT: Set for all NUMA levels above NODE.
|
||||
* NEEDS_GROUPS: Overlaps can only exist with more than one group.
|
||||
*/
|
||||
SD_FLAG(SD_OVERLAP, SDF_SHARED_PARENT | SDF_NEEDS_GROUPS)
|
||||
|
||||
/*
|
||||
* Cross-node balancing
|
||||
*
|
||||
|
||||
+10
-21
@@ -109,11 +109,7 @@ int kernel_wait(pid_t pid, int *stat);
|
||||
extern void free_task(struct task_struct *tsk);
|
||||
|
||||
/* sched_exec is called by processes performing an exec */
|
||||
#ifdef CONFIG_SMP
|
||||
extern void sched_exec(void);
|
||||
#else
|
||||
#define sched_exec() {}
|
||||
#endif
|
||||
|
||||
static inline struct task_struct *get_task_struct(struct task_struct *t)
|
||||
{
|
||||
@@ -135,24 +131,17 @@ static inline void put_task_struct(struct task_struct *t)
|
||||
return;
|
||||
|
||||
/*
|
||||
* In !RT, it is always safe to call __put_task_struct().
|
||||
* Under RT, we can only call it in preemptible context.
|
||||
*/
|
||||
if (!IS_ENABLED(CONFIG_PREEMPT_RT) || preemptible()) {
|
||||
static DEFINE_WAIT_OVERRIDE_MAP(put_task_map, LD_WAIT_SLEEP);
|
||||
|
||||
lock_map_acquire_try(&put_task_map);
|
||||
__put_task_struct(t);
|
||||
lock_map_release(&put_task_map);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* under PREEMPT_RT, we can't call put_task_struct
|
||||
* Under PREEMPT_RT, we can't call __put_task_struct
|
||||
* in atomic context because it will indirectly
|
||||
* acquire sleeping locks.
|
||||
* acquire sleeping locks. The same is true if the
|
||||
* current process has a mutex enqueued (blocked on
|
||||
* a PI chain).
|
||||
*
|
||||
* call_rcu() will schedule delayed_put_task_struct_rcu()
|
||||
* In !RT, it is always safe to call __put_task_struct().
|
||||
* Though, in order to simplify the code, resort to the
|
||||
* deferred call too.
|
||||
*
|
||||
* call_rcu() will schedule __put_task_struct_rcu_cb()
|
||||
* to be called in process context.
|
||||
*
|
||||
* __put_task_struct() is called when
|
||||
@@ -165,7 +154,7 @@ static inline void put_task_struct(struct task_struct *t)
|
||||
*
|
||||
* delayed_free_task() also uses ->rcu, but it is only called
|
||||
* when it fails to fork a process. Therefore, there is no
|
||||
* way it can conflict with put_task_struct().
|
||||
* way it can conflict with __put_task_struct().
|
||||
*/
|
||||
call_rcu(&t->rcu, __put_task_struct_rcu_cb);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
/*
|
||||
* sched-domains (multiprocessor balancing) declarations:
|
||||
*/
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/* Generate SD flag indexes */
|
||||
#define SD_FLAG(name, mflags) __##name,
|
||||
@@ -176,8 +175,6 @@ bool cpus_share_resources(int this_cpu, int that_cpu);
|
||||
typedef const struct cpumask *(*sched_domain_mask_f)(int cpu);
|
||||
typedef int (*sched_domain_flags_f)(void);
|
||||
|
||||
#define SDTL_OVERLAP 0x01
|
||||
|
||||
struct sd_data {
|
||||
struct sched_domain *__percpu *sd;
|
||||
struct sched_domain_shared *__percpu *sds;
|
||||
@@ -188,7 +185,6 @@ struct sd_data {
|
||||
struct sched_domain_topology_level {
|
||||
sched_domain_mask_f mask;
|
||||
sched_domain_flags_f sd_flags;
|
||||
int flags;
|
||||
int numa_level;
|
||||
struct sd_data data;
|
||||
char *name;
|
||||
@@ -197,39 +193,8 @@ struct sched_domain_topology_level {
|
||||
extern void __init set_sched_topology(struct sched_domain_topology_level *tl);
|
||||
extern void sched_update_asym_prefer_cpu(int cpu, int old_prio, int new_prio);
|
||||
|
||||
|
||||
# define SD_INIT_NAME(type) .name = #type
|
||||
|
||||
#else /* CONFIG_SMP */
|
||||
|
||||
struct sched_domain_attr;
|
||||
|
||||
static inline void
|
||||
partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
|
||||
struct sched_domain_attr *dattr_new)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool cpus_equal_capacity(int this_cpu, int that_cpu)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool cpus_share_cache(int this_cpu, int that_cpu)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool cpus_share_resources(int this_cpu, int that_cpu)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void sched_update_asym_prefer_cpu(int cpu, int old_prio, int new_prio)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_SMP */
|
||||
#define SDTL_INIT(maskfn, flagsfn, dname) ((struct sched_domain_topology_level) \
|
||||
{ .mask = maskfn, .sd_flags = flagsfn, .name = #dname })
|
||||
|
||||
#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)
|
||||
extern void rebuild_sched_domains_energy(void);
|
||||
|
||||
@@ -142,6 +142,9 @@ config RUSTC_HAS_SPAN_FILE
|
||||
config RUSTC_HAS_UNNECESSARY_TRANSMUTES
|
||||
def_bool RUSTC_VERSION >= 108800
|
||||
|
||||
config RUSTC_HAS_FILE_WITH_NUL
|
||||
def_bool RUSTC_VERSION >= 108900
|
||||
|
||||
config PAHOLE_VERSION
|
||||
int
|
||||
default $(shell,$(srctree)/scripts/pahole-version.sh $(PAHOLE))
|
||||
@@ -875,6 +878,18 @@ config UCLAMP_BUCKETS_COUNT
|
||||
|
||||
If in doubt, use the default value.
|
||||
|
||||
config SCHED_PROXY_EXEC
|
||||
bool "Proxy Execution"
|
||||
# Avoid some build failures w/ PREEMPT_RT until it can be fixed
|
||||
depends on !PREEMPT_RT
|
||||
# Need to investigate how to inform sched_ext of split contexts
|
||||
depends on !SCHED_CLASS_EXT
|
||||
# Not particularly useful until we get to multi-rq proxying
|
||||
depends on EXPERT
|
||||
help
|
||||
This option enables proxy execution, a mechanism for mutex-owning
|
||||
tasks to inherit the scheduling context of higher priority waiters.
|
||||
|
||||
endmenu
|
||||
|
||||
#
|
||||
|
||||
+1
-2
@@ -2127,9 +2127,8 @@ __latent_entropy struct task_struct *copy_process(
|
||||
lockdep_init_task(p);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_MUTEXES
|
||||
p->blocked_on = NULL; /* not blocked yet */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BCACHE
|
||||
p->sequential_io = 0;
|
||||
p->sequential_io_avg = 0;
|
||||
|
||||
@@ -53,17 +53,18 @@ void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
|
||||
{
|
||||
lockdep_assert_held(&lock->wait_lock);
|
||||
|
||||
/* Mark the current thread as blocked on the lock: */
|
||||
task->blocked_on = waiter;
|
||||
/* Current thread can't be already blocked (since it's executing!) */
|
||||
DEBUG_LOCKS_WARN_ON(__get_task_blocked_on(task));
|
||||
}
|
||||
|
||||
void debug_mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
|
||||
struct task_struct *task)
|
||||
{
|
||||
struct mutex *blocked_on = __get_task_blocked_on(task);
|
||||
|
||||
DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list));
|
||||
DEBUG_LOCKS_WARN_ON(waiter->task != task);
|
||||
DEBUG_LOCKS_WARN_ON(task->blocked_on != waiter);
|
||||
task->blocked_on = NULL;
|
||||
DEBUG_LOCKS_WARN_ON(blocked_on && blocked_on != lock);
|
||||
|
||||
INIT_LIST_HEAD(&waiter->list);
|
||||
waiter->task = NULL;
|
||||
|
||||
@@ -644,6 +644,7 @@ __mutex_lock_common(struct mutex *lock, unsigned int state, unsigned int subclas
|
||||
goto err_early_kill;
|
||||
}
|
||||
|
||||
__set_task_blocked_on(current, lock);
|
||||
set_current_state(state);
|
||||
trace_contention_begin(lock, LCB_F_MUTEX);
|
||||
for (;;) {
|
||||
@@ -680,6 +681,12 @@ __mutex_lock_common(struct mutex *lock, unsigned int state, unsigned int subclas
|
||||
|
||||
first = __mutex_waiter_is_first(lock, &waiter);
|
||||
|
||||
/*
|
||||
* As we likely have been woken up by task
|
||||
* that has cleared our blocked_on state, re-set
|
||||
* it to the lock we are trying to acquire.
|
||||
*/
|
||||
set_task_blocked_on(current, lock);
|
||||
set_current_state(state);
|
||||
/*
|
||||
* Here we order against unlock; we must either see it change
|
||||
@@ -691,8 +698,15 @@ __mutex_lock_common(struct mutex *lock, unsigned int state, unsigned int subclas
|
||||
|
||||
if (first) {
|
||||
trace_contention_begin(lock, LCB_F_MUTEX | LCB_F_SPIN);
|
||||
/*
|
||||
* mutex_optimistic_spin() can call schedule(), so
|
||||
* clear blocked on so we don't become unselectable
|
||||
* to run.
|
||||
*/
|
||||
clear_task_blocked_on(current, lock);
|
||||
if (mutex_optimistic_spin(lock, ww_ctx, &waiter))
|
||||
break;
|
||||
set_task_blocked_on(current, lock);
|
||||
trace_contention_begin(lock, LCB_F_MUTEX);
|
||||
}
|
||||
|
||||
@@ -700,6 +714,7 @@ __mutex_lock_common(struct mutex *lock, unsigned int state, unsigned int subclas
|
||||
}
|
||||
raw_spin_lock_irqsave(&lock->wait_lock, flags);
|
||||
acquired:
|
||||
__clear_task_blocked_on(current, lock);
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
if (ww_ctx) {
|
||||
@@ -729,9 +744,11 @@ skip_wait:
|
||||
return 0;
|
||||
|
||||
err:
|
||||
__clear_task_blocked_on(current, lock);
|
||||
__set_current_state(TASK_RUNNING);
|
||||
__mutex_remove_waiter(lock, &waiter);
|
||||
err_early_kill:
|
||||
WARN_ON(__get_task_blocked_on(current));
|
||||
trace_contention_end(lock, ret);
|
||||
raw_spin_unlock_irqrestore_wake(&lock->wait_lock, flags, &wake_q);
|
||||
debug_mutex_free_waiter(&waiter);
|
||||
@@ -942,6 +959,7 @@ static noinline void __sched __mutex_unlock_slowpath(struct mutex *lock, unsigne
|
||||
next = waiter->task;
|
||||
|
||||
debug_mutex_wake_waiter(lock, waiter);
|
||||
__clear_task_blocked_on(next, lock);
|
||||
wake_q_add(&wake_q, next);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_PREEMPT_RT
|
||||
/*
|
||||
* This is the control structure for tasks blocked on mutex, which resides
|
||||
* on the blocked task's kernel stack:
|
||||
@@ -70,3 +70,4 @@ extern void debug_mutex_init(struct mutex *lock, const char *name,
|
||||
# define debug_mutex_unlock(lock) do { } while (0)
|
||||
# define debug_mutex_init(lock, name, key) do { } while (0)
|
||||
#endif /* !CONFIG_DEBUG_MUTEXES */
|
||||
#endif /* CONFIG_PREEMPT_RT */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user