forked from mirrors/linux
		
	document while_each_thread(), change first_tid() to use for_each_thread()
Add the comment to explain that while_each_thread(g,t) is not rcu-safe unless g is stable (e.g. current). Even if g is a group leader and thus can't exit before t, t or another sub-thread can exec and remove g from the thread_group list. The only lockless user of while_each_thread() is first_tid() and it is fine in that it can't loop forever, yet for_each_thread() looks better and I am going to change while_each_thread/next_thread. Link: https://lkml.kernel.org/r/20230823170806.GA11724@redhat.com Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									ed1af26cd2
								
							
						
					
					
						commit
						dce8f8ed1d
					
				
					 2 changed files with 6 additions and 3 deletions
				
			
		| 
						 | 
					@ -3813,11 +3813,10 @@ static struct task_struct *first_tid(struct pid *pid, int tid, loff_t f_pos,
 | 
				
			||||||
	/* If we haven't found our starting place yet start
 | 
						/* If we haven't found our starting place yet start
 | 
				
			||||||
	 * with the leader and walk nr threads forward.
 | 
						 * with the leader and walk nr threads forward.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	pos = task = task->group_leader;
 | 
						for_each_thread(task, pos) {
 | 
				
			||||||
	do {
 | 
					 | 
				
			||||||
		if (!nr--)
 | 
							if (!nr--)
 | 
				
			||||||
			goto found;
 | 
								goto found;
 | 
				
			||||||
	} while_each_thread(task, pos);
 | 
						};
 | 
				
			||||||
fail:
 | 
					fail:
 | 
				
			||||||
	pos = NULL;
 | 
						pos = NULL;
 | 
				
			||||||
	goto out;
 | 
						goto out;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -648,6 +648,10 @@ extern void flush_itimer_signals(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern bool current_is_single_threaded(void);
 | 
					extern bool current_is_single_threaded(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Without tasklist/siglock it is only rcu-safe if g can't exit/exec,
 | 
				
			||||||
 | 
					 * otherwise next_thread(t) will never reach g after list_del_rcu(g).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
#define while_each_thread(g, t) \
 | 
					#define while_each_thread(g, t) \
 | 
				
			||||||
	while ((t = next_thread(t)) != g)
 | 
						while ((t = next_thread(t)) != g)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue