aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2009-07-09 17:28:49 -0400
committerJames Morris <jmorris@namei.org>2009-07-16 19:11:31 -0400
commit967cc5371113f9806b39a2ebb2174af2883d96fe (patch)
treed99845169cde5e238a02d1e984ff9aa65b66482f
parent5bb459bb45d1ad3c177485dcf0af01580aa31125 (diff)
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 <oleg@redhat.com> Acked-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r--lib/is_single_threaded.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/lib/is_single_threaded.c b/lib/is_single_threaded.c
index 434010980bdf..bd2bea963364 100644
--- a/lib/is_single_threaded.c
+++ b/lib/is_single_threaded.c
@@ -22,8 +22,6 @@ bool current_is_single_threaded(void)
22 struct task_struct *p, *t; 22 struct task_struct *p, *t;
23 bool ret; 23 bool ret;
24 24
25 might_sleep();
26
27 if (atomic_read(&task->signal->live) != 1) 25 if (atomic_read(&task->signal->live) != 1)
28 return false; 26 return false;
29 27
@@ -31,7 +29,6 @@ bool current_is_single_threaded(void)
31 return true; 29 return true;
32 30
33 ret = false; 31 ret = false;
34 down_write(&mm->mmap_sem);
35 rcu_read_lock(); 32 rcu_read_lock();
36 for_each_process(p) { 33 for_each_process(p) {
37 if (unlikely(p->flags & PF_KTHREAD)) 34 if (unlikely(p->flags & PF_KTHREAD))
@@ -45,12 +42,17 @@ bool current_is_single_threaded(void)
45 goto found; 42 goto found;
46 if (likely(t->mm)) 43 if (likely(t->mm))
47 break; 44 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();
48 } while_each_thread(p, t); 51 } while_each_thread(p, t);
49 } 52 }
50 ret = true; 53 ret = true;
51found: 54found:
52 rcu_read_unlock(); 55 rcu_read_unlock();
53 up_write(&mm->mmap_sem);
54 56
55 return ret; 57 return ret;
56} 58}