[Deepin-Kernel-SIG] [linux 6.6.y] [Upstream] introduce __next_thread(), change next_thread() & kill task_struct->thread_group#1868
Conversation
mainline inclusion from mainline-v6.7-rc1 category: performance Patch series "introduce __next_thread(), change next_thread()". After commit dce8f8e ("document while_each_thread(), change first_tid() to use for_each_thread()") + this series 1. We have only one lockless user of next_thread(), task_group_seq_get_next(). I think it should be changed too. 2. We have only one user of task_struct->thread_group, thread_group_empty(). The next patches will change thread_group_empty() and kill ->thread_group. This patch (of 2): next_tid(start) does: rcu_read_lock(); if (pid_alive(start)) { pos = next_thread(start); if (thread_group_leader(pos)) pos = NULL; else get_task_struct(pos); it should return pos = NULL when next_thread() wraps to the 1st thread in the thread group, group leader, and the thread_group_leader() check tries to detect this case. But this can race with exec. To simplify, suppose we have a main thread M and a single sub-thread T, next_tid(T) should return NULL. Now suppose that T execs. If next_tid(T) is called after T changes the leadership and before it does release_task() which removes the old leader from list, then next_thread() returns M and thread_group_leader(M) = F. Lockless use of next_thread() should be avoided. After this change only task_group_seq_get_next() does this, and I believe it should be changed as well. Link: https://lkml.kernel.org/r/20230824143112.GA31208@redhat.com Link: https://lkml.kernel.org/r/20230824143142.GA31222@redhat.com Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> (cherry picked from commit 33a9813) Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
mainline inclusion from mainline-v6.7-rc1 category: performance This relies on fact that group leader is always the 1st entry in the signal->thread_head list. With or without this change, if the lockless next_thread(last_thread) races with exec it can return the old or the new leader. We are almost ready to kill task->thread_group, after this change its only user is thread_group_empty(). Link: https://lkml.kernel.org/r/20230824143201.GB31222@redhat.com Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> (cherry picked from commit d639cf4) Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
mainline inclusion from mainline-v6.7-rc1 category: performance Patch series "kill task_struct->thread_group". This patch (of 2): It could use list_is_singular() but this way it is cheaper. Plus the thread_group_leader() check makes it clear that thread_group_empty() can only return true if p is a group leader. This was not immediately obvious before this patch. task_struct->thread_group no longer has users, it can die. Link: https://lkml.kernel.org/r/20230826111200.GA22982@redhat.com Link: https://lkml.kernel.org/r/20230826111406.GA23238@redhat.com Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> (cherry picked from commit e34a35e) Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
mainline inclusion from mainline-v6.7-rc1 category: performance The last user was removed by the previous patch. Link: https://lkml.kernel.org/r/20230826111409.GA23243@redhat.com Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> (cherry picked from commit 8e1f385) Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
mainline inclusion from mainline-v6.7-rc5 category: bugfix Since commit 8e1f385 ("kill task_struct->thread_group") remove the thread_group, we will encounter below issue. (gdb) lx-ps TASK PID COMM 0xffff800086503340 0 swapper/0 Python Exception <class 'gdb.error'>: There is no member named thread_group. Error occurred in Python: There is no member named thread_group. We use signal->thread_head to iterate all threads instead. [Kuan-Ying.Lee@mediatek.com: v2] Link: https://lkml.kernel.org/r/20231129065142.13375-2-Kuan-Ying.Lee@mediatek.com Link: https://lkml.kernel.org/r/20231127070404.4192-2-Kuan-Ying.Lee@mediatek.com Fixes: 8e1f385 ("kill task_struct->thread_group") Signed-off-by: Kuan-Ying Lee <Kuan-Ying.Lee@mediatek.com> Acked-by: Oleg Nesterov <oleg@redhat.com> Tested-by: Florian Fainelli <florian.fainelli@broadcom.com> Cc: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Cc: Chinwen Chang <chinwen.chang@mediatek.com> Cc: Kuan-Ying Lee <Kuan-Ying.Lee@mediatek.com> Cc: Matthias Brugger <matthias.bgg@gmail.com> Cc: Qun-Wei Lin <qun-wei.lin@mediatek.com> Cc: Andrey Konovalov <andreyknvl@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> (cherry picked from commit 854f276) Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
Reviewer's GuideRefactors thread-group iteration to use the existing signal->thread_head/thread_node list, introduces __next_thread() for raw iteration, changes next_thread() semantics to wrap to the group leader, and removes the task_struct->thread_group list and its users in core kernel, proc, fork, exit, and GDB scripts. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- In scripts/gdb/linux/tasks.py, the new task_lists() implementation will traverse thread_head for every task in the tasks list, which will cause threads to be yielded multiple times for multi-threaded groups; consider restricting the inner traversal to group leaders only (e.g., guard with a group_leader check) or otherwise ensuring each thread group is walked exactly once as before.
- The change of next_thread() (and __next_thread()) to take a non-const struct task_struct * parameter weakens the previous const-correctness; consider keeping the parameter const and using an internal cast around list_next_or_null_rcu() to avoid unnecessarily widening the API surface for mutation.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In scripts/gdb/linux/tasks.py, the new task_lists() implementation will traverse thread_head for every task in the tasks list, which will cause threads to be yielded multiple times for multi-threaded groups; consider restricting the inner traversal to group leaders only (e.g., guard with a group_leader check) or otherwise ensuring each thread group is walked exactly once as before.
- The change of next_thread() (and __next_thread()) to take a non-const struct task_struct * parameter weakens the previous const-correctness; consider keeping the parameter const and using an internal cast around list_next_or_null_rcu() to avoid unnecessarily widening the API surface for mutation.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| /* PID/PID hash table linkage. */ | ||
| struct pid *thread_pid; | ||
| struct hlist_node pid_links[PIDTYPE_MAX]; | ||
| struct list_head thread_group; |
There was a problem hiding this comment.
what about kabi
don`t worry it, these patches sync from internal repo.
There was a problem hiding this comment.
Pull request overview
This PR refactors thread-group iteration to rely solely on signal->thread_head / task_struct->thread_node, introducing __next_thread() and removing the deprecated task_struct->thread_group linkage.
Changes:
- Add
__next_thread()and reworknext_thread()/thread_group_empty()to usesignal->thread_head+thread_node. - Remove all initialization and unlinking of
task_struct->thread_group(and drop the field fromtask_struct). - Update
/procTID traversal and the GDBtasks.pyhelper to iterate viathread_head/thread_node.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| scripts/gdb/linux/tasks.py | Switches GDB task/thread enumeration to signal->thread_head / thread_node. |
| kernel/fork.c | Removes thread_group initialization/linking; relies on thread_node insertion into signal->thread_head. |
| kernel/exit.c | Removes thread_group unlinking; keeps unlinking via thread_node. |
| init/init_task.c | Drops init_task.thread_group static initialization. |
| include/linux/sched/signal.h | Introduces __next_thread(), updates next_thread() and thread_group_empty() to use thread_head / thread_node. |
| include/linux/sched.h | Removes task_struct::thread_group. |
| fs/proc/base.c | Updates next_tid() to use __next_thread() to avoid wraparound semantics. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| while True: | ||
| while True: | ||
| yield t | ||
| thread_head = t['signal']['thread_head'] | ||
| for thread in lists.list_for_each_entry(thread_head, task_ptr_type, 'thread_node'): | ||
| yield thread |
Link: https://lore.kernel.org/all/20230824143142.GA31222@redhat.com/T/#u
Hello,
After document-while_each_thread-change-first_tid-to-use-for_each_thread.patch
in mm tree + this series
We have only one lockless user of next_thread(), task_group_seq_get_next().
I think it should be changed too.
We have only one user of task_struct->thread_group, thread_group_empty().
The next patches will change thread_group_empty() and kill ->thread_group.
Oleg.
Link: https://lore.kernel.org/all/20230826111406.GA23238@redhat.com/T/#u
On top of
Next: audit the while_each_thread() users.
Oleg.
Summary by Sourcery
Refactor kernel thread group iteration to use the shared thread_head/thread_node list and remove the deprecated thread_group list linkage.
Enhancements: