Skip to content

Commit bfac700

Browse files
oleg-nesterovIngo Molnar
authored andcommitted
sched: thread_group_cputime: Simplify, document the "alive" check
thread_group_cputime() looks as if it is rcu-safe, but in fact this was wrong until ea6d290 which pins task->signal to task_struct. It checks ->sighand != NULL under rcu, but this can't help if ->signal can go away. Fortunately the caller either holds ->siglock, or it is fastpath_timer_check() which uses current and checks exit_state == 0. - Since ea6d290 commit tsk->signal is stable, we can read it first and avoid the initialization from INIT_CPUTIME. - Even if tsk->signal is always valid, we still have to check it is safe to use next_thread() under rcu_read_lock(). Currently the code checks ->sighand != NULL, change it to use pid_alive() which is commonly used to ensure the task wasn't unhashed before we take rcu_read_lock(). Add the comment to explain this check. - Change the main loop to use the while_each_thread() helper. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <20100610230956.GA25921@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
1 parent 48286d5 commit bfac700

File tree

1 file changed

+7
-14
lines changed

1 file changed

+7
-14
lines changed

kernel/posix-cpu-timers.c

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -232,31 +232,24 @@ static int cpu_clock_sample(const clockid_t which_clock, struct task_struct *p,
232232

233233
void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times)
234234
{
235-
struct sighand_struct *sighand;
236-
struct signal_struct *sig;
235+
struct signal_struct *sig = tsk->signal;
237236
struct task_struct *t;
238237

239-
*times = INIT_CPUTIME;
238+
times->utime = sig->utime;
239+
times->stime = sig->stime;
240+
times->sum_exec_runtime = sig->sum_sched_runtime;
240241

241242
rcu_read_lock();
242-
sighand = rcu_dereference(tsk->sighand);
243-
if (!sighand)
243+
/* make sure we can trust tsk->thread_group list */
244+
if (!likely(pid_alive(tsk)))
244245
goto out;
245246

246-
sig = tsk->signal;
247-
248247
t = tsk;
249248
do {
250249
times->utime = cputime_add(times->utime, t->utime);
251250
times->stime = cputime_add(times->stime, t->stime);
252251
times->sum_exec_runtime += t->se.sum_exec_runtime;
253-
254-
t = next_thread(t);
255-
} while (t != tsk);
256-
257-
times->utime = cputime_add(times->utime, sig->utime);
258-
times->stime = cputime_add(times->stime, sig->stime);
259-
times->sum_exec_runtime += sig->sum_sched_runtime;
252+
} while_each_thread(tsk, t);
260253
out:
261254
rcu_read_unlock();
262255
}

0 commit comments

Comments
 (0)