[RFC PATCH 0/7] sched/cache: Per-task control of cache aware scheduling via prctl

Tim Chen posted 7 patches 4 weeks ago
.../admin-guide/kernel-parameters.txt         |   3 +
Documentation/scheduler/index.rst             |   1 +
Documentation/scheduler/sched-cache.rst       | 175 ++++++++
fs/exec.c                                     |  24 ++
include/linux/mm_types.h                      |  15 +-
include/linux/sched.h                         |  18 +-
include/uapi/linux/prctl.h                    |   9 +
kernel/exit.c                                 |  35 +-
kernel/fork.c                                 |  38 ++
kernel/sched/build_utility.c                  |   4 +
kernel/sched/cache_sched.c                    | 374 ++++++++++++++++++
kernel/sched/debug.c                          |  63 ++-
kernel/sched/fair.c                           | 188 +++++----
kernel/sched/sched.h                          |  24 +-
kernel/sched/topology.c                       |  32 +-
kernel/sys.c                                  |   5 +
16 files changed, 895 insertions(+), 113 deletions(-)
create mode 100644 Documentation/scheduler/sched-cache.rst
create mode 100644 kernel/sched/cache_sched.c
[RFC PATCH 0/7] sched/cache: Per-task control of cache aware scheduling via prctl
Posted by Tim Chen 4 weeks ago
Hi all,

Cache aware scheduling today groups tasks by their mm: the LLC aggregation
target lives in mm_struct, so the address space is the unit of grouping.
That works, but in some scenarios that is too coarse and too eager, and the
only knob we have over it is a single system-wide debugfs switch.

It's too coarse because plenty of workloads share data across cooperating
*processes* rather than threads - a database with a process per connection,
a browser with a renderer per site, a server and its worker helpers. They
pass data through shm or pipes and would love to be pulled onto the same
LLC, but they never share an mm, so today they can't be. And it's too eager
in the other direction: a process whose threads don't actually share
anything gets aggregated anyway, just because they happen to sit in one
address space.

So the core idea of this series is simple: allow other groupings than
the mm, make the grouping an object in its own right, and let user space
say "put these tasks together" explicitly.

What the series does
====================

Patches 1-3 are pure preparation, no behavior change. They turn the
per-mm statistics into a standalone, refcounted sched_cache_group, reach
it from task_struct instead of from p->mm, and pull the allocation out into
a helper. Once the group stands on its own, membership no longer has to
follow the mm address space.

Patch 4 adds the actual interface:

    int prctl(PR_SCHED_CACHE, subop, pid, arg4, pid_type);

    PR_SCHED_CACHE_GET         read back a task's (obfuscated) cookie id
    PR_SCHED_CACHE_CREATE      create a fresh group and install it
    PR_SCHED_CACHE_SHARE_FROM  copy the group of arg4 onto pid
    PR_SCHED_CACHE_DISABLE     opt this group out of LLC aggregation
    PR_SCHED_CACHE_ENABLE      opt it back in

'pid' is the task the operation applies to, with 0 meaning the caller, and
'pid_type' picks whether we touch just the thread, the whole thread group,
or the process group. Permissions follow core scheduling: every task we
touch has to pass ptrace_may_access(PTRACE_MODE_READ_REALCREDS), and for
the group scopes we check *all* of them before changing *any* of them, so
the operation is all-or-nothing.

Two subops need a word on their fourth argument:

  - GET writes the cookie id to arg4, which is a u64 __user * and must be
    8-byte aligned (misaligned pointers are rejected with -EINVAL). As in
    core scheduling the value handed out is an obfuscated hash of the
    kernel object, not a real pointer or a user-supplied number.

  - SHARE_FROM reads arg4 as the *source* pid and copies its group onto
    'pid'. CREATE is deliberately not idempotent - it always allocates a
    new group - so a caller that wants many tasks in one group does CREATE
    once and SHARE_FROM for the rest.

Patches 5-6 build on that. Patch 5 wires up DISABLE/ENABLE, and patch 6
turns the old debugfs boolean into a THP-style always/advise/never mode so
that the system policy and the per-task hint compose the same way THP's do:
'always' aggregates regardless of the per-task hint, 'advise' honors it,
'never' turns the whole thing off. The write side still accepts the old
0/1 (and y/n, on/off) spelling so existing scripts don't break; only the
read format grows to "[always] advise never".

Patch 7 documents the prctl and debugfs interface for cache aware
scheduling in kerneldoc.

Relation to sched QoS
=====================

