aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c90
1 files changed, 80 insertions, 10 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 9aaf567c5da5..751a7cc6a5cd 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -75,6 +75,9 @@
75#include <asm/tlb.h> 75#include <asm/tlb.h>
76#include <asm/irq_regs.h> 76#include <asm/irq_regs.h>
77#include <asm/mutex.h> 77#include <asm/mutex.h>
78#ifdef CONFIG_PARAVIRT
79#include <asm/paravirt.h>
80#endif
78 81
79#include "sched_cpupri.h" 82#include "sched_cpupri.h"
80#include "workqueue_sched.h" 83#include "workqueue_sched.h"
@@ -528,6 +531,12 @@ struct rq {
528#ifdef CONFIG_IRQ_TIME_ACCOUNTING 531#ifdef CONFIG_IRQ_TIME_ACCOUNTING
529 u64 prev_irq_time; 532 u64 prev_irq_time;
530#endif 533#endif
534#ifdef CONFIG_PARAVIRT
535 u64 prev_steal_time;
536#endif
537#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
538 u64 prev_steal_time_rq;
539#endif
531 540
532 /* calc_load related fields */ 541 /* calc_load related fields */
533 unsigned long calc_load_update; 542 unsigned long calc_load_update;
@@ -1921,10 +1930,28 @@ void account_system_vtime(struct task_struct *curr)
1921} 1930}
1922EXPORT_SYMBOL_GPL(account_system_vtime); 1931EXPORT_SYMBOL_GPL(account_system_vtime);
1923 1932
1924static void update_rq_clock_task(struct rq *rq, s64 delta) 1933#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
1934
1935#ifdef CONFIG_PARAVIRT
1936static inline u64 steal_ticks(u64 steal)
1925{ 1937{
1926 s64 irq_delta; 1938 if (unlikely(steal > NSEC_PER_SEC))
1939 return div_u64(steal, TICK_NSEC);
1927 1940
1941 return __iter_div_u64_rem(steal, TICK_NSEC, &steal);
1942}
1943#endif
1944
1945static void update_rq_clock_task(struct rq *rq, s64 delta)
1946{
1947/*
1948 * In theory, the compile should just see 0 here, and optimize out the call
1949 * to sched_rt_avg_update. But I don't trust it...
1950 */
1951#if defined(CONFIG_IRQ_TIME_ACCOUNTING) || defined(CONFIG_PARAVIRT_TIME_ACCOUNTING)
1952 s64 steal = 0, irq_delta = 0;
1953#endif
1954#ifdef CONFIG_IRQ_TIME_ACCOUNTING
1928 irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time; 1955 irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time;
1929 1956
1930 /* 1957 /*
@@ -1947,12 +1974,35 @@ static void update_rq_clock_task(struct rq *rq, s64 delta)
1947 1974
1948 rq->prev_irq_time += irq_delta; 1975 rq->prev_irq_time += irq_delta;
1949 delta -= irq_delta; 1976 delta -= irq_delta;
1977#endif
1978#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
1979 if (static_branch((&paravirt_steal_rq_enabled))) {
1980 u64 st;
1981
1982 steal = paravirt_steal_clock(cpu_of(rq));
1983 steal -= rq->prev_steal_time_rq;
1984
1985 if (unlikely(steal > delta))
1986 steal = delta;
1987
1988 st = steal_ticks(steal);
1989 steal = st * TICK_NSEC;
1990
1991 rq->prev_steal_time_rq += steal;
1992
1993 delta -= steal;
1994 }
1995#endif
1996
1950 rq->clock_task += delta; 1997 rq->clock_task += delta;
1951 1998
1952 if (irq_delta && sched_feat(NONIRQ_POWER)) 1999#if defined(CONFIG_IRQ_TIME_ACCOUNTING) || defined(CONFIG_PARAVIRT_TIME_ACCOUNTING)
1953 sched_rt_avg_update(rq, irq_delta); 2000 if ((irq_delta + steal) && sched_feat(NONTASK_POWER))
2001 sched_rt_avg_update(rq, irq_delta + steal);
2002#endif
1954} 2003}
1955 2004
2005#ifdef CONFIG_IRQ_TIME_ACCOUNTING
1956static int irqtime_account_hi_update(void) 2006static int irqtime_account_hi_update(void)
1957{ 2007{
1958 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 2008 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
@@ -1987,12 +2037,7 @@ static int irqtime_account_si_update(void)
1987 2037
1988#define sched_clock_irqtime (0) 2038#define sched_clock_irqtime (0)
1989 2039
1990static void update_rq_clock_task(struct rq *rq, s64 delta) 2040#endif
1991{
1992 rq->clock_task += delta;
1993}
1994
1995#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
1996 2041
1997#include "sched_idletask.c" 2042#include "sched_idletask.c"
1998#include "sched_fair.c" 2043#include "sched_fair.c"
@@ -3845,6 +3890,25 @@ void account_idle_time(cputime_t cputime)
3845 cpustat->idle = cputime64_add(cpustat->idle, cputime64); 3890 cpustat->idle = cputime64_add(cpustat->idle, cputime64);
3846} 3891}
3847 3892
3893static __always_inline bool steal_account_process_tick(void)
3894{
3895#ifdef CONFIG_PARAVIRT
3896 if (static_branch(&paravirt_steal_enabled)) {
3897 u64 steal, st = 0;
3898
3899 steal = paravirt_steal_clock(smp_processor_id());
3900 steal -= this_rq()->prev_steal_time;
3901
3902 st = steal_ticks(steal);
3903 this_rq()->prev_steal_time += st * TICK_NSEC;
3904
3905 account_steal_time(st);
3906 return st;
3907 }
3908#endif
3909 return false;
3910}
3911
3848#ifndef CONFIG_VIRT_CPU_ACCOUNTING 3912#ifndef CONFIG_VIRT_CPU_ACCOUNTING
3849 3913
3850#ifdef CONFIG_IRQ_TIME_ACCOUNTING 3914#ifdef CONFIG_IRQ_TIME_ACCOUNTING
@@ -3876,6 +3940,9 @@ static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
3876 cputime64_t tmp = cputime_to_cputime64(cputime_one_jiffy); 3940 cputime64_t tmp = cputime_to_cputime64(cputime_one_jiffy);
3877 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 3941 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
3878 3942
3943 if (steal_account_process_tick())
3944 return;
3945
3879 if (irqtime_account_hi_update()) { 3946 if (irqtime_account_hi_update()) {
3880 cpustat->irq = cputime64_add(cpustat->irq, tmp); 3947 cpustat->irq = cputime64_add(cpustat->irq, tmp);
3881 } else if (irqtime_account_si_update()) { 3948 } else if (irqtime_account_si_update()) {
@@ -3929,6 +3996,9 @@ void account_process_tick(struct task_struct *p, int user_tick)
3929 return; 3996 return;
3930 } 3997 }
3931 3998
3999 if (steal_account_process_tick())
4000 return;
4001
3932 if (user_tick) 4002 if (user_tick)
3933 account_user_time(p, cputime_one_jiffy, one_jiffy_scaled); 4003 account_user_time(p, cputime_one_jiffy, one_jiffy_scaled);
3934 else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET)) 4004 else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET))