From: Tim Chen <tim.c.chen@linux.intel.com>
To: Peter Zijlstra <peterz@infradead.org>, Ingo Molnar <mingo@redhat.com>
Cc: Tim Chen <tim.c.chen@linux.intel.com>,
Juri Lelli <juri.lelli@redhat.com>,
Vincent Guittot <vincent.guittot@linaro.org>,
Dietmar Eggemann <dietmar.eggemann@arm.com>,
Steven Rostedt <rostedt@goodmis.org>,
Ben Segall <bsegall@google.com>, Mel Gorman <mgorman@suse.de>,
Valentin Schneider <vschneid@redhat.com>,
K Prateek Nayak <kprateek.nayak@amd.com>,
Kees Cook <kees@kernel.org>,
Christian Brauner <brauner@kernel.org>,
Alexander Viro <viro@zeniv.linux.org.uk>, Jan Kara <jack@suse.cz>,
Shrikanth Hegde <sshegde@linux.ibm.com>,
Qais Yousef <qyousef@layalina.io>,
Aaron Lu <ziqianlu@bytedance.com>,
Srikar Dronamraju <srikar@linux.ibm.com>,
Vineeth Remanan Pillai <vineethr@linux.ibm.com>,
Ricardo Neri-Calderon <ricardo.neri-calderon@linux.intel.com>,
Chen Yu <yu.c.chen@intel.com>, Lu Wang <wanglu.priv@gmail.com>,
Hyunwoo Kim <imv4bel@gmail.com>,
Zhan Xusheng <zhanxusheng@xiaomi.com>,
Zhan Xusheng <zhanxusheng1024@gmail.com>,
Yi Lai <yi1.lai@intel.com>,
"Rafael J . Wysocki" <rafael.j.wysocki@intel.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Danilo Krummrich <dakr@kernel.org>,
Zenghui Yu <zenghui.yu@linux.dev>,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
linux-fsdevel@vger.kernel.org, stable@kernel.org
Subject: [PATCH v2 4/6] sched/cache: Introduce task_struct->sched_cache_grp
Date: Mon, 21 Sep 2026 17:37:25 -0700 [thread overview]
Message-ID: <ae7081dc54736bf115215f9867abb2711a7403fb.1790035273.git.tim.c.chen@linux.intel.com> (raw)
In-Reply-To: <cover.1790035273.git.tim.c.chen@linux.intel.com>
Add a sched_cache_grp pointer to task_struct so that scheduler code
can access the cache group directly via the task, without going
through mm->sched_cache_grp. This decouples the scheduler's hot-path
accesses from the mm_struct.
Each task holds its own refcount on the sched_cache_group, separate
from the reference held by its mm_struct. The reference is acquired
in copy_mm() (fork) and exec_mmap() (exec), and released in exit_mm().
This fixes the use-after-free when account_mm_sched() reaches the group
through a task whose mm is being switched, as reported by Hyunwoo:
https://lore.kernel.org/lkml/apPb-Dr4nPYuHQOK@v4bel/
Convert all scheduler code in fair.c and exit.c to use
p->sched_cache_grp instead of p->mm->sched_cache_grp.
Keep the fork/exec/exit reference management out of the generic mm
paths: add sched_cache_fork(), sched_cache_fork_cleanup(),
sched_cache_exec_mmap() and sched_cache_exit_mm() in
kernel/sched/cache_sched.c (with empty stubs for !CONFIG_SCHED_CACHE),
so fs/exec.c, kernel/fork.c and kernel/exit.c each call one helper
instead of open-coding the refcounting under #ifdef. Also add
sched_cache_group_get() and task_cache_group_get().
Fixes: df0d98475954 ("sched/cache: Introduce infrastructure for cache-aware load balancing")
Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
Closes: https://lore.kernel.org/lkml/apPb-Dr4nPYuHQOK@v4bel/
Reported-by: Zenghui Yu (Huawei) <zenghui.yu@linux.dev>
Closes: https://lore.kernel.org/all/343a7e07-7fad-4979-9c9b-82ec038c293c@linux.dev/
Cc: stable@kernel.org #7.2.x
Co-developed-by: Chen Yu <yu.c.chen@intel.com>
Signed-off-by: Chen Yu <yu.c.chen@intel.com>
Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com>
---
fs/exec.c | 1 +
include/linux/sched.h | 13 +++++
kernel/exit.c | 33 +-----------
kernel/fork.c | 2 +
kernel/sched/cache_sched.c | 87 ++++++++++++++++++++++++++++++
kernel/sched/fair.c | 106 ++++++++++++++++---------------------
kernel/sched/sched.h | 3 ++
7 files changed, 153 insertions(+), 92 deletions(-)
diff --git a/fs/exec.c b/fs/exec.c
index 745f6eb5279e..6400bae97a32 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -882,6 +882,7 @@ static int exec_mmap(struct linux_binprm *bprm)
active_mm = tsk->active_mm;
tsk->active_mm = mm;
tsk->mm = mm;
+ sched_cache_exec_mmap(tsk, mm);
mm_init_cid(mm, tsk);
exec_state = task_exec_state_replace(tsk, exec_state);
/*
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 1f254364f216..1aa81cb6637b 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1434,6 +1434,7 @@ struct task_struct {
#ifdef CONFIG_SCHED_CACHE
struct callback_head cache_work;
int preferred_llc;
+ struct sched_cache_group __rcu *sched_cache_grp;
/* 1: task was enqueued to its preferred LLC, 0 otherwise */
int pref_llc_queued;
#endif
@@ -2418,11 +2419,23 @@ struct sched_cache_group {
} ____cacheline_aligned_in_smp;
void sched_cache_group_put(struct sched_cache_group *grp);
+struct sched_cache_group *sched_cache_group_get(struct sched_cache_group *grp);
+struct sched_cache_group *task_cache_group_get(struct task_struct *p);
+
+void sched_cache_fork(struct task_struct *p);
+void sched_cache_fork_cleanup(struct task_struct *p);
+void sched_cache_exec_mmap(struct task_struct *p, struct mm_struct *mm);
+void sched_cache_exit_mm(struct task_struct *p);
#else
struct sched_cache_group { };
+static inline void sched_cache_fork(struct task_struct *p) { }
+static inline void sched_cache_fork_cleanup(struct task_struct *p) { }
+static inline void sched_cache_exec_mmap(struct task_struct *p, struct mm_struct *mm) { }
+static inline void sched_cache_exit_mm(struct task_struct *p) { }
+
#endif
#ifndef MODULE
diff --git a/kernel/exit.c b/kernel/exit.c
index 16abbe1cf682..35afa1d2d251 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -547,37 +547,6 @@ void mm_update_next_owner(struct mm_struct *mm)
}
#endif /* CONFIG_MEMCG */
-#if defined(CONFIG_SCHED_CACHE) && defined(CONFIG_NUMA_BALANCING)
-/*
- * Subtract the memory footprint of the current task from
- * mm.
- */
-static void exit_mm_sched_cache(struct mm_struct *mm)
-{
- struct sched_cache_group *grp;
- unsigned long fp, sub;
-
- if (!current->total_numa_faults)
- return;
- /*
- * No lock protection due to performance considerations.
- * Make sure the group footprint does not become
- * negative.
- */
- grp = READ_ONCE(mm->sched_cache_grp);
- if (!grp)
- return;
-
- fp = READ_ONCE(grp->footprint);
- sub = min(fp, current->total_numa_faults);
- WRITE_ONCE(grp->footprint, fp - sub);
-}
-#else
-static inline void exit_mm_sched_cache(struct mm_struct *mm)
-{
-}
-#endif /* CONFIG_SCHED_CACHE CONFIG_NUMA_BALANCING */
-
/*
* Turn us into a lazy TLB process if we
* aren't already..
@@ -590,7 +559,7 @@ static void exit_mm(void)
if (!mm)
return;
- exit_mm_sched_cache(mm);
+ sched_cache_exit_mm(current);
mmap_read_lock(mm);
mmgrab_lazy_tlb(mm);
diff --git a/kernel/fork.c b/kernel/fork.c
index 416758c8a3d4..d9b263a32471 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1599,6 +1599,7 @@ static int copy_mm(u64 clone_flags, struct task_struct *tsk)
tsk->mm = mm;
tsk->active_mm = mm;
+ sched_cache_fork(tsk);
return 0;
}
@@ -2599,6 +2600,7 @@ __latent_entropy struct task_struct *copy_process(
bad_fork_cleanup_namespaces:
exit_nsproxy_namespaces(p);
bad_fork_cleanup_mm:
+ sched_cache_fork_cleanup(p);
if (p->mm) {
mm_clear_owner(p->mm, p);
mmput(p->mm);
diff --git a/kernel/sched/cache_sched.c b/kernel/sched/cache_sched.c
index ff3d9538e7a4..7c5d23a1e09c 100644
--- a/kernel/sched/cache_sched.c
+++ b/kernel/sched/cache_sched.c
@@ -1,6 +1,93 @@
// SPDX-License-Identifier: GPL-2.0-only
#include "sched.h"
+#define rcu_deref_sched_cache_grp(tsk) \
+ rcu_dereference_check((tsk)->sched_cache_grp, (tsk) == current)
+
+static struct sched_cache_group *sched_cache_replace_grp(struct task_struct *p,
+ struct sched_cache_group *new)
+{
+ struct sched_cache_group *old;
+
+ old = rcu_deref_sched_cache_grp(p);
+ rcu_assign_pointer(p->sched_cache_grp, new);
+
+ return old;
+}
+
+struct sched_cache_group *sched_cache_group_get(struct sched_cache_group *grp)
+{
+ /*
+ * refcount_inc_not_zero() is the acquire primitive for lockless
+ * (RCU) lookups; plain refcount_inc() would scribble the count if
+ * it already reached zero. Return NULL in that case.
+ */
+ if (grp && !refcount_inc_not_zero(&grp->refcnt))
+ grp = NULL;
+
+ return grp;
+}
+
+struct sched_cache_group *task_cache_group_get(struct task_struct *p)
+{
+ guard(rcu)();
+ return sched_cache_group_get(rcu_dereference(p->sched_cache_grp));
+}
+
+void sched_cache_fork(struct task_struct *p)
+{
+ /*
+ * The child takes its own reference on the mm's cache group, separate
+ * from the reference held by the mm. @p is not yet visible to readers,
+ * so a plain initializing store is enough.
+ */
+ RCU_INIT_POINTER(p->sched_cache_grp,
+ sched_cache_group_get(p->mm->sched_cache_grp));
+}
+
+void sched_cache_fork_cleanup(struct task_struct *p)
+{
+ /*
+ * A fork that fails after sched_cache_fork() never reaches exit_mm(),
+ * so drop the reference here. @p never became visible, so there are no
+ * concurrent readers and the reference we hold keeps the group alive.
+ */
+ sched_cache_group_put(rcu_access_pointer(p->sched_cache_grp));
+ RCU_INIT_POINTER(p->sched_cache_grp, NULL);
+}
+
+void sched_cache_exec_mmap(struct task_struct *p, struct mm_struct *mm)
+{
+ struct sched_cache_group *old;
+
+ /*
+ * Acquire the new reference before publishing the pointer, then drop
+ * the old one. @p is current and the only writer of its own pointer.
+ */
+ old = sched_cache_replace_grp(p, sched_cache_group_get(mm->sched_cache_grp));
+ sched_cache_group_put(old);
+}
+
+void sched_cache_exit_mm(struct task_struct *p)
+{
+ struct sched_cache_group *grp = sched_cache_replace_grp(p, NULL);
+
+#ifdef CONFIG_NUMA_BALANCING
+ /*
+ * Subtract this task's footprint from the group before dropping the
+ * reference, so the group footprint converges as its threads exit.
+ * Unlocked for performance; clamp to avoid underflow.
+ */
+ if (grp && p->total_numa_faults) {
+ unsigned long fp = READ_ONCE(grp->footprint);
+ unsigned long sub = min(fp, p->total_numa_faults);
+
+ WRITE_ONCE(grp->footprint, fp - sub);
+ }
+#endif
+ sched_cache_group_put(grp);
+}
+
static void sched_cache_group_free_rcu(struct rcu_head *rcu)
{
struct sched_cache_group *grp =
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 6e939807dff2..3e2d236be2a3 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -1483,7 +1483,7 @@ static inline int get_sched_cache_scale(int mul)
return (1 + (tol - 1) * mul);
}
-static bool exceed_llc_capacity(struct mm_struct *mm, int cpu)
+static bool exceed_llc_capacity(struct sched_cache_group *grp, int cpu)
{
#ifdef CONFIG_NUMA_BALANCING
unsigned long llc, footprint;
@@ -1497,11 +1497,6 @@ static bool exceed_llc_capacity(struct mm_struct *mm, int cpu)
return true;
if (static_branch_likely(&sched_numa_balancing)) {
- struct sched_cache_group *grp = READ_ONCE(mm->sched_cache_grp);
-
- if (!grp)
- return true;
-
/*
* TBD: RDT exclusive LLC ways reserved should be
* excluded.
@@ -1536,10 +1531,9 @@ static bool exceed_llc_capacity(struct mm_struct *mm, int cpu)
return false;
}
-static bool invalid_llc_nr(struct mm_struct *mm, struct task_struct *p,
+static bool invalid_llc_nr(struct sched_cache_group *grp, struct task_struct *p,
int cpu)
{
- struct sched_cache_group *grp;
int scale;
if (get_nr_threads(p) <= 1)
@@ -1553,10 +1547,6 @@ static bool invalid_llc_nr(struct mm_struct *mm, struct task_struct *p,
if (scale == INT_MAX)
return false;
- grp = READ_ONCE(mm->sched_cache_grp);
- if (!grp)
- return true;
-
return !fits_capacity((READ_ONCE(grp->nr_running_avg) * cpu_smt_num_threads),
(scale * per_cpu(sd_llc_size, cpu)));
}
@@ -1765,15 +1755,10 @@ static unsigned long fraction_mm_sched(struct rq *rq,
return div64_u64(NICE_0_LOAD * pcpu_sched->runtime, rq->cpu_runtime + 1);
}
-static int get_pref_llc(struct task_struct *p, struct mm_struct *mm)
+static int get_pref_llc(struct task_struct *p, struct sched_cache_group *grp)
{
int mm_sched_llc = -1, mm_sched_cpu;
- struct sched_cache_group *grp;
- if (!mm)
- return -1;
-
- grp = READ_ONCE(mm->sched_cache_grp);
if (!grp)
return -1;
@@ -1807,9 +1792,8 @@ static unsigned int task_running_on_cpu(int cpu, struct task_struct *p);
static inline
void account_mm_sched(struct rq *rq, struct task_struct *p, s64 delta_exec)
{
+ struct sched_cache_group *grp = rcu_dereference_all(p->sched_cache_grp);
struct sched_cache_time *pcpu_sched;
- struct sched_cache_group *grp;
- struct mm_struct *mm = p->mm;
int mm_sched_llc = -1;
unsigned long epoch;
@@ -1820,12 +1804,8 @@ void account_mm_sched(struct rq *rq, struct task_struct *p, s64 delta_exec)
return;
/*
* init_task, kthreads and user thread created
- * by user_mode_thread() don't have mm.
+ * by user_mode_thread() don't have a cache group.
*/
- if (!mm)
- return;
-
- grp = READ_ONCE(mm->sched_cache_grp);
if (!grp || !grp->pcpu_sched)
return;
@@ -1843,13 +1823,13 @@ void account_mm_sched(struct rq *rq, struct task_struct *p, s64 delta_exec)
* its preferred state.
*/
if ((long)(epoch - READ_ONCE(grp->epoch)) > llc_epoch_affinity_timeout ||
- invalid_llc_nr(mm, p, cpu_of(rq)) ||
- exceed_llc_capacity(mm, cpu_of(rq))) {
+ invalid_llc_nr(grp, p, cpu_of(rq)) ||
+ exceed_llc_capacity(grp, cpu_of(rq))) {
if (READ_ONCE(grp->cpu) != -1)
WRITE_ONCE(grp->cpu, -1);
}
- mm_sched_llc = get_pref_llc(p, mm);
+ mm_sched_llc = get_pref_llc(p, grp);
/* task not on rq accounted later in account_entity_enqueue() */
if (task_running_on_cpu(rq->cpu, p) &&
@@ -1862,19 +1842,15 @@ void account_mm_sched(struct rq *rq, struct task_struct *p, s64 delta_exec)
static void task_tick_cache(struct rq *rq, struct task_struct *p)
{
+ struct sched_cache_group *grp = rcu_dereference_all(p->sched_cache_grp);
struct callback_head *work = &p->cache_work;
- struct sched_cache_group *grp;
- struct mm_struct *mm = p->mm;
unsigned long epoch;
if (!sched_cache_enabled())
return;
- if (!mm || p->flags & PF_KTHREAD)
- return;
-
- grp = READ_ONCE(mm->sched_cache_grp);
- if (!grp || !grp->pcpu_sched)
+ if (!grp || p->flags & PF_KTHREAD ||
+ !grp->pcpu_sched)
return;
epoch = rq->cpu_epoch;
@@ -1956,14 +1932,13 @@ static inline void update_avg_scale(u64 *avg, u64 sample)
static void task_cache_work(struct callback_head *work)
{
+ struct sched_cache_group *grp __free(sched_cache_group_put) = NULL;
+ cpumask_var_t cpus __free(free_cpumask_var) = CPUMASK_VAR_NULL;
int cpu, m_a_cpu = -1, nr_running = 0, curr_cpu;
unsigned long next_scan, now = jiffies;
struct task_struct *p = current, *cur;
unsigned long curr_m_a_occ = 0;
- struct sched_cache_group *grp;
- struct mm_struct *mm = p->mm;
unsigned long m_a_occ = 0;
- cpumask_var_t cpus;
WARN_ON_ONCE(work != &p->cache_work);
@@ -1972,7 +1947,12 @@ static void task_cache_work(struct callback_head *work)
if (p->flags & PF_EXITING)
return;
- grp = READ_ONCE(mm->sched_cache_grp);
+ /*
+ * A reference makes sure grp is not released by others. The rcu
+ * lock can not be held till after zalloc_cpumask_var() below,
+ * because the latter might sleep.
+ */
+ grp = task_cache_group_get(p);
if (!grp)
return;
@@ -1987,8 +1967,8 @@ static void task_cache_work(struct callback_head *work)
return;
curr_cpu = task_cpu(p);
- if (invalid_llc_nr(mm, p, curr_cpu) ||
- exceed_llc_capacity(mm, curr_cpu)) {
+ if (invalid_llc_nr(grp, p, curr_cpu) ||
+ exceed_llc_capacity(grp, curr_cpu)) {
if (READ_ONCE(grp->cpu) != -1)
WRITE_ONCE(grp->cpu, -1);
@@ -2021,9 +2001,13 @@ static void task_cache_work(struct callback_head *work)
m_cpu = i;
}
+ /*
+ * rcu_access_pointer() is used because the
+ * pointer is only compared, never dereferenced.
+ */
cur = rcu_dereference_all(cpu_rq(i)->curr);
if (cur && !(cur->flags & (PF_EXITING | PF_KTHREAD)) &&
- cur->mm == mm)
+ rcu_access_pointer(cur->sched_cache_grp) == grp)
nr_running++;
}
@@ -2069,7 +2053,6 @@ static void task_cache_work(struct callback_head *work)
}
update_avg_scale(&grp->nr_running_avg, nr_running);
- free_cpumask_var(cpus);
}
void init_sched_mm(struct task_struct *p)
@@ -2078,6 +2061,13 @@ void init_sched_mm(struct task_struct *p)
init_task_work(work, task_cache_work);
work->next = work;
+ /*
+ * dup_task_struct() copies the parent's task_struct, including its
+ * sched_cache_grp, for which the child holds no reference. Clear it
+ * here - before copy_mm() runs - so the child never carries a
+ * borrowed pointer that the fork error path would put.
+ */
+ RCU_INIT_POINTER(p->sched_cache_grp, NULL);
/*
* Reset new task's preference to avoid
* polluting account_llc_enqueue().
@@ -3878,10 +3868,9 @@ static void task_numa_placement(struct task_struct *p)
* heuristic and occasional lost updates are tolerable.
*
* If a task exits, its corresponding footprint must
- * be subtracted from the mm->sched_cache_grp->footprint,
- * otherwise the mm->sched_cache_grp->footprint will not
- * converge: the exiting thread's footprint remains
- * unchanged/undecayed in mm->sched_cache_grp->footprint.
+ * be subtracted from p->sched_cache_grp->footprint,
+ * otherwise the footprint will not converge: the
+ * exiting thread's footprint remains unchanged/undecayed.
* See exit_mm().
*
* Lost updates and unsynchronized subtraction
@@ -3889,12 +3878,14 @@ static void task_numa_placement(struct task_struct *p)
* go negative. Clamp to zero to prevent the
* unsigned footprint from wrapping.
*/
- grp = READ_ONCE(p->mm->sched_cache_grp);
- if (!grp)
- continue;
+ scoped_guard(rcu) {
+ grp = rcu_dereference(p->sched_cache_grp);
- new_fp = (long)READ_ONCE(grp->footprint) + diff;
- WRITE_ONCE(grp->footprint, max(new_fp, 0L));
+ if (grp) {
+ new_fp = (long)READ_ONCE(grp->footprint) + diff;
+ WRITE_ONCE(grp->footprint, max(new_fp, 0L));
+ }
+ }
#endif
}
@@ -10843,7 +10834,6 @@ static enum llc_mig can_migrate_llc_task(struct lb_env *env,
struct task_struct *p)
{
struct sched_cache_group *grp;
- struct mm_struct *mm;
bool to_pref;
int cpu, src_cpu, dst_cpu;
@@ -10852,11 +10842,7 @@ static enum llc_mig can_migrate_llc_task(struct lb_env *env,
src_cpu = env->src_cpu;
dst_cpu = env->dst_cpu;
- mm = p->mm;
- if (!mm)
- return mig_unrestricted;
-
- grp = READ_ONCE(mm->sched_cache_grp);
+ grp = rcu_dereference_all(p->sched_cache_grp);
if (!grp)
return mig_unrestricted;
@@ -10865,8 +10851,8 @@ static enum llc_mig can_migrate_llc_task(struct lb_env *env,
return mig_unrestricted;
/* skip cache aware load balance for too many threads */
- if (invalid_llc_nr(mm, p, dst_cpu) ||
- exceed_llc_capacity(mm, dst_cpu)) {
+ if (invalid_llc_nr(grp, p, dst_cpu) ||
+ exceed_llc_capacity(grp, dst_cpu)) {
if (READ_ONCE(grp->cpu) != -1)
WRITE_ONCE(grp->cpu, -1);
return mig_unrestricted;
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index e656c7059bf8..8b67af28a471 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -4145,6 +4145,9 @@ static inline bool sched_cache_enabled(void)
return static_branch_unlikely(&sched_cache_active);
}
+DEFINE_FREE(sched_cache_group_put, struct sched_cache_group *,
+ sched_cache_group_put(_T));
+
extern void sched_cache_active_set(void);
#endif
--
2.32.0
next prev parent reply other threads:[~2026-09-22 0:32 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-22 0:37 [PATCH v2 0/6] sched/cache: Fixes for cache aware scheduling Tim Chen
2026-09-22 0:37 ` [PATCH v2 1/6] sched/cache: Keep nr_pref_llc_running in the runnable domain Tim Chen
2026-09-22 7:22 ` Peter Zijlstra
2026-09-22 8:25 ` Chen, Yu C
2026-09-22 8:28 ` Peter Zijlstra
2026-09-22 0:37 ` [PATCH v2 2/6] sched/cache: Honor migrate_llc_task semantics in active load balance Tim Chen
2026-09-22 7:23 ` Peter Zijlstra
2026-09-22 8:30 ` Chen, Yu C
2026-09-22 0:37 ` [PATCH v2 3/6] sched/cache: Decouple sched_cache_group from mm Tim Chen
2026-09-22 0:37 ` Tim Chen [this message]
2026-09-22 0:37 ` [PATCH v2 5/6] sched/cache: Skip kernel thread for cache aware scheduling Tim Chen
2026-09-22 0:37 ` [PATCH v2 6/6] sched/cache: Refresh LLC capacity across CPU hotplug Tim Chen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ae7081dc54736bf115215f9867abb2711a7403fb.1790035273.git.tim.c.chen@linux.intel.com \
--to=tim.c.chen@linux.intel.com \
--cc=brauner@kernel.org \
--cc=bsegall@google.com \
--cc=dakr@kernel.org \
--cc=dietmar.eggemann@arm.com \
--cc=gregkh@linuxfoundation.org \
--cc=imv4bel@gmail.com \
--cc=jack@suse.cz \
--cc=juri.lelli@redhat.com \
--cc=kees@kernel.org \
--cc=kprateek.nayak@amd.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mgorman@suse.de \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=qyousef@layalina.io \
--cc=rafael.j.wysocki@intel.com \
--cc=ricardo.neri-calderon@linux.intel.com \
--cc=rostedt@goodmis.org \
--cc=srikar@linux.ibm.com \
--cc=sshegde@linux.ibm.com \
--cc=stable@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=vineethr@linux.ibm.com \
--cc=viro@zeniv.linux.org.uk \
--cc=vschneid@redhat.com \
--cc=wanglu.priv@gmail.com \
--cc=yi1.lai@intel.com \
--cc=yu.c.chen@intel.com \
--cc=zenghui.yu@linux.dev \
--cc=zhanxusheng1024@gmail.com \
--cc=zhanxusheng@xiaomi.com \
--cc=ziqianlu@bytedance.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®