This patch set is also inspired by Qais' sched QoS tool for finer-grained
control:

  https://lore.kernel.org/lkml/20260415000910.2h5misvwc45bdumu@airbuntu/
  https://github.com/qais-yousef/schedqos

There are two deliberate differences from the sched QoS interface:

1. The cookie is owned by the kernel. User space never invents or passes a
   cookie value - it only names tasks by pid and asks the kernel to create
   a group or link one task's group to another. That mirrors core
   scheduling, where PR_SCHED_CORE_GET only hands back an obfuscated id.
   It also relieves userspace the burden of cookie lifecycle management and
   avoiding duplicate cookies between separate entities doing the grouping.
   We think that it will make schedqos easier to implement.
   The cookie value is only meant to identify whether two tasks belong
   in the same cache scheduling group.

2. It's prctl() rather than sched_setattr(). Group membership isn't really
   an attribute value, and core scheduling already set a prctl-shaped
   precedent for "put these tasks together", so we reuse its subop layout,
   pid_type scoping and ptrace_may_access() permission model.

On the schedqos side the change would live in apply_thread_qos(): create
the group once per app instance and let the rest of the app join it -
roughly:

    if (!appi->grouped) {
        /* CREATE is not idempotent, do it once per instance */
        err = prctl(PR_SCHED_CACHE, PR_SCHED_CACHE_CREATE,
                    tgid, 0, PIDTYPE_TGID);
        appi->grouped = !err;
    } else {
        prctl(PR_SCHED_CACHE, PR_SCHED_CACHE_SHARE_FROM,
              pid, tgid, PIDTYPE_PID);
    }

Yangyu Chen also proposed exposing per-process parameters via prctl:
https://lore.kernel.org/all/tencent_93116D14C771DC8C988C10E3C634BE0CC107@qq.com/
That fits naturally on top of this if people agree the direction is right.

And in theory cgroup could offer per-cgroup cache aware scheduling with the
same mechanism - but we'd want input from the cgroup maintainers before
going anywhere near that.

Still to do
===========

  - Documentation for the new prctl (a prctl(2) man-page
    update).
  - A selftest under tools/testing/selftests exercising the subops and the
    permission checks - likewise TODO.

Feedbacks very welcome, especially on the interface shape (prctl vs. a QoS
attribute), the kernel-owned-cookie choice, and whether the always/advise/
never policy composition is the right model.

The series applies on v7.2-rc6.

Tim Chen and Chen Yu

Chen Yu (1):
  sched/cache: Extend the enabled debugfs to more modes

Tim Chen (6):
  sched/cache: Decouple sched_cache_group from mm
  sched/cache: Introduce task_struct->sched_cache_grp
  sched/cache: Extract sched_cache_alloc_group() helper
  sched/cache: Add prctl to manage per process cache scheduling groups
  sched/cache: Allow a process to enable cache aware scheduling via
    prctl
  sched/cache: Documentation: document the PR_SCHED_CACHE prctl

 .../admin-guide/kernel-parameters.txt         |   3 +
 Documentation/scheduler/index.rst             |   1 +
 Documentation/scheduler/sched-cache.rst       | 175 ++++++++
 fs/exec.c                                     |  24 ++
 include/linux/mm_types.h                      |  15 +-
 include/linux/sched.h                         |  18 +-
 include/uapi/linux/prctl.h                    |   9 +
 kernel/exit.c                                 |  35 +-
 kernel/fork.c                                 |  38 ++
 kernel/sched/build_utility.c                  |   4 +
 kernel/sched/cache_sched.c                    | 374 ++++++++++++++++++
 kernel/sched/debug.c                          |  63 ++-
 kernel/sched/fair.c                           | 188 +++++----
 kernel/sched/sched.h                          |  24 +-
 kernel/sched/topology.c                       |  32 +-
 kernel/sys.c                                  |   5 +
 16 files changed, 895 insertions(+), 113 deletions(-)
 create mode 100644 Documentation/scheduler/sched-cache.rst
 create mode 100644 kernel/sched/cache_sched.c

-- 
2.32.0
Re: [RFC PATCH 0/7] sched/cache: Per-task control of cache aware scheduling via prctl
Posted by Shrikanth Hegde 2 weeks, 3 days ago
Hi Tim/Peter.

I have been trying to catch up. I still have to read
and might have missed some conversation details. So please
bear with me for silly questions.

