173fbec60SFrederic Weisbecker #include <linux/export.h> 273fbec60SFrederic Weisbecker #include <linux/sched.h> 373fbec60SFrederic Weisbecker #include <linux/tsacct_kern.h> 473fbec60SFrederic Weisbecker #include <linux/kernel_stat.h> 573fbec60SFrederic Weisbecker #include <linux/static_key.h> 6abf917cdSFrederic Weisbecker #include <linux/context_tracking.h> 732ef5517SIngo Molnar #include <linux/sched/cputime.h> 873fbec60SFrederic Weisbecker #include "sched.h" 973fbec60SFrederic Weisbecker 1073fbec60SFrederic Weisbecker #ifdef CONFIG_IRQ_TIME_ACCOUNTING 1173fbec60SFrederic Weisbecker 1273fbec60SFrederic Weisbecker /* 1373fbec60SFrederic Weisbecker * There are no locks covering percpu hardirq/softirq time. 14bf9fae9fSFrederic Weisbecker * They are only modified in vtime_account, on corresponding CPU 1573fbec60SFrederic Weisbecker * with interrupts disabled. So, writes are safe. 1673fbec60SFrederic Weisbecker * They are read and saved off onto struct rq in update_rq_clock(). 1773fbec60SFrederic Weisbecker * This may result in other CPU reading this CPU's irq time and can 18bf9fae9fSFrederic Weisbecker * race with irq/vtime_account on this CPU. We would either get old 1973fbec60SFrederic Weisbecker * or new value with a side effect of accounting a slice of irq time to wrong 2073fbec60SFrederic Weisbecker * task when irq is in progress while we read rq->clock. That is a worthy 2173fbec60SFrederic Weisbecker * compromise in place of having locks on each irq in account_system_time. 2273fbec60SFrederic Weisbecker */ 2319d23dbfSFrederic Weisbecker DEFINE_PER_CPU(struct irqtime, cpu_irqtime); 2473fbec60SFrederic Weisbecker 2573fbec60SFrederic Weisbecker static int sched_clock_irqtime; 2673fbec60SFrederic Weisbecker 2773fbec60SFrederic Weisbecker void enable_sched_clock_irqtime(void) 2873fbec60SFrederic Weisbecker { 2973fbec60SFrederic Weisbecker sched_clock_irqtime = 1; 3073fbec60SFrederic Weisbecker } 3173fbec60SFrederic Weisbecker 3273fbec60SFrederic Weisbecker void disable_sched_clock_irqtime(void) 3373fbec60SFrederic Weisbecker { 3473fbec60SFrederic Weisbecker sched_clock_irqtime = 0; 3573fbec60SFrederic Weisbecker } 3673fbec60SFrederic Weisbecker 3725e2d8c1SFrederic Weisbecker static void irqtime_account_delta(struct irqtime *irqtime, u64 delta, 3825e2d8c1SFrederic Weisbecker enum cpu_usage_stat idx) 3925e2d8c1SFrederic Weisbecker { 4025e2d8c1SFrederic Weisbecker u64 *cpustat = kcpustat_this_cpu->cpustat; 4125e2d8c1SFrederic Weisbecker 4225e2d8c1SFrederic Weisbecker u64_stats_update_begin(&irqtime->sync); 4325e2d8c1SFrederic Weisbecker cpustat[idx] += delta; 4425e2d8c1SFrederic Weisbecker irqtime->total += delta; 4525e2d8c1SFrederic Weisbecker irqtime->tick_delta += delta; 4625e2d8c1SFrederic Weisbecker u64_stats_update_end(&irqtime->sync); 4725e2d8c1SFrederic Weisbecker } 4825e2d8c1SFrederic Weisbecker 4973fbec60SFrederic Weisbecker /* 5073fbec60SFrederic Weisbecker * Called before incrementing preempt_count on {soft,}irq_enter 5173fbec60SFrederic Weisbecker * and before decrementing preempt_count on {soft,}irq_exit. 5273fbec60SFrederic Weisbecker */ 533e1df4f5SFrederic Weisbecker void irqtime_account_irq(struct task_struct *curr) 5473fbec60SFrederic Weisbecker { 5519d23dbfSFrederic Weisbecker struct irqtime *irqtime = this_cpu_ptr(&cpu_irqtime); 5673fbec60SFrederic Weisbecker s64 delta; 5773fbec60SFrederic Weisbecker int cpu; 5873fbec60SFrederic Weisbecker 5973fbec60SFrederic Weisbecker if (!sched_clock_irqtime) 6073fbec60SFrederic Weisbecker return; 6173fbec60SFrederic Weisbecker 6273fbec60SFrederic Weisbecker cpu = smp_processor_id(); 6319d23dbfSFrederic Weisbecker delta = sched_clock_cpu(cpu) - irqtime->irq_start_time; 6419d23dbfSFrederic Weisbecker irqtime->irq_start_time += delta; 6573fbec60SFrederic Weisbecker 6673fbec60SFrederic Weisbecker /* 6773fbec60SFrederic Weisbecker * We do not account for softirq time from ksoftirqd here. 6873fbec60SFrederic Weisbecker * We want to continue accounting softirq time to ksoftirqd thread 6973fbec60SFrederic Weisbecker * in that case, so as not to confuse scheduler with a special task 7073fbec60SFrederic Weisbecker * that do not consume any time, but still wants to run. 7173fbec60SFrederic Weisbecker */ 7225e2d8c1SFrederic Weisbecker if (hardirq_count()) 7325e2d8c1SFrederic Weisbecker irqtime_account_delta(irqtime, delta, CPUTIME_IRQ); 7425e2d8c1SFrederic Weisbecker else if (in_serving_softirq() && curr != this_cpu_ksoftirqd()) 7525e2d8c1SFrederic Weisbecker irqtime_account_delta(irqtime, delta, CPUTIME_SOFTIRQ); 7673fbec60SFrederic Weisbecker } 773e1df4f5SFrederic Weisbecker EXPORT_SYMBOL_GPL(irqtime_account_irq); 7873fbec60SFrederic Weisbecker 792b1f967dSFrederic Weisbecker static u64 irqtime_tick_accounted(u64 maxtime) 8073fbec60SFrederic Weisbecker { 81a499a5a1SFrederic Weisbecker struct irqtime *irqtime = this_cpu_ptr(&cpu_irqtime); 822b1f967dSFrederic Weisbecker u64 delta; 8373fbec60SFrederic Weisbecker 842b1f967dSFrederic Weisbecker delta = min(irqtime->tick_delta, maxtime); 852b1f967dSFrederic Weisbecker irqtime->tick_delta -= delta; 862810f611SFrederic Weisbecker 87a499a5a1SFrederic Weisbecker return delta; 8873fbec60SFrederic Weisbecker } 8973fbec60SFrederic Weisbecker 9073fbec60SFrederic Weisbecker #else /* CONFIG_IRQ_TIME_ACCOUNTING */ 9173fbec60SFrederic Weisbecker 9273fbec60SFrederic Weisbecker #define sched_clock_irqtime (0) 9373fbec60SFrederic Weisbecker 942b1f967dSFrederic Weisbecker static u64 irqtime_tick_accounted(u64 dummy) 9557430218SRik van Riel { 9657430218SRik van Riel return 0; 9757430218SRik van Riel } 9857430218SRik van Riel 9973fbec60SFrederic Weisbecker #endif /* !CONFIG_IRQ_TIME_ACCOUNTING */ 10073fbec60SFrederic Weisbecker 10173fbec60SFrederic Weisbecker static inline void task_group_account_field(struct task_struct *p, int index, 10273fbec60SFrederic Weisbecker u64 tmp) 10373fbec60SFrederic Weisbecker { 10473fbec60SFrederic Weisbecker /* 10573fbec60SFrederic Weisbecker * Since all updates are sure to touch the root cgroup, we 10673fbec60SFrederic Weisbecker * get ourselves ahead and touch it first. If the root cgroup 10773fbec60SFrederic Weisbecker * is the only cgroup, then nothing else should be necessary. 10873fbec60SFrederic Weisbecker * 10973fbec60SFrederic Weisbecker */ 110a4f61cc0SChristoph Lameter __this_cpu_add(kernel_cpustat.cpustat[index], tmp); 11173fbec60SFrederic Weisbecker 1121966aaf7SLi Zefan cpuacct_account_field(p, index, tmp); 11373fbec60SFrederic Weisbecker } 11473fbec60SFrederic Weisbecker 11573fbec60SFrederic Weisbecker /* 11673fbec60SFrederic Weisbecker * Account user cpu time to a process. 11773fbec60SFrederic Weisbecker * @p: the process that the cpu time gets accounted to 11873fbec60SFrederic Weisbecker * @cputime: the cpu time spent in user space since the last update 11973fbec60SFrederic Weisbecker */ 12023244a5cSFrederic Weisbecker void account_user_time(struct task_struct *p, u64 cputime) 12173fbec60SFrederic Weisbecker { 12273fbec60SFrederic Weisbecker int index; 12373fbec60SFrederic Weisbecker 12473fbec60SFrederic Weisbecker /* Add user time to process. */ 12523244a5cSFrederic Weisbecker p->utime += cputime; 12623244a5cSFrederic Weisbecker account_group_user_time(p, cputime); 12773fbec60SFrederic Weisbecker 128d0ea0268SDongsheng Yang index = (task_nice(p) > 0) ? CPUTIME_NICE : CPUTIME_USER; 12973fbec60SFrederic Weisbecker 13073fbec60SFrederic Weisbecker /* Add user time to cpustat. */ 13123244a5cSFrederic Weisbecker task_group_account_field(p, index, cputime); 13273fbec60SFrederic Weisbecker 13373fbec60SFrederic Weisbecker /* Account for user time used */ 1346fac4829SFrederic Weisbecker acct_account_cputime(p); 13573fbec60SFrederic Weisbecker } 13673fbec60SFrederic Weisbecker 13773fbec60SFrederic Weisbecker /* 13873fbec60SFrederic Weisbecker * Account guest cpu time to a process. 13973fbec60SFrederic Weisbecker * @p: the process that the cpu time gets accounted to 14073fbec60SFrederic Weisbecker * @cputime: the cpu time spent in virtual machine since the last update 14173fbec60SFrederic Weisbecker */ 142fb8b049cSFrederic Weisbecker void account_guest_time(struct task_struct *p, u64 cputime) 14373fbec60SFrederic Weisbecker { 14473fbec60SFrederic Weisbecker u64 *cpustat = kcpustat_this_cpu->cpustat; 14573fbec60SFrederic Weisbecker 14673fbec60SFrederic Weisbecker /* Add guest time to process. */ 147fb8b049cSFrederic Weisbecker p->utime += cputime; 148fb8b049cSFrederic Weisbecker account_group_user_time(p, cputime); 149fb8b049cSFrederic Weisbecker p->gtime += cputime; 15073fbec60SFrederic Weisbecker 15173fbec60SFrederic Weisbecker /* Add guest time to cpustat. */ 152d0ea0268SDongsheng Yang if (task_nice(p) > 0) { 153fb8b049cSFrederic Weisbecker cpustat[CPUTIME_NICE] += cputime; 154fb8b049cSFrederic Weisbecker cpustat[CPUTIME_GUEST_NICE] += cputime; 15573fbec60SFrederic Weisbecker } else { 156fb8b049cSFrederic Weisbecker cpustat[CPUTIME_USER] += cputime; 157fb8b049cSFrederic Weisbecker cpustat[CPUTIME_GUEST] += cputime; 15873fbec60SFrederic Weisbecker } 15973fbec60SFrederic Weisbecker } 16073fbec60SFrederic Weisbecker 16173fbec60SFrederic Weisbecker /* 16273fbec60SFrederic Weisbecker * Account system cpu time to a process and desired cpustat field 16373fbec60SFrederic Weisbecker * @p: the process that the cpu time gets accounted to 16473fbec60SFrederic Weisbecker * @cputime: the cpu time spent in kernel space since the last update 16540565b5aSStanislaw Gruszka * @index: pointer to cpustat field that has to be updated 16673fbec60SFrederic Weisbecker */ 167c31cc6a5SFrederic Weisbecker void account_system_index_time(struct task_struct *p, 168fb8b049cSFrederic Weisbecker u64 cputime, enum cpu_usage_stat index) 16973fbec60SFrederic Weisbecker { 17073fbec60SFrederic Weisbecker /* Add system time to process. */ 171fb8b049cSFrederic Weisbecker p->stime += cputime; 172fb8b049cSFrederic Weisbecker account_group_system_time(p, cputime); 17373fbec60SFrederic Weisbecker 17473fbec60SFrederic Weisbecker /* Add system time to cpustat. */ 175fb8b049cSFrederic Weisbecker task_group_account_field(p, index, cputime); 17673fbec60SFrederic Weisbecker 17773fbec60SFrederic Weisbecker /* Account for system time used */ 1786fac4829SFrederic Weisbecker acct_account_cputime(p); 17973fbec60SFrederic Weisbecker } 18073fbec60SFrederic Weisbecker 18173fbec60SFrederic Weisbecker /* 18273fbec60SFrederic Weisbecker * Account system cpu time to a process. 18373fbec60SFrederic Weisbecker * @p: the process that the cpu time gets accounted to 18473fbec60SFrederic Weisbecker * @hardirq_offset: the offset to subtract from hardirq_count() 18573fbec60SFrederic Weisbecker * @cputime: the cpu time spent in kernel space since the last update 18673fbec60SFrederic Weisbecker */ 187fb8b049cSFrederic Weisbecker void account_system_time(struct task_struct *p, int hardirq_offset, u64 cputime) 18873fbec60SFrederic Weisbecker { 18973fbec60SFrederic Weisbecker int index; 19073fbec60SFrederic Weisbecker 19173fbec60SFrederic Weisbecker if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) { 19240565b5aSStanislaw Gruszka account_guest_time(p, cputime); 19373fbec60SFrederic Weisbecker return; 19473fbec60SFrederic Weisbecker } 19573fbec60SFrederic Weisbecker 19673fbec60SFrederic Weisbecker if (hardirq_count() - hardirq_offset) 19773fbec60SFrederic Weisbecker index = CPUTIME_IRQ; 19873fbec60SFrederic Weisbecker else if (in_serving_softirq()) 19973fbec60SFrederic Weisbecker index = CPUTIME_SOFTIRQ; 20073fbec60SFrederic Weisbecker else 20173fbec60SFrederic Weisbecker index = CPUTIME_SYSTEM; 20273fbec60SFrederic Weisbecker 203c31cc6a5SFrederic Weisbecker account_system_index_time(p, cputime, index); 20473fbec60SFrederic Weisbecker } 20573fbec60SFrederic Weisbecker 20673fbec60SFrederic Weisbecker /* 20773fbec60SFrederic Weisbecker * Account for involuntary wait time. 20873fbec60SFrederic Weisbecker * @cputime: the cpu time spent in involuntary wait 20973fbec60SFrederic Weisbecker */ 210be9095edSFrederic Weisbecker void account_steal_time(u64 cputime) 21173fbec60SFrederic Weisbecker { 21273fbec60SFrederic Weisbecker u64 *cpustat = kcpustat_this_cpu->cpustat; 21373fbec60SFrederic Weisbecker 214be9095edSFrederic Weisbecker cpustat[CPUTIME_STEAL] += cputime; 21573fbec60SFrederic Weisbecker } 21673fbec60SFrederic Weisbecker 21773fbec60SFrederic Weisbecker /* 21873fbec60SFrederic Weisbecker * Account for idle time. 21973fbec60SFrederic Weisbecker * @cputime: the cpu time spent in idle wait 22073fbec60SFrederic Weisbecker */ 22118b43a9bSFrederic Weisbecker void account_idle_time(u64 cputime) 22273fbec60SFrederic Weisbecker { 22373fbec60SFrederic Weisbecker u64 *cpustat = kcpustat_this_cpu->cpustat; 22473fbec60SFrederic Weisbecker struct rq *rq = this_rq(); 22573fbec60SFrederic Weisbecker 22673fbec60SFrederic Weisbecker if (atomic_read(&rq->nr_iowait) > 0) 22718b43a9bSFrederic Weisbecker cpustat[CPUTIME_IOWAIT] += cputime; 22873fbec60SFrederic Weisbecker else 22918b43a9bSFrederic Weisbecker cpustat[CPUTIME_IDLE] += cputime; 23073fbec60SFrederic Weisbecker } 23173fbec60SFrederic Weisbecker 23203cbc732SWanpeng Li /* 23303cbc732SWanpeng Li * When a guest is interrupted for a longer amount of time, missed clock 23403cbc732SWanpeng Li * ticks are not redelivered later. Due to that, this function may on 23503cbc732SWanpeng Li * occasion account more time than the calling functions think elapsed. 23603cbc732SWanpeng Li */ 2372b1f967dSFrederic Weisbecker static __always_inline u64 steal_account_process_time(u64 maxtime) 23873fbec60SFrederic Weisbecker { 23973fbec60SFrederic Weisbecker #ifdef CONFIG_PARAVIRT 24073fbec60SFrederic Weisbecker if (static_key_false(¶virt_steal_enabled)) { 2412b1f967dSFrederic Weisbecker u64 steal; 24273fbec60SFrederic Weisbecker 24373fbec60SFrederic Weisbecker steal = paravirt_steal_clock(smp_processor_id()); 24473fbec60SFrederic Weisbecker steal -= this_rq()->prev_steal_time; 2452b1f967dSFrederic Weisbecker steal = min(steal, maxtime); 2462b1f967dSFrederic Weisbecker account_steal_time(steal); 2472b1f967dSFrederic Weisbecker this_rq()->prev_steal_time += steal; 24873fbec60SFrederic Weisbecker 2492b1f967dSFrederic Weisbecker return steal; 25073fbec60SFrederic Weisbecker } 25173fbec60SFrederic Weisbecker #endif 252807e5b80SWanpeng Li return 0; 25373fbec60SFrederic Weisbecker } 25473fbec60SFrederic Weisbecker 255a634f933SFrederic Weisbecker /* 25657430218SRik van Riel * Account how much elapsed time was spent in steal, irq, or softirq time. 25757430218SRik van Riel */ 2582b1f967dSFrederic Weisbecker static inline u64 account_other_time(u64 max) 25957430218SRik van Riel { 2602b1f967dSFrederic Weisbecker u64 accounted; 26157430218SRik van Riel 2622810f611SFrederic Weisbecker /* Shall be converted to a lockdep-enabled lightweight check */ 2632810f611SFrederic Weisbecker WARN_ON_ONCE(!irqs_disabled()); 2642810f611SFrederic Weisbecker 26557430218SRik van Riel accounted = steal_account_process_time(max); 26657430218SRik van Riel 26757430218SRik van Riel if (accounted < max) 268a499a5a1SFrederic Weisbecker accounted += irqtime_tick_accounted(max - accounted); 26957430218SRik van Riel 27057430218SRik van Riel return accounted; 27157430218SRik van Riel } 27257430218SRik van Riel 273a1eb1411SStanislaw Gruszka #ifdef CONFIG_64BIT 274a1eb1411SStanislaw Gruszka static inline u64 read_sum_exec_runtime(struct task_struct *t) 275a1eb1411SStanislaw Gruszka { 276a1eb1411SStanislaw Gruszka return t->se.sum_exec_runtime; 277a1eb1411SStanislaw Gruszka } 278a1eb1411SStanislaw Gruszka #else 279a1eb1411SStanislaw Gruszka static u64 read_sum_exec_runtime(struct task_struct *t) 280a1eb1411SStanislaw Gruszka { 281a1eb1411SStanislaw Gruszka u64 ns; 282a1eb1411SStanislaw Gruszka struct rq_flags rf; 283a1eb1411SStanislaw Gruszka struct rq *rq; 284a1eb1411SStanislaw Gruszka 285a1eb1411SStanislaw Gruszka rq = task_rq_lock(t, &rf); 286a1eb1411SStanislaw Gruszka ns = t->se.sum_exec_runtime; 287a1eb1411SStanislaw Gruszka task_rq_unlock(rq, t, &rf); 288a1eb1411SStanislaw Gruszka 289a1eb1411SStanislaw Gruszka return ns; 290a1eb1411SStanislaw Gruszka } 291a1eb1411SStanislaw Gruszka #endif 292a1eb1411SStanislaw Gruszka 29357430218SRik van Riel /* 294a634f933SFrederic Weisbecker * Accumulate raw cputime values of dead tasks (sig->[us]time) and live 295a634f933SFrederic Weisbecker * tasks (sum on group iteration) belonging to @tsk's group. 296a634f933SFrederic Weisbecker */ 297a634f933SFrederic Weisbecker void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times) 298a634f933SFrederic Weisbecker { 299a634f933SFrederic Weisbecker struct signal_struct *sig = tsk->signal; 3005613fda9SFrederic Weisbecker u64 utime, stime; 301a634f933SFrederic Weisbecker struct task_struct *t; 302e78c3496SRik van Riel unsigned int seq, nextseq; 3039c368b5bSRik van Riel unsigned long flags; 304a634f933SFrederic Weisbecker 305a1eb1411SStanislaw Gruszka /* 306a1eb1411SStanislaw Gruszka * Update current task runtime to account pending time since last 307a1eb1411SStanislaw Gruszka * scheduler action or thread_group_cputime() call. This thread group 308a1eb1411SStanislaw Gruszka * might have other running tasks on different CPUs, but updating 309a1eb1411SStanislaw Gruszka * their runtime can affect syscall performance, so we skip account 310a1eb1411SStanislaw Gruszka * those pending times and rely only on values updated on tick or 311a1eb1411SStanislaw Gruszka * other scheduler action. 312a1eb1411SStanislaw Gruszka */ 313a1eb1411SStanislaw Gruszka if (same_thread_group(current, tsk)) 314a1eb1411SStanislaw Gruszka (void) task_sched_runtime(current); 315a1eb1411SStanislaw Gruszka 316e78c3496SRik van Riel rcu_read_lock(); 317e78c3496SRik van Riel /* Attempt a lockless read on the first round. */ 318e78c3496SRik van Riel nextseq = 0; 319e78c3496SRik van Riel do { 320e78c3496SRik van Riel seq = nextseq; 3219c368b5bSRik van Riel flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq); 322a634f933SFrederic Weisbecker times->utime = sig->utime; 323a634f933SFrederic Weisbecker times->stime = sig->stime; 324a634f933SFrederic Weisbecker times->sum_exec_runtime = sig->sum_sched_runtime; 325a634f933SFrederic Weisbecker 3261e4dda08SOleg Nesterov for_each_thread(tsk, t) { 327e614b333SStanislaw Gruszka task_cputime(t, &utime, &stime); 3286fac4829SFrederic Weisbecker times->utime += utime; 3296fac4829SFrederic Weisbecker times->stime += stime; 330a1eb1411SStanislaw Gruszka times->sum_exec_runtime += read_sum_exec_runtime(t); 3311e4dda08SOleg Nesterov } 332e78c3496SRik van Riel /* If lockless access failed, take the lock. */ 333e78c3496SRik van Riel nextseq = 1; 334e78c3496SRik van Riel } while (need_seqretry(&sig->stats_lock, seq)); 3359c368b5bSRik van Riel done_seqretry_irqrestore(&sig->stats_lock, seq, flags); 336a634f933SFrederic Weisbecker rcu_read_unlock(); 337a634f933SFrederic Weisbecker } 338a634f933SFrederic Weisbecker 33973fbec60SFrederic Weisbecker #ifdef CONFIG_IRQ_TIME_ACCOUNTING 34073fbec60SFrederic Weisbecker /* 34173fbec60SFrederic Weisbecker * Account a tick to a process and cpustat 34273fbec60SFrederic Weisbecker * @p: the process that the cpu time gets accounted to 34373fbec60SFrederic Weisbecker * @user_tick: is the tick from userspace 34473fbec60SFrederic Weisbecker * @rq: the pointer to rq 34573fbec60SFrederic Weisbecker * 34673fbec60SFrederic Weisbecker * Tick demultiplexing follows the order 34773fbec60SFrederic Weisbecker * - pending hardirq update 34873fbec60SFrederic Weisbecker * - pending softirq update 34973fbec60SFrederic Weisbecker * - user_time 35073fbec60SFrederic Weisbecker * - idle_time 35173fbec60SFrederic Weisbecker * - system time 35273fbec60SFrederic Weisbecker * - check for guest_time 35373fbec60SFrederic Weisbecker * - else account as system_time 35473fbec60SFrederic Weisbecker * 35573fbec60SFrederic Weisbecker * Check for hardirq is done both for system and user time as there is 35673fbec60SFrederic Weisbecker * no timer going off while we are on hardirq and hence we may never get an 35773fbec60SFrederic Weisbecker * opportunity to update it solely in system time. 35873fbec60SFrederic Weisbecker * p->stime and friends are only updated on system time and not on irq 35973fbec60SFrederic Weisbecker * softirq as those do not count in task exec_runtime any more. 36073fbec60SFrederic Weisbecker */ 36173fbec60SFrederic Weisbecker static void irqtime_account_process_tick(struct task_struct *p, int user_tick, 3622d513868SThomas Gleixner struct rq *rq, int ticks) 36373fbec60SFrederic Weisbecker { 3642b1f967dSFrederic Weisbecker u64 other, cputime = TICK_NSEC * ticks; 36573fbec60SFrederic Weisbecker 36657430218SRik van Riel /* 36757430218SRik van Riel * When returning from idle, many ticks can get accounted at 36857430218SRik van Riel * once, including some ticks of steal, irq, and softirq time. 36957430218SRik van Riel * Subtract those ticks from the amount of time accounted to 37057430218SRik van Riel * idle, or potentially user or system time. Due to rounding, 37157430218SRik van Riel * other time can exceed ticks occasionally. 37257430218SRik van Riel */ 37303cbc732SWanpeng Li other = account_other_time(ULONG_MAX); 3742b1f967dSFrederic Weisbecker if (other >= cputime) 37573fbec60SFrederic Weisbecker return; 37623244a5cSFrederic Weisbecker 3772b1f967dSFrederic Weisbecker cputime -= other; 37873fbec60SFrederic Weisbecker 37957430218SRik van Riel if (this_cpu_ksoftirqd() == p) { 38073fbec60SFrederic Weisbecker /* 38173fbec60SFrederic Weisbecker * ksoftirqd time do not get accounted in cpu_softirq_time. 38273fbec60SFrederic Weisbecker * So, we have to handle it separately here. 38373fbec60SFrederic Weisbecker * Also, p->stime needs to be updated for ksoftirqd. 38473fbec60SFrederic Weisbecker */ 385fb8b049cSFrederic Weisbecker account_system_index_time(p, cputime, CPUTIME_SOFTIRQ); 38673fbec60SFrederic Weisbecker } else if (user_tick) { 38740565b5aSStanislaw Gruszka account_user_time(p, cputime); 38873fbec60SFrederic Weisbecker } else if (p == rq->idle) { 38918b43a9bSFrederic Weisbecker account_idle_time(cputime); 39073fbec60SFrederic Weisbecker } else if (p->flags & PF_VCPU) { /* System time or guest time */ 391fb8b049cSFrederic Weisbecker account_guest_time(p, cputime); 39273fbec60SFrederic Weisbecker } else { 393fb8b049cSFrederic Weisbecker account_system_index_time(p, cputime, CPUTIME_SYSTEM); 39473fbec60SFrederic Weisbecker } 39573fbec60SFrederic Weisbecker } 39673fbec60SFrederic Weisbecker 39773fbec60SFrederic Weisbecker static void irqtime_account_idle_ticks(int ticks) 39873fbec60SFrederic Weisbecker { 39973fbec60SFrederic Weisbecker struct rq *rq = this_rq(); 40073fbec60SFrederic Weisbecker 4012d513868SThomas Gleixner irqtime_account_process_tick(current, 0, rq, ticks); 40273fbec60SFrederic Weisbecker } 40373fbec60SFrederic Weisbecker #else /* CONFIG_IRQ_TIME_ACCOUNTING */ 4043f4724eaSFrederic Weisbecker static inline void irqtime_account_idle_ticks(int ticks) {} 4053f4724eaSFrederic Weisbecker static inline void irqtime_account_process_tick(struct task_struct *p, int user_tick, 4062d513868SThomas Gleixner struct rq *rq, int nr_ticks) {} 40773fbec60SFrederic Weisbecker #endif /* CONFIG_IRQ_TIME_ACCOUNTING */ 40873fbec60SFrederic Weisbecker 40973fbec60SFrederic Weisbecker /* 41073fbec60SFrederic Weisbecker * Use precise platform statistics if available: 41173fbec60SFrederic Weisbecker */ 41273fbec60SFrederic Weisbecker #ifdef CONFIG_VIRT_CPU_ACCOUNTING 413a7e1a9e3SFrederic Weisbecker 414e3942ba0SFrederic Weisbecker #ifndef __ARCH_HAS_VTIME_TASK_SWITCH 415b0493406SFrederic Weisbecker void vtime_common_task_switch(struct task_struct *prev) 416e3942ba0SFrederic Weisbecker { 417e3942ba0SFrederic Weisbecker if (is_idle_task(prev)) 418e3942ba0SFrederic Weisbecker vtime_account_idle(prev); 419e3942ba0SFrederic Weisbecker else 420e3942ba0SFrederic Weisbecker vtime_account_system(prev); 421e3942ba0SFrederic Weisbecker 422c8d7dabfSFrederic Weisbecker vtime_flush(prev); 423e3942ba0SFrederic Weisbecker arch_vtime_task_switch(prev); 424e3942ba0SFrederic Weisbecker } 425e3942ba0SFrederic Weisbecker #endif 42611113334SFrederic Weisbecker 4270cfdf9a1SFrederic Weisbecker #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ 4280cfdf9a1SFrederic Weisbecker 4290cfdf9a1SFrederic Weisbecker 4300cfdf9a1SFrederic Weisbecker #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE 431a7e1a9e3SFrederic Weisbecker /* 432a7e1a9e3SFrederic Weisbecker * Archs that account the whole time spent in the idle task 433a7e1a9e3SFrederic Weisbecker * (outside irq) as idle time can rely on this and just implement 434fd25b4c2SFrederic Weisbecker * vtime_account_system() and vtime_account_idle(). Archs that 435a7e1a9e3SFrederic Weisbecker * have other meaning of the idle time (s390 only includes the 436a7e1a9e3SFrederic Weisbecker * time spent by the CPU when it's in low power mode) must override 437a7e1a9e3SFrederic Weisbecker * vtime_account(). 438a7e1a9e3SFrederic Weisbecker */ 439a7e1a9e3SFrederic Weisbecker #ifndef __ARCH_HAS_VTIME_ACCOUNT 4400cfdf9a1SFrederic Weisbecker void vtime_account_irq_enter(struct task_struct *tsk) 441a7e1a9e3SFrederic Weisbecker { 4420cfdf9a1SFrederic Weisbecker if (!in_interrupt() && is_idle_task(tsk)) 443fd25b4c2SFrederic Weisbecker vtime_account_idle(tsk); 4440cfdf9a1SFrederic Weisbecker else 445abf917cdSFrederic Weisbecker vtime_account_system(tsk); 446a7e1a9e3SFrederic Weisbecker } 4470cfdf9a1SFrederic Weisbecker EXPORT_SYMBOL_GPL(vtime_account_irq_enter); 448a7e1a9e3SFrederic Weisbecker #endif /* __ARCH_HAS_VTIME_ACCOUNT */ 449a7e1a9e3SFrederic Weisbecker 4505613fda9SFrederic Weisbecker void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st) 45173fbec60SFrederic Weisbecker { 4529fbc42eaSFrederic Weisbecker *ut = p->utime; 4539fbc42eaSFrederic Weisbecker *st = p->stime; 4549fbc42eaSFrederic Weisbecker } 4559eec50b8SAndrey Smetanin EXPORT_SYMBOL_GPL(task_cputime_adjusted); 45673fbec60SFrederic Weisbecker 4575613fda9SFrederic Weisbecker void thread_group_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st) 4589fbc42eaSFrederic Weisbecker { 4599fbc42eaSFrederic Weisbecker struct task_cputime cputime; 46073fbec60SFrederic Weisbecker 4619fbc42eaSFrederic Weisbecker thread_group_cputime(p, &cputime); 4629fbc42eaSFrederic Weisbecker 4639fbc42eaSFrederic Weisbecker *ut = cputime.utime; 4649fbc42eaSFrederic Weisbecker *st = cputime.stime; 4659fbc42eaSFrederic Weisbecker } 4669fbc42eaSFrederic Weisbecker #else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ 4679fbc42eaSFrederic Weisbecker /* 4689fbc42eaSFrederic Weisbecker * Account a single tick of cpu time. 4699fbc42eaSFrederic Weisbecker * @p: the process that the cpu time gets accounted to 4709fbc42eaSFrederic Weisbecker * @user_tick: indicates if the tick is a user or a system tick 4719fbc42eaSFrederic Weisbecker */ 4729fbc42eaSFrederic Weisbecker void account_process_tick(struct task_struct *p, int user_tick) 4739fbc42eaSFrederic Weisbecker { 4742b1f967dSFrederic Weisbecker u64 cputime, steal; 4759fbc42eaSFrederic Weisbecker struct rq *rq = this_rq(); 4769fbc42eaSFrederic Weisbecker 47755dbdcfaSFrederic Weisbecker if (vtime_accounting_cpu_enabled()) 4789fbc42eaSFrederic Weisbecker return; 4799fbc42eaSFrederic Weisbecker 4809fbc42eaSFrederic Weisbecker if (sched_clock_irqtime) { 4812d513868SThomas Gleixner irqtime_account_process_tick(p, user_tick, rq, 1); 4829fbc42eaSFrederic Weisbecker return; 4839fbc42eaSFrederic Weisbecker } 4849fbc42eaSFrederic Weisbecker 4852b1f967dSFrederic Weisbecker cputime = TICK_NSEC; 48603cbc732SWanpeng Li steal = steal_account_process_time(ULONG_MAX); 48757430218SRik van Riel 4882b1f967dSFrederic Weisbecker if (steal >= cputime) 4899fbc42eaSFrederic Weisbecker return; 4909fbc42eaSFrederic Weisbecker 4912b1f967dSFrederic Weisbecker cputime -= steal; 49257430218SRik van Riel 4939fbc42eaSFrederic Weisbecker if (user_tick) 49440565b5aSStanislaw Gruszka account_user_time(p, cputime); 4959fbc42eaSFrederic Weisbecker else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET)) 496fb8b049cSFrederic Weisbecker account_system_time(p, HARDIRQ_OFFSET, cputime); 49773fbec60SFrederic Weisbecker else 49818b43a9bSFrederic Weisbecker account_idle_time(cputime); 4999fbc42eaSFrederic Weisbecker } 50073fbec60SFrederic Weisbecker 5019fbc42eaSFrederic Weisbecker /* 5029fbc42eaSFrederic Weisbecker * Account multiple ticks of idle time. 5039fbc42eaSFrederic Weisbecker * @ticks: number of stolen ticks 5049fbc42eaSFrederic Weisbecker */ 5059fbc42eaSFrederic Weisbecker void account_idle_ticks(unsigned long ticks) 5069fbc42eaSFrederic Weisbecker { 50718b43a9bSFrederic Weisbecker u64 cputime, steal; 50826f2c75cSFrederic Weisbecker 5099fbc42eaSFrederic Weisbecker if (sched_clock_irqtime) { 5109fbc42eaSFrederic Weisbecker irqtime_account_idle_ticks(ticks); 5119fbc42eaSFrederic Weisbecker return; 5129fbc42eaSFrederic Weisbecker } 5139fbc42eaSFrederic Weisbecker 51418b43a9bSFrederic Weisbecker cputime = ticks * TICK_NSEC; 5152b1f967dSFrederic Weisbecker steal = steal_account_process_time(ULONG_MAX); 516f9bcf1e0SWanpeng Li 517f9bcf1e0SWanpeng Li if (steal >= cputime) 518f9bcf1e0SWanpeng Li return; 519f9bcf1e0SWanpeng Li 520f9bcf1e0SWanpeng Li cputime -= steal; 521f9bcf1e0SWanpeng Li account_idle_time(cputime); 5229fbc42eaSFrederic Weisbecker } 52373fbec60SFrederic Weisbecker 524d9a3c982SFrederic Weisbecker /* 52555eaa7c1SStanislaw Gruszka * Perform (stime * rtime) / total, but avoid multiplication overflow by 52655eaa7c1SStanislaw Gruszka * loosing precision when the numbers are big. 527d9a3c982SFrederic Weisbecker */ 5285613fda9SFrederic Weisbecker static u64 scale_stime(u64 stime, u64 rtime, u64 total) 52973fbec60SFrederic Weisbecker { 53055eaa7c1SStanislaw Gruszka u64 scaled; 53173fbec60SFrederic Weisbecker 53255eaa7c1SStanislaw Gruszka for (;;) { 53355eaa7c1SStanislaw Gruszka /* Make sure "rtime" is the bigger of stime/rtime */ 53484f9f3a1SStanislaw Gruszka if (stime > rtime) 53584f9f3a1SStanislaw Gruszka swap(rtime, stime); 53673fbec60SFrederic Weisbecker 53755eaa7c1SStanislaw Gruszka /* Make sure 'total' fits in 32 bits */ 53855eaa7c1SStanislaw Gruszka if (total >> 32) 53955eaa7c1SStanislaw Gruszka goto drop_precision; 54055eaa7c1SStanislaw Gruszka 54155eaa7c1SStanislaw Gruszka /* Does rtime (and thus stime) fit in 32 bits? */ 54255eaa7c1SStanislaw Gruszka if (!(rtime >> 32)) 54355eaa7c1SStanislaw Gruszka break; 54455eaa7c1SStanislaw Gruszka 54555eaa7c1SStanislaw Gruszka /* Can we just balance rtime/stime rather than dropping bits? */ 54655eaa7c1SStanislaw Gruszka if (stime >> 31) 54755eaa7c1SStanislaw Gruszka goto drop_precision; 54855eaa7c1SStanislaw Gruszka 54955eaa7c1SStanislaw Gruszka /* We can grow stime and shrink rtime and try to make them both fit */ 55055eaa7c1SStanislaw Gruszka stime <<= 1; 55155eaa7c1SStanislaw Gruszka rtime >>= 1; 55255eaa7c1SStanislaw Gruszka continue; 55355eaa7c1SStanislaw Gruszka 55455eaa7c1SStanislaw Gruszka drop_precision: 55555eaa7c1SStanislaw Gruszka /* We drop from rtime, it has more bits than stime */ 55655eaa7c1SStanislaw Gruszka rtime >>= 1; 55755eaa7c1SStanislaw Gruszka total >>= 1; 55855eaa7c1SStanislaw Gruszka } 55955eaa7c1SStanislaw Gruszka 56055eaa7c1SStanislaw Gruszka /* 56155eaa7c1SStanislaw Gruszka * Make sure gcc understands that this is a 32x32->64 multiply, 56255eaa7c1SStanislaw Gruszka * followed by a 64/32->64 divide. 56355eaa7c1SStanislaw Gruszka */ 56455eaa7c1SStanislaw Gruszka scaled = div_u64((u64) (u32) stime * (u64) (u32) rtime, (u32)total); 5655613fda9SFrederic Weisbecker return scaled; 56673fbec60SFrederic Weisbecker } 56773fbec60SFrederic Weisbecker 568fa092057SFrederic Weisbecker /* 5699d7fb042SPeter Zijlstra * Adjust tick based cputime random precision against scheduler runtime 5709d7fb042SPeter Zijlstra * accounting. 571347abad9SRik van Riel * 5729d7fb042SPeter Zijlstra * Tick based cputime accounting depend on random scheduling timeslices of a 5739d7fb042SPeter Zijlstra * task to be interrupted or not by the timer. Depending on these 5749d7fb042SPeter Zijlstra * circumstances, the number of these interrupts may be over or 5759d7fb042SPeter Zijlstra * under-optimistic, matching the real user and system cputime with a variable 5769d7fb042SPeter Zijlstra * precision. 5779d7fb042SPeter Zijlstra * 5789d7fb042SPeter Zijlstra * Fix this by scaling these tick based values against the total runtime 5799d7fb042SPeter Zijlstra * accounted by the CFS scheduler. 5809d7fb042SPeter Zijlstra * 5819d7fb042SPeter Zijlstra * This code provides the following guarantees: 5829d7fb042SPeter Zijlstra * 5839d7fb042SPeter Zijlstra * stime + utime == rtime 5849d7fb042SPeter Zijlstra * stime_i+1 >= stime_i, utime_i+1 >= utime_i 5859d7fb042SPeter Zijlstra * 5869d7fb042SPeter Zijlstra * Assuming that rtime_i+1 >= rtime_i. 587fa092057SFrederic Weisbecker */ 588d37f761dSFrederic Weisbecker static void cputime_adjust(struct task_cputime *curr, 5899d7fb042SPeter Zijlstra struct prev_cputime *prev, 5905613fda9SFrederic Weisbecker u64 *ut, u64 *st) 59173fbec60SFrederic Weisbecker { 5925613fda9SFrederic Weisbecker u64 rtime, stime, utime; 5939d7fb042SPeter Zijlstra unsigned long flags; 594fa092057SFrederic Weisbecker 5959d7fb042SPeter Zijlstra /* Serialize concurrent callers such that we can honour our guarantees */ 5969d7fb042SPeter Zijlstra raw_spin_lock_irqsave(&prev->lock, flags); 5975613fda9SFrederic Weisbecker rtime = curr->sum_exec_runtime; 59873fbec60SFrederic Weisbecker 599772c808aSStanislaw Gruszka /* 6009d7fb042SPeter Zijlstra * This is possible under two circumstances: 6019d7fb042SPeter Zijlstra * - rtime isn't monotonic after all (a bug); 6029d7fb042SPeter Zijlstra * - we got reordered by the lock. 6039d7fb042SPeter Zijlstra * 6049d7fb042SPeter Zijlstra * In both cases this acts as a filter such that the rest of the code 6059d7fb042SPeter Zijlstra * can assume it is monotonic regardless of anything else. 606772c808aSStanislaw Gruszka */ 607772c808aSStanislaw Gruszka if (prev->stime + prev->utime >= rtime) 608772c808aSStanislaw Gruszka goto out; 609772c808aSStanislaw Gruszka 6105a8e01f8SStanislaw Gruszka stime = curr->stime; 6115a8e01f8SStanislaw Gruszka utime = curr->utime; 6125a8e01f8SStanislaw Gruszka 613173be9a1SPeter Zijlstra /* 6143b9c08aeSIngo Molnar * If either stime or utime are 0, assume all runtime is userspace. 6153b9c08aeSIngo Molnar * Once a task gets some ticks, the monotonicy code at 'update:' 6163b9c08aeSIngo Molnar * will ensure things converge to the observed ratio. 617173be9a1SPeter Zijlstra */ 6183b9c08aeSIngo Molnar if (stime == 0) { 6193b9c08aeSIngo Molnar utime = rtime; 6203b9c08aeSIngo Molnar goto update; 6219d7fb042SPeter Zijlstra } 62273fbec60SFrederic Weisbecker 6233b9c08aeSIngo Molnar if (utime == 0) { 6243b9c08aeSIngo Molnar stime = rtime; 6253b9c08aeSIngo Molnar goto update; 6263b9c08aeSIngo Molnar } 6273b9c08aeSIngo Molnar 6283b9c08aeSIngo Molnar stime = scale_stime(stime, rtime, stime + utime); 6293b9c08aeSIngo Molnar 6303b9c08aeSIngo Molnar update: 6319d7fb042SPeter Zijlstra /* 6329d7fb042SPeter Zijlstra * Make sure stime doesn't go backwards; this preserves monotonicity 6339d7fb042SPeter Zijlstra * for utime because rtime is monotonic. 6349d7fb042SPeter Zijlstra * 6359d7fb042SPeter Zijlstra * utime_i+1 = rtime_i+1 - stime_i 6369d7fb042SPeter Zijlstra * = rtime_i+1 - (rtime_i - utime_i) 6379d7fb042SPeter Zijlstra * = (rtime_i+1 - rtime_i) + utime_i 6389d7fb042SPeter Zijlstra * >= utime_i 6399d7fb042SPeter Zijlstra */ 6409d7fb042SPeter Zijlstra if (stime < prev->stime) 6419d7fb042SPeter Zijlstra stime = prev->stime; 6429d7fb042SPeter Zijlstra utime = rtime - stime; 6439d7fb042SPeter Zijlstra 6449d7fb042SPeter Zijlstra /* 6459d7fb042SPeter Zijlstra * Make sure utime doesn't go backwards; this still preserves 6469d7fb042SPeter Zijlstra * monotonicity for stime, analogous argument to above. 6479d7fb042SPeter Zijlstra */ 6489d7fb042SPeter Zijlstra if (utime < prev->utime) { 6499d7fb042SPeter Zijlstra utime = prev->utime; 6509d7fb042SPeter Zijlstra stime = rtime - utime; 6519d7fb042SPeter Zijlstra } 6529d7fb042SPeter Zijlstra 6539d7fb042SPeter Zijlstra prev->stime = stime; 6549d7fb042SPeter Zijlstra prev->utime = utime; 655772c808aSStanislaw Gruszka out: 656d37f761dSFrederic Weisbecker *ut = prev->utime; 657d37f761dSFrederic Weisbecker *st = prev->stime; 6589d7fb042SPeter Zijlstra raw_spin_unlock_irqrestore(&prev->lock, flags); 659d37f761dSFrederic Weisbecker } 660d37f761dSFrederic Weisbecker 6615613fda9SFrederic Weisbecker void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st) 662d37f761dSFrederic Weisbecker { 663d37f761dSFrederic Weisbecker struct task_cputime cputime = { 664d37f761dSFrederic Weisbecker .sum_exec_runtime = p->se.sum_exec_runtime, 665d37f761dSFrederic Weisbecker }; 666d37f761dSFrederic Weisbecker 6676fac4829SFrederic Weisbecker task_cputime(p, &cputime.utime, &cputime.stime); 668d37f761dSFrederic Weisbecker cputime_adjust(&cputime, &p->prev_cputime, ut, st); 66973fbec60SFrederic Weisbecker } 6709eec50b8SAndrey Smetanin EXPORT_SYMBOL_GPL(task_cputime_adjusted); 67173fbec60SFrederic Weisbecker 6725613fda9SFrederic Weisbecker void thread_group_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st) 67373fbec60SFrederic Weisbecker { 67473fbec60SFrederic Weisbecker struct task_cputime cputime; 67573fbec60SFrederic Weisbecker 67673fbec60SFrederic Weisbecker thread_group_cputime(p, &cputime); 677d37f761dSFrederic Weisbecker cputime_adjust(&cputime, &p->signal->prev_cputime, ut, st); 67873fbec60SFrederic Weisbecker } 6799fbc42eaSFrederic Weisbecker #endif /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ 680abf917cdSFrederic Weisbecker 681abf917cdSFrederic Weisbecker #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN 682bfce1d60SFrederic Weisbecker static u64 vtime_delta(struct task_struct *tsk) 683abf917cdSFrederic Weisbecker { 684ff9a9b4cSRik van Riel unsigned long now = READ_ONCE(jiffies); 685abf917cdSFrederic Weisbecker 686*60a9ce57SFrederic Weisbecker if (time_before(now, (unsigned long)tsk->vtime_starttime)) 6876a61671bSFrederic Weisbecker return 0; 6886a61671bSFrederic Weisbecker 689*60a9ce57SFrederic Weisbecker return jiffies_to_nsecs(now - tsk->vtime_starttime); 6906a61671bSFrederic Weisbecker } 6916a61671bSFrederic Weisbecker 692bfce1d60SFrederic Weisbecker static u64 get_vtime_delta(struct task_struct *tsk) 6936a61671bSFrederic Weisbecker { 694ff9a9b4cSRik van Riel unsigned long now = READ_ONCE(jiffies); 695bfce1d60SFrederic Weisbecker u64 delta, other; 6966a61671bSFrederic Weisbecker 69703cbc732SWanpeng Li /* 69803cbc732SWanpeng Li * Unlike tick based timing, vtime based timing never has lost 69903cbc732SWanpeng Li * ticks, and no need for steal time accounting to make up for 70003cbc732SWanpeng Li * lost ticks. Vtime accounts a rounded version of actual 70103cbc732SWanpeng Li * elapsed time. Limit account_other_time to prevent rounding 70203cbc732SWanpeng Li * errors from causing elapsed vtime to go negative. 70303cbc732SWanpeng Li */ 704*60a9ce57SFrederic Weisbecker delta = jiffies_to_nsecs(now - tsk->vtime_starttime); 705b58c3584SRik van Riel other = account_other_time(delta); 706*60a9ce57SFrederic Weisbecker WARN_ON_ONCE(tsk->vtime_state == VTIME_INACTIVE); 707*60a9ce57SFrederic Weisbecker tsk->vtime_starttime = now; 708abf917cdSFrederic Weisbecker 709b58c3584SRik van Riel return delta - other; 710abf917cdSFrederic Weisbecker } 711abf917cdSFrederic Weisbecker 7126a61671bSFrederic Weisbecker static void __vtime_account_system(struct task_struct *tsk) 7136a61671bSFrederic Weisbecker { 714bfce1d60SFrederic Weisbecker account_system_time(tsk, irq_count(), get_vtime_delta(tsk)); 7156a61671bSFrederic Weisbecker } 7166a61671bSFrederic Weisbecker 717abf917cdSFrederic Weisbecker void vtime_account_system(struct task_struct *tsk) 718abf917cdSFrederic Weisbecker { 719ff9a9b4cSRik van Riel if (!vtime_delta(tsk)) 720ff9a9b4cSRik van Riel return; 721ff9a9b4cSRik van Riel 722b7ce2277SFrederic Weisbecker write_seqcount_begin(&tsk->vtime_seqcount); 7236a61671bSFrederic Weisbecker __vtime_account_system(tsk); 724b7ce2277SFrederic Weisbecker write_seqcount_end(&tsk->vtime_seqcount); 7256a61671bSFrederic Weisbecker } 7266a61671bSFrederic Weisbecker 7276a61671bSFrederic Weisbecker void vtime_user_enter(struct task_struct *tsk) 7286a61671bSFrederic Weisbecker { 729b7ce2277SFrederic Weisbecker write_seqcount_begin(&tsk->vtime_seqcount); 730ff9a9b4cSRik van Riel if (vtime_delta(tsk)) 7316a61671bSFrederic Weisbecker __vtime_account_system(tsk); 732af2350bdSFrederic Weisbecker tsk->vtime_snap_whence = VTIME_USER; 733b7ce2277SFrederic Weisbecker write_seqcount_end(&tsk->vtime_seqcount); 7346a61671bSFrederic Weisbecker } 7356a61671bSFrederic Weisbecker 7361c3eda01SFrederic Weisbecker void vtime_user_exit(struct task_struct *tsk) 7371c3eda01SFrederic Weisbecker { 7381c3eda01SFrederic Weisbecker write_seqcount_begin(&tsk->vtime_seqcount); 7391c3eda01SFrederic Weisbecker if (vtime_delta(tsk)) 7401c3eda01SFrederic Weisbecker account_user_time(tsk, get_vtime_delta(tsk)); 7419fa57cf5SFrederic Weisbecker tsk->vtime_snap_whence = VTIME_SYS; 7421c3eda01SFrederic Weisbecker write_seqcount_end(&tsk->vtime_seqcount); 7431c3eda01SFrederic Weisbecker } 7441c3eda01SFrederic Weisbecker 7456a61671bSFrederic Weisbecker void vtime_guest_enter(struct task_struct *tsk) 7466a61671bSFrederic Weisbecker { 7475b206d48SFrederic Weisbecker /* 7485b206d48SFrederic Weisbecker * The flags must be updated under the lock with 749*60a9ce57SFrederic Weisbecker * the vtime_starttime flush and update. 7505b206d48SFrederic Weisbecker * That enforces a right ordering and update sequence 7515b206d48SFrederic Weisbecker * synchronization against the reader (task_gtime()) 7525b206d48SFrederic Weisbecker * that can thus safely catch up with a tickless delta. 7535b206d48SFrederic Weisbecker */ 754b7ce2277SFrederic Weisbecker write_seqcount_begin(&tsk->vtime_seqcount); 755ff9a9b4cSRik van Riel if (vtime_delta(tsk)) 7566a61671bSFrederic Weisbecker __vtime_account_system(tsk); 7576a61671bSFrederic Weisbecker current->flags |= PF_VCPU; 758b7ce2277SFrederic Weisbecker write_seqcount_end(&tsk->vtime_seqcount); 7596a61671bSFrederic Weisbecker } 76048d6a816SFrederic Weisbecker EXPORT_SYMBOL_GPL(vtime_guest_enter); 7616a61671bSFrederic Weisbecker 7626a61671bSFrederic Weisbecker void vtime_guest_exit(struct task_struct *tsk) 7636a61671bSFrederic Weisbecker { 764b7ce2277SFrederic Weisbecker write_seqcount_begin(&tsk->vtime_seqcount); 7656a61671bSFrederic Weisbecker __vtime_account_system(tsk); 7666a61671bSFrederic Weisbecker current->flags &= ~PF_VCPU; 767b7ce2277SFrederic Weisbecker write_seqcount_end(&tsk->vtime_seqcount); 768abf917cdSFrederic Weisbecker } 76948d6a816SFrederic Weisbecker EXPORT_SYMBOL_GPL(vtime_guest_exit); 770abf917cdSFrederic Weisbecker 771abf917cdSFrederic Weisbecker void vtime_account_idle(struct task_struct *tsk) 772abf917cdSFrederic Weisbecker { 773bfce1d60SFrederic Weisbecker account_idle_time(get_vtime_delta(tsk)); 774abf917cdSFrederic Weisbecker } 7753f4724eaSFrederic Weisbecker 7766a61671bSFrederic Weisbecker void arch_vtime_task_switch(struct task_struct *prev) 7776a61671bSFrederic Weisbecker { 778b7ce2277SFrederic Weisbecker write_seqcount_begin(&prev->vtime_seqcount); 779*60a9ce57SFrederic Weisbecker prev->vtime_state = VTIME_INACTIVE; 780b7ce2277SFrederic Weisbecker write_seqcount_end(&prev->vtime_seqcount); 7816a61671bSFrederic Weisbecker 782b7ce2277SFrederic Weisbecker write_seqcount_begin(¤t->vtime_seqcount); 783*60a9ce57SFrederic Weisbecker current->vtime_state = VTIME_SYS; 784*60a9ce57SFrederic Weisbecker current->vtime_starttime = jiffies; 785b7ce2277SFrederic Weisbecker write_seqcount_end(¤t->vtime_seqcount); 7866a61671bSFrederic Weisbecker } 7876a61671bSFrederic Weisbecker 78845eacc69SFrederic Weisbecker void vtime_init_idle(struct task_struct *t, int cpu) 7896a61671bSFrederic Weisbecker { 7906a61671bSFrederic Weisbecker unsigned long flags; 7916a61671bSFrederic Weisbecker 792b7ce2277SFrederic Weisbecker local_irq_save(flags); 793b7ce2277SFrederic Weisbecker write_seqcount_begin(&t->vtime_seqcount); 794*60a9ce57SFrederic Weisbecker t->vtime_state = VTIME_SYS; 795*60a9ce57SFrederic Weisbecker t->vtime_starttime = jiffies; 796b7ce2277SFrederic Weisbecker write_seqcount_end(&t->vtime_seqcount); 797b7ce2277SFrederic Weisbecker local_irq_restore(flags); 7986a61671bSFrederic Weisbecker } 7996a61671bSFrederic Weisbecker 80016a6d9beSFrederic Weisbecker u64 task_gtime(struct task_struct *t) 8016a61671bSFrederic Weisbecker { 8026a61671bSFrederic Weisbecker unsigned int seq; 80316a6d9beSFrederic Weisbecker u64 gtime; 8046a61671bSFrederic Weisbecker 805e5925394SFrederic Weisbecker if (!vtime_accounting_enabled()) 8062541117bSHiroshi Shimamoto return t->gtime; 8072541117bSHiroshi Shimamoto 8086a61671bSFrederic Weisbecker do { 809b7ce2277SFrederic Weisbecker seq = read_seqcount_begin(&t->vtime_seqcount); 8106a61671bSFrederic Weisbecker 8116a61671bSFrederic Weisbecker gtime = t->gtime; 812*60a9ce57SFrederic Weisbecker if (t->vtime_state == VTIME_SYS && t->flags & PF_VCPU) 813bfce1d60SFrederic Weisbecker gtime += vtime_delta(t); 8146a61671bSFrederic Weisbecker 815b7ce2277SFrederic Weisbecker } while (read_seqcount_retry(&t->vtime_seqcount, seq)); 8166a61671bSFrederic Weisbecker 8176a61671bSFrederic Weisbecker return gtime; 8186a61671bSFrederic Weisbecker } 8196a61671bSFrederic Weisbecker 8206a61671bSFrederic Weisbecker /* 8216a61671bSFrederic Weisbecker * Fetch cputime raw values from fields of task_struct and 8226a61671bSFrederic Weisbecker * add up the pending nohz execution time since the last 8236a61671bSFrederic Weisbecker * cputime snapshot. 8246a61671bSFrederic Weisbecker */ 8255613fda9SFrederic Weisbecker void task_cputime(struct task_struct *t, u64 *utime, u64 *stime) 8266a61671bSFrederic Weisbecker { 8275613fda9SFrederic Weisbecker u64 delta; 8286a61671bSFrederic Weisbecker unsigned int seq; 829353c50ebSStanislaw Gruszka 830353c50ebSStanislaw Gruszka if (!vtime_accounting_enabled()) { 831353c50ebSStanislaw Gruszka *utime = t->utime; 832353c50ebSStanislaw Gruszka *stime = t->stime; 833353c50ebSStanislaw Gruszka return; 834353c50ebSStanislaw Gruszka } 8356a61671bSFrederic Weisbecker 8366a61671bSFrederic Weisbecker do { 837b7ce2277SFrederic Weisbecker seq = read_seqcount_begin(&t->vtime_seqcount); 8386a61671bSFrederic Weisbecker 839353c50ebSStanislaw Gruszka *utime = t->utime; 840353c50ebSStanislaw Gruszka *stime = t->stime; 8416a61671bSFrederic Weisbecker 8426a61671bSFrederic Weisbecker /* Task is sleeping, nothing to add */ 843*60a9ce57SFrederic Weisbecker if (t->vtime_state == VTIME_INACTIVE || is_idle_task(t)) 8446a61671bSFrederic Weisbecker continue; 8456a61671bSFrederic Weisbecker 846bfce1d60SFrederic Weisbecker delta = vtime_delta(t); 8476a61671bSFrederic Weisbecker 8486a61671bSFrederic Weisbecker /* 8496a61671bSFrederic Weisbecker * Task runs either in user or kernel space, add pending nohz time to 8506a61671bSFrederic Weisbecker * the right place. 8516a61671bSFrederic Weisbecker */ 852*60a9ce57SFrederic Weisbecker if (t->vtime_state == VTIME_USER || t->flags & PF_VCPU) 853353c50ebSStanislaw Gruszka *utime += delta; 854*60a9ce57SFrederic Weisbecker else if (t->vtime_state == VTIME_SYS) 855353c50ebSStanislaw Gruszka *stime += delta; 856b7ce2277SFrederic Weisbecker } while (read_seqcount_retry(&t->vtime_seqcount, seq)); 8576a61671bSFrederic Weisbecker } 858abf917cdSFrederic Weisbecker #endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */ 859