| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Rickard=20M=C3=B6ller?= <rickard.moller@sony.com> |
| Date: Fri, 1 Nov 2019 14:20:46 +0100 |
| Subject: ANDROID: uid_sys_stats: avoid double accounting of dying threads |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| When a thread is being killed process_notifier() is called to record |
| the final accounting of the thread. But after that uid_cputime_show() |
| and add_uid_io_stats() can be called before the dying thread is |
| removed from the parent's thread_group resulting in double accounting. |
| |
| This can cause the user and system time for a given UID to move |
| backwards in /proc/uid_cputime/show_uid_stat. That gives negative delta |
| times in KernelCpuUidUserSysTimeReader.readDeltaImpl() and it logs |
| an error: |
| |
| "Negative user/sys time delta for UID=..." |
| |
| One consequence of which was incorrectly calculated power consumptions |
| in BatteryStats. |
| |
| With this change we avoid the double accounting by ignoring the thread |
| if it has the PF_EXITING flag set. |
| |
| Bug: 144366911 |
| |
| Change-Id: I6b929e8f558cd81ce1c00481c8b550d24877aa2c |
| Signed-off-by: Rickard Möller <rickard.moller@sony.com> |
| --- |
| drivers/misc/uid_sys_stats.c | 13 ++++++++++--- |
| 1 file changed, 10 insertions(+), 3 deletions(-) |
| |
| diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c |
| index 88dc1cd3a204..49974954d4f0 100644 |
| --- a/drivers/misc/uid_sys_stats.c |
| +++ b/drivers/misc/uid_sys_stats.c |
| @@ -358,9 +358,12 @@ static int uid_cputime_show(struct seq_file *m, void *v) |
| __func__, uid); |
| return -ENOMEM; |
| } |
| - task_cputime_adjusted(task, &utime, &stime); |
| - uid_entry->active_utime += utime; |
| - uid_entry->active_stime += stime; |
| + /* avoid double accounting of dying threads */ |
| + if (!(task->flags & PF_EXITING)) { |
| + task_cputime_adjusted(task, &utime, &stime); |
| + uid_entry->active_utime += utime; |
| + uid_entry->active_stime += stime; |
| + } |
| } while_each_thread(temp, task); |
| rcu_read_unlock(); |
| |
| @@ -453,6 +456,10 @@ static void add_uid_io_stats(struct uid_entry *uid_entry, |
| { |
| struct io_stats *io_slot = &uid_entry->io[slot]; |
| |
| + /* avoid double accounting of dying threads */ |
| + if (slot != UID_STATE_DEAD_TASKS && (task->flags & PF_EXITING)) |
| + return; |
| + |
| io_slot->read_bytes += task->ioac.read_bytes; |
| io_slot->write_bytes += compute_write_bytes(task); |
| io_slot->rchar += task->ioac.rchar; |