blob: 9bb8ed0dae02677ffa96a60971e111c52951f731 [file] [log] [blame]
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;