On 8/29/26 3:59 AM, Tim Chen wrote:
> Hi all,
> 
> Cache aware scheduling today groups tasks by their mm: the LLC aggregation
> target lives in mm_struct, so the address space is the unit of grouping.
> That works, but in some scenarios that is too coarse and too eager, and the
> only knob we have over it is a single system-wide debugfs switch.
> 
> It's too coarse because plenty of workloads share data across cooperating
> *processes* rather than threads - a database with a process per connection,
> a browser with a renderer per site, a server and its worker helpers. They
> pass data through shm or pipes and would love to be pulled onto the same
> LLC, but they never share an mm, so today they can't be. And it's too eager
> in the other direction: a process whose threads don't actually share
> anything gets aggregated anyway, just because they happen to sit in one
> address space.
> 
> So the core idea of this series is simple: allow other groupings than
> the mm, make the grouping an object in its own right, and let user space
> say "put these tasks together" explicitly.

So, As you said, this is effectively asking user to make the decision.

But what tools do user space have today to make effective decisions?
Application changes could turn out to be tricky to do and how an
application developer will know whether to group them together or not?
What's guidance there?

Can the grouping be done post the application started running?
Like any option that says these pid's are to be bundled into one group?

I remember you guys discussed about cgroup and decided it is not a good option.
That argument is still holds?
Re: [RFC PATCH 0/7] sched/cache: Per-task control of cache aware scheduling via prctl
Posted by Tim Chen 2 weeks, 1 day ago
On Wed, 2026-09-09 at 18:27 +0530, Shrikanth Hegde wrote:
> Hi Tim/Peter.
> 
> I have been trying to catch up. I still have to read
> and might have missed some conversation details. So please
> bear with me for silly questions.

Thanks for taking a look.  You questions are helpful for
providing the context of why this series was proposed.

> 
> On 8/29/26 3:59 AM, Tim Chen wrote:
> > Hi all,
> > 
> > Cache aware scheduling today groups tasks by their mm: the LLC aggregation
> > target lives in mm_struct, so the address space is the unit of grouping.
> > That works, but in some scenarios that is too coarse and too eager, and the
> > only knob we have over it is a single system-wide debugfs switch.
> > 
> > It's too coarse because plenty of workloads share data across cooperating
> > *processes* rather than threads - a database with a process per connection,
> > a browser with a renderer per site, a server and its worker helpers. They
> > pass data through shm or pipes and would love to be pulled onto the same
> > LLC, but they never share an mm, so today they can't be. And it's too eager
> > in the other direction: a process whose threads don't actually share
> > anything gets aggregated anyway, just because they happen to sit in one
> > address space.
> > 
> > So the core idea of this series is simple: allow other groupings than
> > the mm, make the grouping an object in its own right, and let user space
> > say "put these tasks together" explicitly.
> 
> So, As you said, this is effectively asking user to make the decision.

By default, tasks are grouped by process and that make sense in many cases.
But sometimes the users have information about task characteristics that they wish to group
tasks in other ways. 

In our discussions with Vern Hao from Tencent, they have multiple processes
in their workload, where some tasks in a process is responsible for
database access, some for encryption, and some dealing with disk access.
Those tasks across processes with similar function share more data than
tasks in a process for their applications.  

Another scenario is grouping processes with shared memory together.

> 
> But what tools do user space have today to make effective decisions?

As in the example above, this is for users who know about their workload
characteristics and wish to group their tasks in other way than the default
process grouping.

Also if people identify via perf c2c that tasks  

> Application changes could turn out to be tricky to do and how an
> application developer will know whether to group them together or not?
> What's guidance there?

No changes is required on application. An admin or a separate daemon
can use prctl to group tasks together by sepcifying the pids pair of tasks
to be grouped. Please see the PR_SCHED_CACHE_SHARE_FROM operation in
patch 7 of the documentation.

> 
> Can the grouping be done post the application started running?
> Like any option that says these pid's are to be bundled into one group?

Yes.

> 
> I remember you guys discussed about cgroup and decided it is not a good option.
> That argument is still holds?

I think there is no strong case to support that tasks sharing
data necessarily belong in a cgroup. Using cgroup wouldn't cover all the use cases
we want. With the proposed prctl based interface in this series,
the administrator can easily group the processes in a cgroup together
if that makes sense. We also would rather not disturb the cgroup
interface unnecessarily.

Tim
Re: [RFC PATCH 0/7] sched/cache: Per-task control of cache aware scheduling via prctl
Posted by Peter Zijlstra 4 weeks ago
On Fri, Aug 28, 2026 at 03:29:07PM -0700, Tim Chen wrote:
 
