From 953d6c5a9514ad28bfa5ff4f28c98f9f13f04070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rickard=20M=C3=B6ller?= Date: Fri, 1 Nov 2019 14:20:46 +0100 Subject: [PATCH] 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 --- 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;