diff options
-rw-r--r-- | lib/is_single_threaded.c | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/lib/is_single_threaded.c b/lib/is_single_threaded.c index f1ed2fe76c65..2762516e0a5e 100644 --- a/lib/is_single_threaded.c +++ b/lib/is_single_threaded.c | |||
@@ -12,34 +12,44 @@ | |||
12 | 12 | ||
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | 14 | ||
15 | /** | 15 | /* |
16 | * is_single_threaded - Determine if a thread group is single-threaded or not | 16 | * Returns true if the task does not share ->mm with another thread/process. |
17 | * @p: A task in the thread group in question | ||
18 | * | ||
19 | * This returns true if the thread group to which a task belongs is single | ||
20 | * threaded, false if it is not. | ||
21 | */ | 17 | */ |
22 | bool is_single_threaded(struct task_struct *p) | 18 | bool is_single_threaded(struct task_struct *task) |
23 | { | 19 | { |
24 | struct task_struct *g, *t; | 20 | struct mm_struct *mm = task->mm; |
25 | struct mm_struct *mm = p->mm; | 21 | struct task_struct *p, *t; |
26 | 22 | bool ret; | |
27 | if (atomic_read(&p->signal->count) != 1) | 23 | |
28 | goto no; | 24 | might_sleep(); |
29 | 25 | ||
30 | if (atomic_read(&p->mm->mm_users) != 1) { | 26 | if (atomic_read(&task->signal->live) != 1) |
31 | read_lock(&tasklist_lock); | 27 | return false; |
32 | do_each_thread(g, t) { | ||
33 | if (t->mm == mm && t != p) | ||
34 | goto no_unlock; | ||
35 | } while_each_thread(g, t); | ||
36 | read_unlock(&tasklist_lock); | ||
37 | } | ||
38 | 28 | ||
39 | return true; | 29 | if (atomic_read(&mm->mm_users) == 1) |
30 | return true; | ||
31 | |||
32 | ret = false; | ||
33 | down_write(&mm->mmap_sem); | ||
34 | rcu_read_lock(); | ||
35 | for_each_process(p) { | ||
36 | if (unlikely(p->flags & PF_KTHREAD)) | ||
37 | continue; | ||
38 | if (unlikely(p == task->group_leader)) | ||
39 | continue; | ||
40 | |||
41 | t = p; | ||
42 | do { | ||
43 | if (unlikely(t->mm == mm)) | ||
44 | goto found; | ||
45 | if (likely(t->mm)) | ||
46 | break; | ||
47 | } while_each_thread(p, t); | ||
48 | } | ||
49 | ret = true; | ||
50 | found: | ||
51 | rcu_read_unlock(); | ||
52 | up_write(&mm->mmap_sem); | ||
40 | 53 | ||
41 | no_unlock: | 54 | return ret; |
42 | read_unlock(&tasklist_lock); | ||
43 | no: | ||
44 | return false; | ||
45 | } | 55 | } |