Files
Centos-kernel-stream-10/init
Waiman Long e3ba5f270c cgroup: replace global percpu_rwsem with per threadgroup resem when writing to cgroup.procs
JIRA: https://issues.redhat.com/browse/RHEL-113305

commit 0568f89d4fb82d98001baeb870e92f43cd1f7317
Author: Yi Tao <escape@linux.alibaba.com>
Date:   Wed, 10 Sep 2025 14:59:35 +0800

    cgroup: replace global percpu_rwsem with per threadgroup resem when writing to cgroup.procs

    The static usage pattern of creating a cgroup, enabling controllers,
    and then seeding it with CLONE_INTO_CGROUP doesn't require write
    locking cgroup_threadgroup_rwsem and thus doesn't benefit from this
    patch.

    To avoid affecting other users, the per threadgroup rwsem is only used
    when the favordynmods is enabled.

    As computer hardware advances, modern systems are typically equipped
    with many CPU cores and large amounts of memory, enabling the deployment
    of numerous applications. On such systems, container creation and
    deletion become frequent operations, making cgroup process migration no
    longer a cold path. This leads to noticeable contention with common
    process operations such as fork, exec, and exit.

    To alleviate the contention between cgroup process migration and
    operations like process fork, this patch modifies lock to take the write
    lock on signal_struct->group_rwsem when writing pid to
    cgroup.procs/threads instead of holding a global write lock.

    Cgroup process migration has historically relied on
    signal_struct->group_rwsem to protect thread group integrity. In commit
    <1ed1328792ff> ("sched, cgroup: replace signal_struct->group_rwsem with
    a global percpu_rwsem"), this was changed to a global
    cgroup_threadgroup_rwsem. The advantage of using a global lock was
    simplified handling of process group migrations. This patch retains the
    use of the global lock for protecting process group migration, while
    reducing contention by using per thread group lock during
    cgroup.procs/threads writes.

    The locking behavior is as follows:

    write cgroup.procs/threads  | process fork,exec,exit | process group migration
    ------------------------------------------------------------------------------
    cgroup_lock()               | down_read(&g_rwsem)    | cgroup_lock()
    down_write(&p_rwsem)        | down_read(&p_rwsem)    | down_write(&g_rwsem)
    critical section            | critical section       | critical section
    up_write(&p_rwsem)          | up_read(&p_rwsem)      | up_write(&g_rwsem)
    cgroup_unlock()             | up_read(&g_rwsem)      | cgroup_unlock()

    g_rwsem denotes cgroup_threadgroup_rwsem, p_rwsem denotes
    signal_struct->group_rwsem.

    This patch eliminates contention between cgroup migration and fork
    operations for threads that belong to different thread groups, thereby
    reducing the long-tail latency of cgroup migrations and lowering system
    load.

    With this patch, under heavy fork and exec interference, the long-tail
    latency of cgroup migration has been reduced from milliseconds to
    microseconds. Under heavy cgroup migration interference, the multi-CPU
    score of the spawn test case in UnixBench increased by 9%.

    tj: Update comment in cgroup_favor_dynmods() and switch WARN_ONCE() to
        pr_warn_once().

    Signed-off-by: Yi Tao <escape@linux.alibaba.com>
    Signed-off-by: Tejun Heo <tj@kernel.org>

Signed-off-by: Waiman Long <longman@redhat.com>
2026-02-23 15:13:07 -05:00
..