@@ -485,13 +485,13 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
485485 int permitted ;
486486 struct mm_struct * mm ;
487487 unsigned long long start_time ;
488- unsigned long cmin_flt = 0 , cmaj_flt = 0 ;
489- unsigned long min_flt = 0 , maj_flt = 0 ;
490- u64 cutime , cstime , utime , stime ;
491- u64 cgtime , gtime ;
488+ unsigned long cmin_flt , cmaj_flt , min_flt , maj_flt ;
489+ u64 cutime , cstime , cgtime , utime , stime , gtime ;
492490 unsigned long rsslim = 0 ;
493491 unsigned long flags ;
494492 int exit_code = task -> exit_code ;
493+ struct signal_struct * sig = task -> signal ;
494+ unsigned int seq = 1 ;
495495
496496 state = * get_task_state (task );
497497 vsize = eip = esp = 0 ;
@@ -519,12 +519,8 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
519519
520520 sigemptyset (& sigign );
521521 sigemptyset (& sigcatch );
522- cutime = cstime = utime = stime = 0 ;
523- cgtime = gtime = 0 ;
524522
525523 if (lock_task_sighand (task , & flags )) {
526- struct signal_struct * sig = task -> signal ;
527-
528524 if (sig -> tty ) {
529525 struct pid * pgrp = tty_get_pgrp (sig -> tty );
530526 tty_pgrp = pid_nr_ns (pgrp , ns );
@@ -535,27 +531,9 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
535531 num_threads = get_nr_threads (task );
536532 collect_sigign_sigcatch (task , & sigign , & sigcatch );
537533
538- cmin_flt = sig -> cmin_flt ;
539- cmaj_flt = sig -> cmaj_flt ;
540- cutime = sig -> cutime ;
541- cstime = sig -> cstime ;
542- cgtime = sig -> cgtime ;
543534 rsslim = READ_ONCE (sig -> rlim [RLIMIT_RSS ].rlim_cur );
544535
545- /* add up live thread stats at the group level */
546536 if (whole ) {
547- struct task_struct * t = task ;
548- do {
549- min_flt += t -> min_flt ;
550- maj_flt += t -> maj_flt ;
551- gtime += task_gtime (t );
552- } while_each_thread (task , t );
553-
554- min_flt += sig -> min_flt ;
555- maj_flt += sig -> maj_flt ;
556- thread_group_cputime_adjusted (task , & utime , & stime );
557- gtime += sig -> gtime ;
558-
559537 if (sig -> flags & (SIGNAL_GROUP_EXIT | SIGNAL_STOP_STOPPED ))
560538 exit_code = sig -> group_exit_code ;
561539 }
@@ -569,10 +547,41 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
569547
570548 if (permitted && (!whole || num_threads < 2 ))
571549 wchan = !task_is_running (task );
572- if (!whole ) {
550+
551+ do {
552+ seq ++ ; /* 2 on the 1st/lockless path, otherwise odd */
553+ flags = read_seqbegin_or_lock_irqsave (& sig -> stats_lock , & seq );
554+
555+ cmin_flt = sig -> cmin_flt ;
556+ cmaj_flt = sig -> cmaj_flt ;
557+ cutime = sig -> cutime ;
558+ cstime = sig -> cstime ;
559+ cgtime = sig -> cgtime ;
560+
561+ if (whole ) {
562+ struct task_struct * t ;
563+
564+ min_flt = sig -> min_flt ;
565+ maj_flt = sig -> maj_flt ;
566+ gtime = sig -> gtime ;
567+
568+ rcu_read_lock ();
569+ __for_each_thread (sig , t ) {
570+ min_flt += t -> min_flt ;
571+ maj_flt += t -> maj_flt ;
572+ gtime += task_gtime (t );
573+ }
574+ rcu_read_unlock ();
575+ }
576+ } while (need_seqretry (& sig -> stats_lock , seq ));
577+ done_seqretry_irqrestore (& sig -> stats_lock , seq , flags );
578+
579+ if (whole ) {
580+ thread_group_cputime_adjusted (task , & utime , & stime );
581+ } else {
582+ task_cputime_adjusted (task , & utime , & stime );
573583 min_flt = task -> min_flt ;
574584 maj_flt = task -> maj_flt ;
575- task_cputime_adjusted (task , & utime , & stime );
576585 gtime = task_gtime (task );
577586 }
578587
0 commit comments