Skip to content

Commit 14e07f0

Browse files
committed
Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull scheduler fix from Thomas Gleixner: "A single fix for a cputime accounting regression which got introduced in the 4.11 cycle" * 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: sched/cputime: Fix ksoftirqd cputime accounting regression
2 parents 8c9a694 + 25e2d8c commit 14e07f0

File tree

2 files changed

+23
-13
lines changed

2 files changed

+23
-13
lines changed

kernel/sched/cputime.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,25 @@ void disable_sched_clock_irqtime(void)
3434
sched_clock_irqtime = 0;
3535
}
3636

37+
static void irqtime_account_delta(struct irqtime *irqtime, u64 delta,
38+
enum cpu_usage_stat idx)
39+
{
40+
u64 *cpustat = kcpustat_this_cpu->cpustat;
41+
42+
u64_stats_update_begin(&irqtime->sync);
43+
cpustat[idx] += delta;
44+
irqtime->total += delta;
45+
irqtime->tick_delta += delta;
46+
u64_stats_update_end(&irqtime->sync);
47+
}
48+
3749
/*
3850
* Called before incrementing preempt_count on {soft,}irq_enter
3951
* and before decrementing preempt_count on {soft,}irq_exit.
4052
*/
4153
void irqtime_account_irq(struct task_struct *curr)
4254
{
4355
struct irqtime *irqtime = this_cpu_ptr(&cpu_irqtime);
44-
u64 *cpustat = kcpustat_this_cpu->cpustat;
4556
s64 delta;
4657
int cpu;
4758

@@ -52,22 +63,16 @@ void irqtime_account_irq(struct task_struct *curr)
5263
delta = sched_clock_cpu(cpu) - irqtime->irq_start_time;
5364
irqtime->irq_start_time += delta;
5465

55-
u64_stats_update_begin(&irqtime->sync);
5666
/*
5767
* We do not account for softirq time from ksoftirqd here.
5868
* We want to continue accounting softirq time to ksoftirqd thread
5969
* in that case, so as not to confuse scheduler with a special task
6070
* that do not consume any time, but still wants to run.
6171
*/
62-
if (hardirq_count()) {
63-
cpustat[CPUTIME_IRQ] += delta;
64-
irqtime->tick_delta += delta;
65-
} else if (in_serving_softirq() && curr != this_cpu_ksoftirqd()) {
66-
cpustat[CPUTIME_SOFTIRQ] += delta;
67-
irqtime->tick_delta += delta;
68-
}
69-
70-
u64_stats_update_end(&irqtime->sync);
72+
if (hardirq_count())
73+
irqtime_account_delta(irqtime, delta, CPUTIME_IRQ);
74+
else if (in_serving_softirq() && curr != this_cpu_ksoftirqd())
75+
irqtime_account_delta(irqtime, delta, CPUTIME_SOFTIRQ);
7176
}
7277
EXPORT_SYMBOL_GPL(irqtime_account_irq);
7378

kernel/sched/sched.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,23 +1869,28 @@ static inline void nohz_balance_exit_idle(unsigned int cpu) { }
18691869

18701870
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
18711871
struct irqtime {
1872+
u64 total;
18721873
u64 tick_delta;
18731874
u64 irq_start_time;
18741875
struct u64_stats_sync sync;
18751876
};
18761877

18771878
DECLARE_PER_CPU(struct irqtime, cpu_irqtime);
18781879

1880+
/*
1881+
* Returns the irqtime minus the softirq time computed by ksoftirqd.
1882+
* Otherwise ksoftirqd's sum_exec_runtime is substracted its own runtime
1883+
* and never move forward.
1884+
*/
18791885
static inline u64 irq_time_read(int cpu)
18801886
{
18811887
struct irqtime *irqtime = &per_cpu(cpu_irqtime, cpu);
1882-
u64 *cpustat = kcpustat_cpu(cpu).cpustat;
18831888
unsigned int seq;
18841889
u64 total;
18851890

18861891
do {
18871892
seq = __u64_stats_fetch_begin(&irqtime->sync);
1888-
total = cpustat[CPUTIME_SOFTIRQ] + cpustat[CPUTIME_IRQ];
1893+
total = irqtime->total;
18891894
} while (__u64_stats_fetch_retry(&irqtime->sync, seq));
18901895

18911896
return total;

0 commit comments

Comments
 (0)