Allocate ->signal->stats on demand in taskstats_exit(), this allows us to remove taskstats_tgid_alloc() (the last non-trivial inline) from taskstat's public interface.
Showing the changes to kernel/taskstats.c (1 of 3 files). Show all
Unified · Split
| @@ -412,6 +412,30 @@ err: · 411 unmodified lines | ||
| 412 | 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 | 439 | /* Send pid data out on exit */ |
| 416 | 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) · 15 unmodified lines | ||
| 433 | 457 | size = nla_total_size(sizeof(u32)) + |
| 434 | 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 | 461 | if (is_thread_group) { |
| 438 | 462 | /* PID + STATS + TGID + STATS */ |
| 439 | 463 | size = 2 * size; |