> Feedbacks very welcome, especially on the interface shape (prctl vs. a QoS
> attribute), the kernel-owned-cookie choice, and whether the always/advise/
> never policy composition is the right model.

Who would be using this -- what workload prompted you do do this etc.
Re: [RFC PATCH 0/7] sched/cache: Per-task control of cache aware scheduling via prctl
Posted by Chen Yu 3 weeks, 5 days ago
Hi Peter,

On Sat, Aug 29, 2026 at 11:27:21AM +0200, Peter Zijlstra wrote:
> Subject: Re: [RFC PATCH 0/7] sched/cache: Per-task control of cache aware
>  scheduling via prctl
> 
> On Fri, Aug 28, 2026 at 03:29:07PM -0700, Tim Chen wrote:
>  
> > Feedbacks very welcome, especially on the interface shape (prctl vs. a QoS
> > attribute), the kernel-owned-cookie choice, and whether the always/advise/
> > never policy composition is the right model.
> 
> Who would be using this -- what workload prompted you do do this etc.
>

One motivation is that some cloud users would like finer-grained control over
cache‑aware scheduling. Vern Hao from Tencent previously asked about this:

https://lore.kernel.org/all/7d5bb7c4-abc5-470e-84fe-72a3b1d3a2f4@gmail.com/

and mentioned that, in their production environment, threads within the same
process do not always share data. On the other hand, it is possible that within
one process there are two thread groups, A and B. Threads in group A share data
with each other, while threads in group B do not. Typically, in Vern's environment,
group A and group B are cgroups. Group A usually runs memory‑intensive workloads, such
as KV‑cache related ones, and such workloads have intensive data sharing among themselves,
so they would like to enable cache‑aware scheduling separately. Furthermore, since group A
is memory‑intensive, the default cache‑aware scheduling threshold might reject aggregation
because group A's memory footprint is high. As a result, group A has a requirement to turn the
threshold parameter separately.

thanks,
Chenyu
Re: [RFC PATCH 0/7] sched/cache: Per-task control of cache aware scheduling via prctl
Posted by Tim Chen 3 weeks, 5 days ago
On Mon, 2026-08-31 at 22:39 +0800, Chen Yu wrote:
> Hi Peter,
> 
> On Sat, Aug 29, 2026 at 11:27:21AM +0200, Peter Zijlstra wrote:
> > Subject: Re: [RFC PATCH 0/7] sched/cache: Per-task control of cache aware
> >  scheduling via prctl
> > 
> > On Fri, Aug 28, 2026 at 03:29:07PM -0700, Tim Chen wrote:
> >  
> > > Feedbacks very welcome, especially on the interface shape (prctl vs. a QoS
> > > attribute), the kernel-owned-cookie choice, and whether the always/advise/
> > > never policy composition is the right model.
> > 
> > Who would be using this -- what workload prompted you do do this etc.
> > 
> 
> One motivation is that some cloud users would like finer-grained control over
> cache‑aware scheduling. Vern Hao from Tencent previously asked about this:
> 
> https://lore.kernel.org/all/7d5bb7c4-abc5-470e-84fe-72a3b1d3a2f4@gmail.com/
> 
> and mentioned that, in their production environment, threads within the same
> process do not always share data. On the other hand, it is possible that within
> one process there are two thread groups, A and B. Threads in group A share data
> with each other, while threads in group B do not. Typically, in Vern's environment,
> group A and group B are cgroups. Group A usually runs memory‑intensive workloads, such
> as KV‑cache related ones, and such workloads have intensive data sharing among themselves,
> so they would like to enable cache‑aware scheduling separately. Furthermore, since group A
> is memory‑intensive, the default cache‑aware scheduling threshold might reject aggregation
> because group A's memory footprint is high. As a result, group A has a requirement to turn the
> threshold parameter separately.

I also remembered in discussions with Vern, His usage scenario has processes each comprising of threads
doing different functions, like one thread responsible for database lookup, one for encryption/decryption
and one for file IO ...etc. So the threads in different processes performing similar function
has more common data and perform better when grouped together.

Also in separate discussions with Qais, he has also mentioned that
for his environment, tasks in the same process may not share data.
https://lore.kernel.org/lkml/20260219140828.a7pyzupun7lsdw34@airbuntu/ :

>> This initial implementation treats threads within the same process as
>> entities that are likely to share data. During load balancing, the

>This is a very aggressive assumption. From what I've seen, only few tasks truly
>share data. Lumping everything in a process together is an easy way to
>classify, but I think we can do better.

So this series is an attempt to address such cases where grouping
tasks by other criteria than mm makes sense.

Tim