Skip to content

Commit 967cc53

Browse files
oleg-nesterovJames Morris
authored and
James Morris
committed
kernel: is_current_single_threaded: don't use ->mmap_sem
is_current_single_threaded() can safely miss a freshly forked CLONE_VM task, but in this case it must not miss its parent. That is why we take mm->mmap_sem for writing to make sure a thread/task with the same ->mm can't pass exit_mm() and disappear. However we can avoid ->mmap_sem and rely on rcu/barriers: - if we do not see the exiting parent on thread/process list we see the result of list_del_rcu(), in this case we must also see the result of list_add_rcu() which does wmb(). - if we do see the parent but its ->mm == NULL, we need rmb() to make sure we can't miss the child. Signed-off-by: Oleg Nesterov <[email protected]> Acked-by: David Howells <[email protected]> Signed-off-by: James Morris <[email protected]>
1 parent 5bb459b commit 967cc53

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

lib/is_single_threaded.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,13 @@ bool current_is_single_threaded(void)
2222
struct task_struct *p, *t;
2323
bool ret;
2424

25-
might_sleep();
26-
2725
if (atomic_read(&task->signal->live) != 1)
2826
return false;
2927

3028
if (atomic_read(&mm->mm_users) == 1)
3129
return true;
3230

3331
ret = false;
34-
down_write(&mm->mmap_sem);
3532
rcu_read_lock();
3633
for_each_process(p) {
3734
if (unlikely(p->flags & PF_KTHREAD))
@@ -45,12 +42,17 @@ bool current_is_single_threaded(void)
4542
goto found;
4643
if (likely(t->mm))
4744
break;
45+
/*
46+
* t->mm == NULL. Make sure next_thread/next_task
47+
* will see other CLONE_VM tasks which might be
48+
* forked before exiting.
49+
*/
50+
smp_rmb();
4851
} while_each_thread(p, t);
4952
}
5053
ret = true;
5154
found:
5255
rcu_read_unlock();
53-
up_write(&mm->mmap_sem);
5456

5557
return ret;
5658
}

0 commit comments

Comments
 (0)