Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions fs/proc/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1160,8 +1160,7 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy)
if (mm) {
struct task_struct *p;

rcu_read_lock();
for_each_process(p) {
for_each_process_rculock(p) {
if (same_thread_group(task, p))
continue;

Expand All @@ -1177,7 +1176,6 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy)
}
task_unlock(p);
}
rcu_read_unlock();
mmdrop(mm);
}
err_unlock:
Expand Down
8 changes: 2 additions & 6 deletions fs/resctrl/rdtgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -709,14 +709,12 @@ int rdtgroup_tasks_assigned(struct rdtgroup *r)

lockdep_assert_held(&rdtgroup_mutex);

rcu_read_lock();
for_each_process_thread(p, t) {
for_each_process_thread_rculock(p, t) {
if (is_closid_match(t, r) || is_rmid_match(t, r)) {
ret = 1;
break;
}
}
rcu_read_unlock();

return ret;
}
Expand Down Expand Up @@ -826,15 +824,13 @@ static void show_rdt_tasks(struct rdtgroup *r, struct seq_file *s)
struct task_struct *p, *t;
pid_t pid;

rcu_read_lock();
for_each_process_thread(p, t) {
for_each_process_thread_rculock(p, t) {
if (is_closid_match(t, r) || is_rmid_match(t, r)) {
pid = task_pid_vnr(t);
if (pid)
seq_printf(s, "%d\n", pid);
}
}
rcu_read_unlock();
}

static int rdtgroup_tasks_show(struct kernfs_open_file *of,
Expand Down
26 changes: 26 additions & 0 deletions include/linux/sched/signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#ifndef _LINUX_SCHED_SIGNAL_H
#define _LINUX_SCHED_SIGNAL_H

#include <linux/cleanup.h>
#include <linux/rculist.h>
#include <linux/signal.h>
#include <linux/sched.h>
Expand Down Expand Up @@ -663,6 +664,31 @@ extern bool current_is_single_threaded(void);
#define for_each_process_thread(p, t) \
for_each_process(p) for_each_thread(p, t)

/*
* Variants of for_each_process(), for_each_thread() and
* for_each_process_thread() that automatically acquire and release the
* RCU read lock via scoped_guard(rcu). The lock is held for the
* duration of the loop and released on exit, including via break,
* goto, or return.
*/
#define for_each_process_rculock(p) \
scoped_guard(rcu) \
for (p = &init_task ; (p = next_task(p)) != &init_task ; )

#define for_each_thread_rculock(p, t) \
scoped_guard(rcu) \
__for_each_thread((p)->signal, t)

/*
* Double loop: 'break' only exits the inner for_each_thread() loop.
* Use 'goto' to exit both loops; the RCU read lock is released
* automatically when the scoped_guard scope is left.
*/
#define for_each_process_thread_rculock(p, t) \
scoped_guard(rcu) \
for_each_process(p) \
for_each_thread(p, t)

typedef int (*proc_visitor)(struct task_struct *p, void *data);
void walk_process_tree(struct task_struct *top, proc_visitor, void *);

Expand Down
4 changes: 1 addition & 3 deletions kernel/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1254,8 +1254,7 @@ void clear_tasks_mm_cpumask(int cpu)
* full-fledged tasklist_lock.
*/
WARN_ON(cpu_online(cpu));
rcu_read_lock();
for_each_process(p) {
for_each_process_rculock(p) {
struct task_struct *t;

/*
Expand All @@ -1268,7 +1267,6 @@ void clear_tasks_mm_cpumask(int cpu)
arch_clear_mm_cpumask_cpu(cpu, t->mm);
task_unlock(t);
}
rcu_read_unlock();
}

/* Take this CPU down. */
Expand Down
4 changes: 1 addition & 3 deletions kernel/freezer.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,9 @@ void thaw_process(struct task_struct *p)
{
struct task_struct *t;

rcu_read_lock();
for_each_thread(p, t) {
for_each_thread_rculock(p, t) {
__thaw_task(t);
}
rcu_read_unlock();
}

/**
Expand Down
11 changes: 4 additions & 7 deletions kernel/hung_task.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,13 +315,12 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
return;

this_round_count = 0;
rcu_read_lock();
for_each_process_thread(g, t) {
for_each_process_thread_rculock(g, t) {
if (!max_count--)
goto unlock;
goto out;
if (time_after(jiffies, last_break + HUNG_TASK_LOCK_BREAK)) {
if (!rcu_lock_break(g, t))
goto unlock;
goto out;
last_break = jiffies;
}

Expand All @@ -337,9 +336,7 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
hung_task_info(t, timeout, this_round_count);
}
}
unlock:
rcu_read_unlock();

out:
if (!this_round_count)
return;

Expand Down
4 changes: 1 addition & 3 deletions kernel/locking/lockdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -6834,15 +6834,13 @@ void debug_show_all_locks(void)
}
pr_warn("\nShowing all locks held in the system:\n");

rcu_read_lock();
for_each_process_thread(g, p) {
for_each_process_thread_rculock(g, p) {
if (!p->lockdep_depth)
continue;
lockdep_print_held_locks(p);
touch_nmi_watchdog();
touch_all_softlockup_watchdogs();
}
rcu_read_unlock();

pr_warn("\n");
pr_warn("=============================================\n\n");
Expand Down
4 changes: 1 addition & 3 deletions kernel/rcu/update.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,15 +547,13 @@ void synchronize_rcu_trivial_preempt(void)
struct task_struct *t;

smp_mb(); // Order prior accesses before grace-period start.
rcu_read_lock(); // Protect task list.
for_each_process_thread(g, t) {
for_each_process_thread_rculock(g, t) {
if (t == current)
continue; // Don't deadlock on ourselves!
// Order later rcu_read_lock() on other tasks after QS.
while (smp_load_acquire(&t->rcu_trivial_preempt_nesting))
continue;
}
rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(synchronize_rcu_trivial_preempt);
#endif // #if IS_ENABLED(CONFIG_TRIVIAL_PREEMPT_RCU)
Expand Down
3 changes: 1 addition & 2 deletions kernel/sched/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2015,8 +2015,7 @@ static void uclamp_sync_util_min_rt_default(void)
smp_mb__after_spinlock();
read_unlock(&tasklist_lock);

guard(rcu)();
for_each_process_thread(g, p)
for_each_process_thread_rculock(g, p)
uclamp_update_util_min_rt_default(p);
}

Expand Down
4 changes: 1 addition & 3 deletions kernel/sched/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -1029,14 +1029,12 @@ static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu)
#endif
"\n");

rcu_read_lock();
for_each_process_thread(g, p) {
for_each_process_thread_rculock(g, p) {
if (task_cpu(p) != rq_cpu)
continue;

print_task(m, rq, p);
}
rcu_read_unlock();
}

void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
Expand Down
8 changes: 2 additions & 6 deletions kernel/trace/fgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -1057,11 +1057,10 @@ static int alloc_retstack_tasklist(unsigned long **ret_stack_list)
}
}

rcu_read_lock();
for_each_process_thread(g, t) {
for_each_process_thread_rculock(g, t) {
if (start == end) {
ret = -EAGAIN;
goto unlock;
goto free;
}

if (t->ret_stack == NULL) {
Expand All @@ -1074,9 +1073,6 @@ static int alloc_retstack_tasklist(unsigned long **ret_stack_list)
t->ret_stack = ret_stack_list[start++];
}
}

unlock:
rcu_read_unlock();
free:
for (i = start; i < end; i++)
kmem_cache_free(fgraph_stack_cachep, ret_stack_list[i]);
Expand Down
3 changes: 1 addition & 2 deletions kernel/unwind/deferred.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,8 @@ void unwind_deferred_cancel(struct unwind_work *work)

synchronize_srcu(&unwind_srcu);

guard(rcu)();
/* Clear this bit from all threads */
for_each_process_thread(g, t) {
for_each_process_thread_rculock(g, t) {
atomic_long_andnot(BIT(bit),
&t->unwind_info.unwind_mask);
if (t->unwind_info.cache)
Expand Down
5 changes: 1 addition & 4 deletions lib/is_single_threaded.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ bool current_is_single_threaded(void)
return true;

ret = false;
rcu_read_lock();
for_each_process(p) {
for_each_process_rculock(p) {
if (unlikely(p->flags & PF_KTHREAD))
continue;
if (unlikely(p == task->group_leader))
Expand All @@ -48,7 +47,5 @@ bool current_is_single_threaded(void)
}
ret = true;
found:
rcu_read_unlock();

return ret;
}
4 changes: 1 addition & 3 deletions mm/ksm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3280,8 +3280,7 @@ void collect_procs_ksm(const struct folio *folio, const struct page *page,
struct anon_vma *av = rmap_item->anon_vma;

anon_vma_lock_read(av);
rcu_read_lock();
for_each_process(tsk) {
for_each_process_rculock(tsk) {
struct anon_vma_chain *vmac;
const unsigned long addr = rmap_item->address & PAGE_MASK;
const unsigned long index = rmap_item->linear_page_index;
Expand All @@ -3298,7 +3297,6 @@ void collect_procs_ksm(const struct folio *folio, const struct page *page,
}
}
}
rcu_read_unlock();
anon_vma_unlock_read(av);
}
}
Expand Down
16 changes: 4 additions & 12 deletions mm/memory-failure.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,8 +555,7 @@ static void collect_procs_anon(const struct folio *folio,
return;

pgoff = page_pgoff(folio, page);
rcu_read_lock();
for_each_process(tsk) {
for_each_process_rculock(tsk) {
struct vm_area_struct *vma;
struct anon_vma_chain *vmac;
struct task_struct *t = task_early_kill(tsk, force_early);
Expand All @@ -572,7 +571,6 @@ static void collect_procs_anon(const struct folio *folio,
add_to_kill_anon_file(t, page, vma, to_kill, addr);
}
}
rcu_read_unlock();
anon_vma_unlock_read(av);
}

Expand All @@ -589,9 +587,8 @@ static void collect_procs_file(const struct folio *folio,
pgoff_t pgoff;

i_mmap_lock_read(mapping);
rcu_read_lock();
pgoff = page_pgoff(folio, page);
for_each_process(tsk) {
for_each_process_rculock(tsk) {
struct task_struct *t = task_early_kill(tsk, force_early);
unsigned long addr;

Expand All @@ -611,7 +608,6 @@ static void collect_procs_file(const struct folio *folio,
add_to_kill_anon_file(t, page, vma, to_kill, addr);
}
}
rcu_read_unlock();
i_mmap_unlock_read(mapping);
}

Expand All @@ -635,8 +631,7 @@ static void collect_procs_fsdax(const struct page *page,
struct task_struct *tsk;

i_mmap_lock_read(mapping);
rcu_read_lock();
for_each_process(tsk) {
for_each_process_rculock(tsk) {
struct task_struct *t = tsk;

/*
Expand All @@ -653,7 +648,6 @@ static void collect_procs_fsdax(const struct page *page,
add_to_kill_fsdax(t, page, vma, to_kill, pgoff);
}
}
rcu_read_unlock();
i_mmap_unlock_read(mapping);
}
#endif /* CONFIG_FS_DAX */
Expand Down Expand Up @@ -2288,8 +2282,7 @@ static void collect_procs_pfn(struct pfn_address_space *pfn_space,
struct address_space *mapping = pfn_space->mapping;

i_mmap_lock_read(mapping);
rcu_read_lock();
for_each_process(tsk) {
for_each_process_rculock(tsk) {
struct task_struct *t = tsk;

t = task_early_kill(tsk, true);
Expand All @@ -2303,7 +2296,6 @@ static void collect_procs_pfn(struct pfn_address_space *pfn_space,
add_to_kill_pgoff(t, vma, to_kill, pgoff);
}
}
rcu_read_unlock();
i_mmap_unlock_read(mapping);
}

Expand Down
Loading
Loading