|
@@ -288,18 +288,28 @@ void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times)
|
|
|
struct signal_struct *sig = tsk->signal;
|
|
|
cputime_t utime, stime;
|
|
|
struct task_struct *t;
|
|
|
-
|
|
|
- times->utime = sig->utime;
|
|
|
- times->stime = sig->stime;
|
|
|
- times->sum_exec_runtime = sig->sum_sched_runtime;
|
|
|
+ unsigned int seq, nextseq;
|
|
|
|
|
|
rcu_read_lock();
|
|
|
- for_each_thread(tsk, t) {
|
|
|
- task_cputime(t, &utime, &stime);
|
|
|
- times->utime += utime;
|
|
|
- times->stime += stime;
|
|
|
- times->sum_exec_runtime += task_sched_runtime(t);
|
|
|
- }
|
|
|
+ /* Attempt a lockless read on the first round. */
|
|
|
+ nextseq = 0;
|
|
|
+ do {
|
|
|
+ seq = nextseq;
|
|
|
+ read_seqbegin_or_lock(&sig->stats_lock, &seq);
|
|
|
+ times->utime = sig->utime;
|
|
|
+ times->stime = sig->stime;
|
|
|
+ times->sum_exec_runtime = sig->sum_sched_runtime;
|
|
|
+
|
|
|
+ for_each_thread(tsk, t) {
|
|
|
+ task_cputime(t, &utime, &stime);
|
|
|
+ times->utime += utime;
|
|
|
+ times->stime += stime;
|
|
|
+ times->sum_exec_runtime += task_sched_runtime(t);
|
|
|
+ }
|
|
|
+ /* If lockless access failed, take the lock. */
|
|
|
+ nextseq = 1;
|
|
|
+ } while (need_seqretry(&sig->stats_lock, seq));
|
|
|
+ done_seqretry(&sig->stats_lock, seq);
|
|
|
rcu_read_unlock();
|
|
|
}
|
|
|
|
|
@@ -611,9 +621,6 @@ void task_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
|
|
|
cputime_adjust(&cputime, &p->prev_cputime, ut, st);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Must be called with siglock held.
|
|
|
- */
|
|
|
void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
|
|
|
{
|
|
|
struct task_cputime cputime;
|