diff options
-rw-r--r-- | include/linux/taskstats_kern.h | 24 | ||||
-rw-r--r-- | kernel/fork.c | 1 | ||||
-rw-r--r-- | kernel/taskstats.c | 26 |
3 files changed, 25 insertions, 26 deletions
diff --git a/include/linux/taskstats_kern.h b/include/linux/taskstats_kern.h index f1261a532496..7e9680f4afdd 100644 --- a/include/linux/taskstats_kern.h +++ b/include/linux/taskstats_kern.h | |||
@@ -20,28 +20,6 @@ static inline void taskstats_tgid_init(struct signal_struct *sig) | |||
20 | sig->stats = NULL; | 20 | sig->stats = NULL; |
21 | } | 21 | } |
22 | 22 | ||
23 | static inline void taskstats_tgid_alloc(struct task_struct *tsk) | ||
24 | { | ||
25 | struct signal_struct *sig = tsk->signal; | ||
26 | struct taskstats *stats; | ||
27 | |||
28 | if (sig->stats != NULL) | ||
29 | return; | ||
30 | |||
31 | /* No problem if kmem_cache_zalloc() fails */ | ||
32 | stats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL); | ||
33 | |||
34 | spin_lock_irq(&tsk->sighand->siglock); | ||
35 | if (!sig->stats) { | ||
36 | sig->stats = stats; | ||
37 | stats = NULL; | ||
38 | } | ||
39 | spin_unlock_irq(&tsk->sighand->siglock); | ||
40 | |||
41 | if (stats) | ||
42 | kmem_cache_free(taskstats_cache, stats); | ||
43 | } | ||
44 | |||
45 | static inline void taskstats_tgid_free(struct signal_struct *sig) | 23 | static inline void taskstats_tgid_free(struct signal_struct *sig) |
46 | { | 24 | { |
47 | if (sig->stats) | 25 | if (sig->stats) |
@@ -55,8 +33,6 @@ static inline void taskstats_exit(struct task_struct *tsk, int group_dead) | |||
55 | {} | 33 | {} |
56 | static inline void taskstats_tgid_init(struct signal_struct *sig) | 34 | static inline void taskstats_tgid_init(struct signal_struct *sig) |
57 | {} | 35 | {} |
58 | static inline void taskstats_tgid_alloc(struct task_struct *tsk) | ||
59 | {} | ||
60 | static inline void taskstats_tgid_free(struct signal_struct *sig) | 36 | static inline void taskstats_tgid_free(struct signal_struct *sig) |
61 | {} | 37 | {} |
62 | static inline void taskstats_init_early(void) | 38 | static inline void taskstats_init_early(void) |
diff --git a/kernel/fork.c b/kernel/fork.c index f37980df1d58..658838148647 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -847,7 +847,6 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts | |||
847 | if (clone_flags & CLONE_THREAD) { | 847 | if (clone_flags & CLONE_THREAD) { |
848 | atomic_inc(¤t->signal->count); | 848 | atomic_inc(¤t->signal->count); |
849 | atomic_inc(¤t->signal->live); | 849 | atomic_inc(¤t->signal->live); |
850 | taskstats_tgid_alloc(current); | ||
851 | return 0; | 850 | return 0; |
852 | } | 851 | } |
853 | sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL); | 852 | sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL); |
diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 2654886fe058..7d793d6b1e90 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c | |||
@@ -412,6 +412,30 @@ err: | |||
412 | return rc; | 412 | return rc; |
413 | } | 413 | } |
414 | 414 | ||
415 | static struct taskstats *taskstats_tgid_alloc(struct task_struct *tsk) | ||
416 | { | ||
417 | struct signal_struct *sig = tsk->signal; | ||
418 | struct taskstats *stats; | ||
419 | |||
420 | if (sig->stats || thread_group_empty(tsk)) | ||
421 | goto ret; | ||
422 | |||
423 | /* No problem if kmem_cache_zalloc() fails */ | ||
424 | stats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL); | ||
425 | |||
426 | spin_lock_irq(&tsk->sighand->siglock); | ||
427 | if (!sig->stats) { | ||
428 | sig->stats = stats; | ||
429 | stats = NULL; | ||
430 | } | ||
431 | spin_unlock_irq(&tsk->sighand->siglock); | ||
432 | |||
433 | if (stats) | ||
434 | kmem_cache_free(taskstats_cache, stats); | ||
435 | ret: | ||
436 | return sig->stats; | ||
437 | } | ||
438 | |||
415 | /* Send pid data out on exit */ | 439 | /* Send pid data out on exit */ |
416 | void taskstats_exit(struct task_struct *tsk, int group_dead) | 440 | void taskstats_exit(struct task_struct *tsk, int group_dead) |
417 | { | 441 | { |
@@ -433,7 +457,7 @@ void taskstats_exit(struct task_struct *tsk, int group_dead) | |||
433 | size = nla_total_size(sizeof(u32)) + | 457 | size = nla_total_size(sizeof(u32)) + |
434 | nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); | 458 | nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); |
435 | 459 | ||
436 | is_thread_group = (tsk->signal->stats != NULL); | 460 | is_thread_group = !!taskstats_tgid_alloc(tsk); |
437 | if (is_thread_group) { | 461 | if (is_thread_group) { |
438 | /* PID + STATS + TGID + STATS */ | 462 | /* PID + STATS + TGID + STATS */ |
439 | size = 2 * size; | 463 | size = 2 * size; |