sched: Fix integer overflow in sched_update_nr_prod()
"int" type is used to hold the time difference between the successive updates to nr_run in sched_update_nr_prod(). This can result in overflow, if the function is called ~2.15 sec after it was called before. The most probable scenarios are when CPU is idle and hotplugged. But as we update the last_time of all possible CPUs in sched_get_nr_running_avg() periodically from a deferrable timer context (core_ctl module), this overflow is observed only when the system is completely idle for long time. When this overflow happens we hit a BUG_ON() in sched_get_nr_running_avg(). Use "u64" type instead of "int" for holding the time difference and add additional BUG_ON() to catch the instances where sched_clock() returns a backward value. Change-Id: I284abb5889ceb8cf9cc689c79ed69422a0e74986 Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
This commit is contained in:
parent
9ae0217aa6
commit
e593048d81
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2012, 2015, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2012, 2015-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -60,17 +60,17 @@ void sched_get_nr_running_avg(int *avg, int *iowait_avg, int *big_avg)
|
|||
|
||||
spin_lock_irqsave(&per_cpu(nr_lock, cpu), flags);
|
||||
curr_time = sched_clock();
|
||||
diff = curr_time - per_cpu(last_time, cpu);
|
||||
BUG_ON((s64)diff < 0);
|
||||
|
||||
tmp_avg += per_cpu(nr_prod_sum, cpu);
|
||||
tmp_avg += per_cpu(nr, cpu) *
|
||||
(curr_time - per_cpu(last_time, cpu));
|
||||
tmp_avg += per_cpu(nr, cpu) * diff;
|
||||
|
||||
tmp_big_avg += per_cpu(nr_big_prod_sum, cpu);
|
||||
tmp_big_avg += nr_eligible_big_tasks(cpu) *
|
||||
(curr_time - per_cpu(last_time, cpu));
|
||||
tmp_big_avg += nr_eligible_big_tasks(cpu) * diff;
|
||||
|
||||
tmp_iowait += per_cpu(iowait_prod_sum, cpu);
|
||||
tmp_iowait += nr_iowait_cpu(cpu) *
|
||||
(curr_time - per_cpu(last_time, cpu));
|
||||
tmp_iowait += nr_iowait_cpu(cpu) * diff;
|
||||
|
||||
per_cpu(last_time, cpu) = curr_time;
|
||||
|
||||
|
@ -107,14 +107,15 @@ EXPORT_SYMBOL(sched_get_nr_running_avg);
|
|||
*/
|
||||
void sched_update_nr_prod(int cpu, long delta, bool inc)
|
||||
{
|
||||
int diff;
|
||||
s64 curr_time;
|
||||
u64 diff;
|
||||
u64 curr_time;
|
||||
unsigned long flags, nr_running;
|
||||
|
||||
spin_lock_irqsave(&per_cpu(nr_lock, cpu), flags);
|
||||
nr_running = per_cpu(nr, cpu);
|
||||
curr_time = sched_clock();
|
||||
diff = curr_time - per_cpu(last_time, cpu);
|
||||
BUG_ON((s64)diff < 0);
|
||||
per_cpu(last_time, cpu) = curr_time;
|
||||
per_cpu(nr, cpu) = nr_running + (inc ? delta : -delta);
|
||||
|
||||
|
|
Loading…
Reference in New Issue