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> 773fbec60SFrederic Weisbecker #include "sched.h" 81fe7c4efSStefano Stabellini #ifdef CONFIG_PARAVIRT 91fe7c4efSStefano Stabellini #include <asm/paravirt.h> 101fe7c4efSStefano Stabellini #endif 1173fbec60SFrederic Weisbecker 1273fbec60SFrederic Weisbecker 1373fbec60SFrederic Weisbecker #ifdef CONFIG_IRQ_TIME_ACCOUNTING 1473fbec60SFrederic Weisbecker 1573fbec60SFrederic Weisbecker /* 1673fbec60SFrederic Weisbecker * There are no locks covering percpu hardirq/softirq time. 17bf9fae9fSFrederic Weisbecker * They are only modified in vtime_account, on corresponding CPU 1873fbec60SFrederic Weisbecker * with interrupts disabled. So, writes are safe. 1973fbec60SFrederic Weisbecker * They are read and saved off onto struct rq in update_rq_clock(). 2073fbec60SFrederic Weisbecker * This may result in other CPU reading this CPU's irq time and can 21bf9fae9fSFrederic Weisbecker * race with irq/vtime_account on this CPU. We would either get old 2273fbec60SFrederic Weisbecker * or new value with a side effect of accounting a slice of irq time to wrong 2373fbec60SFrederic Weisbecker * task when irq is in progress while we read rq->clock. That is a worthy 2473fbec60SFrederic Weisbecker * compromise in place of having locks on each irq in account_system_time. 2573fbec60SFrederic Weisbecker */ 2619d23dbfSFrederic Weisbecker DEFINE_PER_CPU(struct irqtime, cpu_irqtime); 2773fbec60SFrederic Weisbecker 2873fbec60SFrederic Weisbecker static int sched_clock_irqtime; 2973fbec60SFrederic Weisbecker 3073fbec60SFrederic Weisbecker void enable_sched_clock_irqtime(void) 3173fbec60SFrederic Weisbecker { 3273fbec60SFrederic Weisbecker sched_clock_irqtime = 1; 3373fbec60SFrederic Weisbecker } 3473fbec60SFrederic Weisbecker 3573fbec60SFrederic Weisbecker void disable_sched_clock_irqtime(void) 3673fbec60SFrederic Weisbecker { 3773fbec60SFrederic Weisbecker sched_clock_irqtime = 0; 3873fbec60SFrederic Weisbecker } 3973fbec60SFrederic Weisbecker 4073fbec60SFrederic Weisbecker /* 4173fbec60SFrederic Weisbecker * Called before incrementing preempt_count on {soft,}irq_enter 4273fbec60SFrederic Weisbecker * and before decrementing preempt_count on {soft,}irq_exit. 4373fbec60SFrederic Weisbecker */ 443e1df4f5SFrederic Weisbecker void irqtime_account_irq(struct task_struct *curr) 4573fbec60SFrederic Weisbecker { 4619d23dbfSFrederic Weisbecker struct irqtime *irqtime = this_cpu_ptr(&cpu_irqtime); 47a499a5a1SFrederic Weisbecker u64 *cpustat = kcpustat_this_cpu->cpustat; 4873fbec60SFrederic Weisbecker s64 delta; 4973fbec60SFrederic Weisbecker int cpu; 5073fbec60SFrederic Weisbecker 5173fbec60SFrederic Weisbecker if (!sched_clock_irqtime) 5273fbec60SFrederic Weisbecker return; 5373fbec60SFrederic Weisbecker 5473fbec60SFrederic Weisbecker cpu = smp_processor_id(); 5519d23dbfSFrederic Weisbecker delta = sched_clock_cpu(cpu) - irqtime->irq_start_time; 5619d23dbfSFrederic Weisbecker irqtime->irq_start_time += delta; 5773fbec60SFrederic Weisbecker 5819d23dbfSFrederic Weisbecker u64_stats_update_begin(&irqtime->sync); 5973fbec60SFrederic Weisbecker /* 6073fbec60SFrederic Weisbecker * We do not account for softirq time from ksoftirqd here. 6173fbec60SFrederic Weisbecker * We want to continue accounting softirq time to ksoftirqd thread 6273fbec60SFrederic Weisbecker * in that case, so as not to confuse scheduler with a special task 6373fbec60SFrederic Weisbecker * that do not consume any time, but still wants to run. 6473fbec60SFrederic Weisbecker */ 65a499a5a1SFrederic Weisbecker if (hardirq_count()) { 66a499a5a1SFrederic Weisbecker cpustat[CPUTIME_IRQ] += delta; 67a499a5a1SFrederic Weisbecker irqtime->tick_delta += delta; 68a499a5a1SFrederic Weisbecker } else if (in_serving_softirq() && curr != this_cpu_ksoftirqd()) { 69a499a5a1SFrederic Weisbecker cpustat[CPUTIME_SOFTIRQ] += delta; 70a499a5a1SFrederic Weisbecker irqtime->tick_delta += delta; 71a499a5a1SFrederic Weisbecker } 7273fbec60SFrederic Weisbecker 7319d23dbfSFrederic Weisbecker u64_stats_update_end(&irqtime->sync); 7473fbec60SFrederic Weisbecker } 753e1df4f5SFrederic Weisbecker EXPORT_SYMBOL_GPL(irqtime_account_irq); 7673fbec60SFrederic Weisbecker 77a499a5a1SFrederic Weisbecker static cputime_t irqtime_tick_accounted(cputime_t maxtime) 7873fbec60SFrederic Weisbecker { 79a499a5a1SFrederic Weisbecker struct irqtime *irqtime = this_cpu_ptr(&cpu_irqtime); 80a499a5a1SFrederic Weisbecker cputime_t delta; 8173fbec60SFrederic Weisbecker 82a499a5a1SFrederic Weisbecker delta = nsecs_to_cputime(irqtime->tick_delta); 83a499a5a1SFrederic Weisbecker delta = min(delta, maxtime); 84a499a5a1SFrederic Weisbecker irqtime->tick_delta -= cputime_to_nsecs(delta); 852810f611SFrederic Weisbecker 86a499a5a1SFrederic Weisbecker return delta; 8773fbec60SFrederic Weisbecker } 8873fbec60SFrederic Weisbecker 8973fbec60SFrederic Weisbecker #else /* CONFIG_IRQ_TIME_ACCOUNTING */ 9073fbec60SFrederic Weisbecker 9173fbec60SFrederic Weisbecker #define sched_clock_irqtime (0) 9273fbec60SFrederic Weisbecker 93a499a5a1SFrederic Weisbecker static cputime_t irqtime_tick_accounted(cputime_t dummy) 9457430218SRik van Riel { 9557430218SRik van Riel return 0; 9657430218SRik van Riel } 9757430218SRik van Riel 9873fbec60SFrederic Weisbecker #endif /* !CONFIG_IRQ_TIME_ACCOUNTING */ 9973fbec60SFrederic Weisbecker 10073fbec60SFrederic Weisbecker static inline void task_group_account_field(struct task_struct *p, int index, 10173fbec60SFrederic Weisbecker u64 tmp) 10273fbec60SFrederic Weisbecker { 10373fbec60SFrederic Weisbecker /* 10473fbec60SFrederic Weisbecker * Since all updates are sure to touch the root cgroup, we 10573fbec60SFrederic Weisbecker * get ourselves ahead and touch it first. If the root cgroup 10673fbec60SFrederic Weisbecker * is the only cgroup, then nothing else should be necessary. 10773fbec60SFrederic Weisbecker * 10873fbec60SFrederic Weisbecker */ 109a4f61cc0SChristoph Lameter __this_cpu_add(kernel_cpustat.cpustat[index], tmp); 11073fbec60SFrederic Weisbecker 1111966aaf7SLi Zefan cpuacct_account_field(p, index, tmp); 11273fbec60SFrederic Weisbecker } 11373fbec60SFrederic Weisbecker 11473fbec60SFrederic Weisbecker /* 11573fbec60SFrederic Weisbecker * Account user cpu time to a process. 11673fbec60SFrederic Weisbecker * @p: the process that the cpu time gets accounted to 11773fbec60SFrederic Weisbecker * @cputime: the cpu time spent in user space since the last update 11873fbec60SFrederic Weisbecker */ 11923244a5cSFrederic Weisbecker void account_user_time(struct task_struct *p, u64 cputime) 12073fbec60SFrederic Weisbecker { 12173fbec60SFrederic Weisbecker int index; 12273fbec60SFrederic Weisbecker 12373fbec60SFrederic Weisbecker /* Add user time to process. */ 12423244a5cSFrederic Weisbecker p->utime += cputime; 12523244a5cSFrederic Weisbecker account_group_user_time(p, cputime); 12673fbec60SFrederic Weisbecker 127d0ea0268SDongsheng Yang index = (task_nice(p) > 0) ? CPUTIME_NICE : CPUTIME_USER; 12873fbec60SFrederic Weisbecker 12973fbec60SFrederic Weisbecker /* Add user time to cpustat. */ 13023244a5cSFrederic Weisbecker task_group_account_field(p, index, cputime); 13173fbec60SFrederic Weisbecker 13273fbec60SFrederic Weisbecker /* Account for user time used */ 1336fac4829SFrederic Weisbecker acct_account_cputime(p); 13473fbec60SFrederic Weisbecker } 13573fbec60SFrederic Weisbecker 13673fbec60SFrederic Weisbecker /* 13773fbec60SFrederic Weisbecker * Account guest cpu time to a process. 13873fbec60SFrederic Weisbecker * @p: the process that the cpu time gets accounted to 13973fbec60SFrederic Weisbecker * @cputime: the cpu time spent in virtual machine since the last update 14073fbec60SFrederic Weisbecker */ 1411213699aSFrederic Weisbecker void account_guest_time(struct task_struct *p, cputime_t cputime) 14273fbec60SFrederic Weisbecker { 14373fbec60SFrederic Weisbecker u64 *cpustat = kcpustat_this_cpu->cpustat; 14473fbec60SFrederic Weisbecker 14573fbec60SFrederic Weisbecker /* Add guest time to process. */ 1465613fda9SFrederic Weisbecker p->utime += cputime_to_nsecs(cputime); 147ebd7e7fcSFrederic Weisbecker account_group_user_time(p, cputime_to_nsecs(cputime)); 14816a6d9beSFrederic Weisbecker p->gtime += cputime_to_nsecs(cputime); 14973fbec60SFrederic Weisbecker 15073fbec60SFrederic Weisbecker /* Add guest time to cpustat. */ 151d0ea0268SDongsheng Yang if (task_nice(p) > 0) { 1527fb1327eSFrederic Weisbecker cpustat[CPUTIME_NICE] += cputime_to_nsecs(cputime); 1537fb1327eSFrederic Weisbecker cpustat[CPUTIME_GUEST_NICE] += cputime_to_nsecs(cputime); 15473fbec60SFrederic Weisbecker } else { 1557fb1327eSFrederic Weisbecker cpustat[CPUTIME_USER] += cputime_to_nsecs(cputime); 1567fb1327eSFrederic Weisbecker cpustat[CPUTIME_GUEST] += cputime_to_nsecs(cputime); 15773fbec60SFrederic Weisbecker } 15873fbec60SFrederic Weisbecker } 15973fbec60SFrederic Weisbecker 16073fbec60SFrederic Weisbecker /* 16173fbec60SFrederic Weisbecker * Account system cpu time to a process and desired cpustat field 16273fbec60SFrederic Weisbecker * @p: the process that the cpu time gets accounted to 16373fbec60SFrederic Weisbecker * @cputime: the cpu time spent in kernel space since the last update 16440565b5aSStanislaw Gruszka * @index: pointer to cpustat field that has to be updated 16573fbec60SFrederic Weisbecker */ 166c31cc6a5SFrederic Weisbecker void account_system_index_time(struct task_struct *p, 167c31cc6a5SFrederic Weisbecker cputime_t cputime, enum cpu_usage_stat index) 16873fbec60SFrederic Weisbecker { 16973fbec60SFrederic Weisbecker /* Add system time to process. */ 1705613fda9SFrederic Weisbecker p->stime += cputime_to_nsecs(cputime); 171ebd7e7fcSFrederic Weisbecker account_group_system_time(p, cputime_to_nsecs(cputime)); 17273fbec60SFrederic Weisbecker 17373fbec60SFrederic Weisbecker /* Add system time to cpustat. */ 1747fb1327eSFrederic Weisbecker task_group_account_field(p, index, cputime_to_nsecs(cputime)); 17573fbec60SFrederic Weisbecker 17673fbec60SFrederic Weisbecker /* Account for system time used */ 1776fac4829SFrederic Weisbecker acct_account_cputime(p); 17873fbec60SFrederic Weisbecker } 17973fbec60SFrederic Weisbecker 18073fbec60SFrederic Weisbecker /* 18173fbec60SFrederic Weisbecker * Account system cpu time to a process. 18273fbec60SFrederic Weisbecker * @p: the process that the cpu time gets accounted to 18373fbec60SFrederic Weisbecker * @hardirq_offset: the offset to subtract from hardirq_count() 18473fbec60SFrederic Weisbecker * @cputime: the cpu time spent in kernel space since the last update 18573fbec60SFrederic Weisbecker */ 18673fbec60SFrederic Weisbecker void account_system_time(struct task_struct *p, int hardirq_offset, 18740565b5aSStanislaw Gruszka cputime_t 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 */ 210*be9095edSFrederic Weisbecker void account_steal_time(u64 cputime) 21173fbec60SFrederic Weisbecker { 21273fbec60SFrederic Weisbecker u64 *cpustat = kcpustat_this_cpu->cpustat; 21373fbec60SFrederic Weisbecker 214*be9095edSFrederic 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 */ 22173fbec60SFrederic Weisbecker void account_idle_time(cputime_t 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) 2277fb1327eSFrederic Weisbecker cpustat[CPUTIME_IOWAIT] += cputime_to_nsecs(cputime); 22873fbec60SFrederic Weisbecker else 2297fb1327eSFrederic Weisbecker cpustat[CPUTIME_IDLE] += cputime_to_nsecs(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 */ 23757430218SRik van Riel static __always_inline cputime_t steal_account_process_time(cputime_t maxtime) 23873fbec60SFrederic Weisbecker { 23973fbec60SFrederic Weisbecker #ifdef CONFIG_PARAVIRT 24073fbec60SFrederic Weisbecker if (static_key_false(¶virt_steal_enabled)) { 24157430218SRik van Riel cputime_t steal_cputime; 242*be9095edSFrederic Weisbecker u64 steal, rounded; 24373fbec60SFrederic Weisbecker 24473fbec60SFrederic Weisbecker steal = paravirt_steal_clock(smp_processor_id()); 24573fbec60SFrederic Weisbecker steal -= this_rq()->prev_steal_time; 24673fbec60SFrederic Weisbecker 24757430218SRik van Riel steal_cputime = min(nsecs_to_cputime(steal), maxtime); 248*be9095edSFrederic Weisbecker rounded = cputime_to_nsecs(steal_cputime); 249*be9095edSFrederic Weisbecker account_steal_time(rounded); 250*be9095edSFrederic Weisbecker this_rq()->prev_steal_time += rounded; 25173fbec60SFrederic Weisbecker 25257430218SRik van Riel return steal_cputime; 25373fbec60SFrederic Weisbecker } 25473fbec60SFrederic Weisbecker #endif 255807e5b80SWanpeng Li return 0; 25673fbec60SFrederic Weisbecker } 25773fbec60SFrederic Weisbecker 258a634f933SFrederic Weisbecker /* 25957430218SRik van Riel * Account how much elapsed time was spent in steal, irq, or softirq time. 26057430218SRik van Riel */ 26157430218SRik van Riel static inline cputime_t account_other_time(cputime_t max) 26257430218SRik van Riel { 26357430218SRik van Riel cputime_t accounted; 26457430218SRik van Riel 2652810f611SFrederic Weisbecker /* Shall be converted to a lockdep-enabled lightweight check */ 2662810f611SFrederic Weisbecker WARN_ON_ONCE(!irqs_disabled()); 2672810f611SFrederic Weisbecker 26857430218SRik van Riel accounted = steal_account_process_time(max); 26957430218SRik van Riel 27057430218SRik van Riel if (accounted < max) 271a499a5a1SFrederic Weisbecker accounted += irqtime_tick_accounted(max - accounted); 27257430218SRik van Riel 27357430218SRik van Riel return accounted; 27457430218SRik van Riel } 27557430218SRik van Riel 276a1eb1411SStanislaw Gruszka #ifdef CONFIG_64BIT 277a1eb1411SStanislaw Gruszka static inline u64 read_sum_exec_runtime(struct task_struct *t) 278a1eb1411SStanislaw Gruszka { 279a1eb1411SStanislaw Gruszka return t->se.sum_exec_runtime; 280a1eb1411SStanislaw Gruszka } 281a1eb1411SStanislaw Gruszka #else 282a1eb1411SStanislaw Gruszka static u64 read_sum_exec_runtime(struct task_struct *t) 283a1eb1411SStanislaw Gruszka { 284a1eb1411SStanislaw Gruszka u64 ns; 285a1eb1411SStanislaw Gruszka struct rq_flags rf; 286a1eb1411SStanislaw Gruszka struct rq *rq; 287a1eb1411SStanislaw Gruszka 288a1eb1411SStanislaw Gruszka rq = task_rq_lock(t, &rf); 289a1eb1411SStanislaw Gruszka ns = t->se.sum_exec_runtime; 290a1eb1411SStanislaw Gruszka task_rq_unlock(rq, t, &rf); 291a1eb1411SStanislaw Gruszka 292a1eb1411SStanislaw Gruszka return ns; 293a1eb1411SStanislaw Gruszka } 294a1eb1411SStanislaw Gruszka #endif 295a1eb1411SStanislaw Gruszka 29657430218SRik van Riel /* 297a634f933SFrederic Weisbecker * Accumulate raw cputime values of dead tasks (sig->[us]time) and live 298a634f933SFrederic Weisbecker * tasks (sum on group iteration) belonging to @tsk's group. 299a634f933SFrederic Weisbecker */ 300a634f933SFrederic Weisbecker void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times) 301a634f933SFrederic Weisbecker { 302a634f933SFrederic Weisbecker struct signal_struct *sig = tsk->signal; 3035613fda9SFrederic Weisbecker u64 utime, stime; 304a634f933SFrederic Weisbecker struct task_struct *t; 305e78c3496SRik van Riel unsigned int seq, nextseq; 3069c368b5bSRik van Riel unsigned long flags; 307a634f933SFrederic Weisbecker 308a1eb1411SStanislaw Gruszka /* 309a1eb1411SStanislaw Gruszka * Update current task runtime to account pending time since last 310a1eb1411SStanislaw Gruszka * scheduler action or thread_group_cputime() call. This thread group 311a1eb1411SStanislaw Gruszka * might have other running tasks on different CPUs, but updating 312a1eb1411SStanislaw Gruszka * their runtime can affect syscall performance, so we skip account 313a1eb1411SStanislaw Gruszka * those pending times and rely only on values updated on tick or 314a1eb1411SStanislaw Gruszka * other scheduler action. 315a1eb1411SStanislaw Gruszka */ 316a1eb1411SStanislaw Gruszka if (same_thread_group(current, tsk)) 317a1eb1411SStanislaw Gruszka (void) task_sched_runtime(current); 318a1eb1411SStanislaw Gruszka 319e78c3496SRik van Riel rcu_read_lock(); 320e78c3496SRik van Riel /* Attempt a lockless read on the first round. */ 321e78c3496SRik van Riel nextseq = 0; 322e78c3496SRik van Riel do { 323e78c3496SRik van Riel seq = nextseq; 3249c368b5bSRik van Riel flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq); 325a634f933SFrederic Weisbecker times->utime = sig->utime; 326a634f933SFrederic Weisbecker times->stime = sig->stime; 327a634f933SFrederic Weisbecker times->sum_exec_runtime = sig->sum_sched_runtime; 328a634f933SFrederic Weisbecker 3291e4dda08SOleg Nesterov for_each_thread(tsk, t) { 330e614b333SStanislaw Gruszka task_cputime(t, &utime, &stime); 3316fac4829SFrederic Weisbecker times->utime += utime; 3326fac4829SFrederic Weisbecker times->stime += stime; 333a1eb1411SStanislaw Gruszka times->sum_exec_runtime += read_sum_exec_runtime(t); 3341e4dda08SOleg Nesterov } 335e78c3496SRik van Riel /* If lockless access failed, take the lock. */ 336e78c3496SRik van Riel nextseq = 1; 337e78c3496SRik van Riel } while (need_seqretry(&sig->stats_lock, seq)); 3389c368b5bSRik van Riel done_seqretry_irqrestore(&sig->stats_lock, seq, flags); 339a634f933SFrederic Weisbecker rcu_read_unlock(); 340a634f933SFrederic Weisbecker } 341a634f933SFrederic Weisbecker 34273fbec60SFrederic Weisbecker #ifdef CONFIG_IRQ_TIME_ACCOUNTING 34373fbec60SFrederic Weisbecker /* 34473fbec60SFrederic Weisbecker * Account a tick to a process and cpustat 34573fbec60SFrederic Weisbecker * @p: the process that the cpu time gets accounted to 34673fbec60SFrederic Weisbecker * @user_tick: is the tick from userspace 34773fbec60SFrederic Weisbecker * @rq: the pointer to rq 34873fbec60SFrederic Weisbecker * 34973fbec60SFrederic Weisbecker * Tick demultiplexing follows the order 35073fbec60SFrederic Weisbecker * - pending hardirq update 35173fbec60SFrederic Weisbecker * - pending softirq update 35273fbec60SFrederic Weisbecker * - user_time 35373fbec60SFrederic Weisbecker * - idle_time 35473fbec60SFrederic Weisbecker * - system time 35573fbec60SFrederic Weisbecker * - check for guest_time 35673fbec60SFrederic Weisbecker * - else account as system_time 35773fbec60SFrederic Weisbecker * 35873fbec60SFrederic Weisbecker * Check for hardirq is done both for system and user time as there is 35973fbec60SFrederic Weisbecker * no timer going off while we are on hardirq and hence we may never get an 36073fbec60SFrederic Weisbecker * opportunity to update it solely in system time. 36173fbec60SFrederic Weisbecker * p->stime and friends are only updated on system time and not on irq 36273fbec60SFrederic Weisbecker * softirq as those do not count in task exec_runtime any more. 36373fbec60SFrederic Weisbecker */ 36473fbec60SFrederic Weisbecker static void irqtime_account_process_tick(struct task_struct *p, int user_tick, 3652d513868SThomas Gleixner struct rq *rq, int ticks) 36673fbec60SFrederic Weisbecker { 36723244a5cSFrederic Weisbecker u64 old_cputime = (__force u64) cputime_one_jiffy * ticks; 368981ee2d4SStanislaw Gruszka cputime_t other; 36923244a5cSFrederic Weisbecker u64 cputime; 37073fbec60SFrederic Weisbecker 37157430218SRik van Riel /* 37257430218SRik van Riel * When returning from idle, many ticks can get accounted at 37357430218SRik van Riel * once, including some ticks of steal, irq, and softirq time. 37457430218SRik van Riel * Subtract those ticks from the amount of time accounted to 37557430218SRik van Riel * idle, or potentially user or system time. Due to rounding, 37657430218SRik van Riel * other time can exceed ticks occasionally. 37757430218SRik van Riel */ 37803cbc732SWanpeng Li other = account_other_time(ULONG_MAX); 37923244a5cSFrederic Weisbecker if (other >= old_cputime) 38073fbec60SFrederic Weisbecker return; 38123244a5cSFrederic Weisbecker 38223244a5cSFrederic Weisbecker old_cputime -= other; 38323244a5cSFrederic Weisbecker cputime = cputime_to_nsecs(old_cputime); 38473fbec60SFrederic Weisbecker 38557430218SRik van Riel if (this_cpu_ksoftirqd() == p) { 38673fbec60SFrederic Weisbecker /* 38773fbec60SFrederic Weisbecker * ksoftirqd time do not get accounted in cpu_softirq_time. 38873fbec60SFrederic Weisbecker * So, we have to handle it separately here. 38973fbec60SFrederic Weisbecker * Also, p->stime needs to be updated for ksoftirqd. 39073fbec60SFrederic Weisbecker */ 39123244a5cSFrederic Weisbecker account_system_index_time(p, old_cputime, CPUTIME_SOFTIRQ); 39273fbec60SFrederic Weisbecker } else if (user_tick) { 39340565b5aSStanislaw Gruszka account_user_time(p, cputime); 39473fbec60SFrederic Weisbecker } else if (p == rq->idle) { 39523244a5cSFrederic Weisbecker account_idle_time(old_cputime); 39673fbec60SFrederic Weisbecker } else if (p->flags & PF_VCPU) { /* System time or guest time */ 39723244a5cSFrederic Weisbecker 39823244a5cSFrederic Weisbecker account_guest_time(p, old_cputime); 39973fbec60SFrederic Weisbecker } else { 40023244a5cSFrederic Weisbecker account_system_index_time(p, old_cputime, CPUTIME_SYSTEM); 40173fbec60SFrederic Weisbecker } 40273fbec60SFrederic Weisbecker } 40373fbec60SFrederic Weisbecker 40473fbec60SFrederic Weisbecker static void irqtime_account_idle_ticks(int ticks) 40573fbec60SFrederic Weisbecker { 40673fbec60SFrederic Weisbecker struct rq *rq = this_rq(); 40773fbec60SFrederic Weisbecker 4082d513868SThomas Gleixner irqtime_account_process_tick(current, 0, rq, ticks); 40973fbec60SFrederic Weisbecker } 41073fbec60SFrederic Weisbecker #else /* CONFIG_IRQ_TIME_ACCOUNTING */ 4113f4724eaSFrederic Weisbecker static inline void irqtime_account_idle_ticks(int ticks) {} 4123f4724eaSFrederic Weisbecker static inline void irqtime_account_process_tick(struct task_struct *p, int user_tick, 4132d513868SThomas Gleixner struct rq *rq, int nr_ticks) {} 41473fbec60SFrederic Weisbecker #endif /* CONFIG_IRQ_TIME_ACCOUNTING */ 41573fbec60SFrederic Weisbecker 41673fbec60SFrederic Weisbecker /* 41773fbec60SFrederic Weisbecker * Use precise platform statistics if available: 41873fbec60SFrederic Weisbecker */ 41973fbec60SFrederic Weisbecker #ifdef CONFIG_VIRT_CPU_ACCOUNTING 420a7e1a9e3SFrederic Weisbecker 421e3942ba0SFrederic Weisbecker #ifndef __ARCH_HAS_VTIME_TASK_SWITCH 422b0493406SFrederic Weisbecker void vtime_common_task_switch(struct task_struct *prev) 423e3942ba0SFrederic Weisbecker { 424e3942ba0SFrederic Weisbecker if (is_idle_task(prev)) 425e3942ba0SFrederic Weisbecker vtime_account_idle(prev); 426e3942ba0SFrederic Weisbecker else 427e3942ba0SFrederic Weisbecker vtime_account_system(prev); 428e3942ba0SFrederic Weisbecker 429c8d7dabfSFrederic Weisbecker vtime_flush(prev); 430e3942ba0SFrederic Weisbecker arch_vtime_task_switch(prev); 431e3942ba0SFrederic Weisbecker } 432e3942ba0SFrederic Weisbecker #endif 43311113334SFrederic Weisbecker 4340cfdf9a1SFrederic Weisbecker #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ 4350cfdf9a1SFrederic Weisbecker 4360cfdf9a1SFrederic Weisbecker 4370cfdf9a1SFrederic Weisbecker #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE 438a7e1a9e3SFrederic Weisbecker /* 439a7e1a9e3SFrederic Weisbecker * Archs that account the whole time spent in the idle task 440a7e1a9e3SFrederic Weisbecker * (outside irq) as idle time can rely on this and just implement 441fd25b4c2SFrederic Weisbecker * vtime_account_system() and vtime_account_idle(). Archs that 442a7e1a9e3SFrederic Weisbecker * have other meaning of the idle time (s390 only includes the 443a7e1a9e3SFrederic Weisbecker * time spent by the CPU when it's in low power mode) must override 444a7e1a9e3SFrederic Weisbecker * vtime_account(). 445a7e1a9e3SFrederic Weisbecker */ 446a7e1a9e3SFrederic Weisbecker #ifndef __ARCH_HAS_VTIME_ACCOUNT 4470cfdf9a1SFrederic Weisbecker void vtime_account_irq_enter(struct task_struct *tsk) 448a7e1a9e3SFrederic Weisbecker { 4490cfdf9a1SFrederic Weisbecker if (!in_interrupt() && is_idle_task(tsk)) 450fd25b4c2SFrederic Weisbecker vtime_account_idle(tsk); 4510cfdf9a1SFrederic Weisbecker else 452abf917cdSFrederic Weisbecker vtime_account_system(tsk); 453a7e1a9e3SFrederic Weisbecker } 4540cfdf9a1SFrederic Weisbecker EXPORT_SYMBOL_GPL(vtime_account_irq_enter); 455a7e1a9e3SFrederic Weisbecker #endif /* __ARCH_HAS_VTIME_ACCOUNT */ 456a7e1a9e3SFrederic Weisbecker 4575613fda9SFrederic Weisbecker void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st) 45873fbec60SFrederic Weisbecker { 4599fbc42eaSFrederic Weisbecker *ut = p->utime; 4609fbc42eaSFrederic Weisbecker *st = p->stime; 4619fbc42eaSFrederic Weisbecker } 4629eec50b8SAndrey Smetanin EXPORT_SYMBOL_GPL(task_cputime_adjusted); 46373fbec60SFrederic Weisbecker 4645613fda9SFrederic Weisbecker void thread_group_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st) 4659fbc42eaSFrederic Weisbecker { 4669fbc42eaSFrederic Weisbecker struct task_cputime cputime; 46773fbec60SFrederic Weisbecker 4689fbc42eaSFrederic Weisbecker thread_group_cputime(p, &cputime); 4699fbc42eaSFrederic Weisbecker 4709fbc42eaSFrederic Weisbecker *ut = cputime.utime; 4719fbc42eaSFrederic Weisbecker *st = cputime.stime; 4729fbc42eaSFrederic Weisbecker } 4739fbc42eaSFrederic Weisbecker #else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ 4749fbc42eaSFrederic Weisbecker /* 4759fbc42eaSFrederic Weisbecker * Account a single tick of cpu time. 4769fbc42eaSFrederic Weisbecker * @p: the process that the cpu time gets accounted to 4779fbc42eaSFrederic Weisbecker * @user_tick: indicates if the tick is a user or a system tick 4789fbc42eaSFrederic Weisbecker */ 4799fbc42eaSFrederic Weisbecker void account_process_tick(struct task_struct *p, int user_tick) 4809fbc42eaSFrederic Weisbecker { 48123244a5cSFrederic Weisbecker cputime_t old_cputime, steal; 48223244a5cSFrederic Weisbecker u64 cputime; 4839fbc42eaSFrederic Weisbecker struct rq *rq = this_rq(); 4849fbc42eaSFrederic Weisbecker 48555dbdcfaSFrederic Weisbecker if (vtime_accounting_cpu_enabled()) 4869fbc42eaSFrederic Weisbecker return; 4879fbc42eaSFrederic Weisbecker 4889fbc42eaSFrederic Weisbecker if (sched_clock_irqtime) { 4892d513868SThomas Gleixner irqtime_account_process_tick(p, user_tick, rq, 1); 4909fbc42eaSFrederic Weisbecker return; 4919fbc42eaSFrederic Weisbecker } 4929fbc42eaSFrederic Weisbecker 49323244a5cSFrederic Weisbecker old_cputime = cputime_one_jiffy; 49403cbc732SWanpeng Li steal = steal_account_process_time(ULONG_MAX); 49557430218SRik van Riel 49623244a5cSFrederic Weisbecker if (steal >= old_cputime) 4979fbc42eaSFrederic Weisbecker return; 4989fbc42eaSFrederic Weisbecker 49923244a5cSFrederic Weisbecker old_cputime -= steal; 50023244a5cSFrederic Weisbecker cputime = cputime_to_nsecs(old_cputime); 50157430218SRik van Riel 5029fbc42eaSFrederic Weisbecker if (user_tick) 50340565b5aSStanislaw Gruszka account_user_time(p, cputime); 5049fbc42eaSFrederic Weisbecker else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET)) 50523244a5cSFrederic Weisbecker account_system_time(p, HARDIRQ_OFFSET, old_cputime); 50673fbec60SFrederic Weisbecker else 50723244a5cSFrederic Weisbecker account_idle_time(old_cputime); 5089fbc42eaSFrederic Weisbecker } 50973fbec60SFrederic Weisbecker 5109fbc42eaSFrederic Weisbecker /* 5119fbc42eaSFrederic Weisbecker * Account multiple ticks of idle time. 5129fbc42eaSFrederic Weisbecker * @ticks: number of stolen ticks 5139fbc42eaSFrederic Weisbecker */ 5149fbc42eaSFrederic Weisbecker void account_idle_ticks(unsigned long ticks) 5159fbc42eaSFrederic Weisbecker { 516f9bcf1e0SWanpeng Li cputime_t cputime, steal; 51726f2c75cSFrederic Weisbecker 5189fbc42eaSFrederic Weisbecker if (sched_clock_irqtime) { 5199fbc42eaSFrederic Weisbecker irqtime_account_idle_ticks(ticks); 5209fbc42eaSFrederic Weisbecker return; 5219fbc42eaSFrederic Weisbecker } 5229fbc42eaSFrederic Weisbecker 52326f2c75cSFrederic Weisbecker cputime = jiffies_to_cputime(ticks); 52403cbc732SWanpeng Li steal = steal_account_process_time(ULONG_MAX); 525f9bcf1e0SWanpeng Li 526f9bcf1e0SWanpeng Li if (steal >= cputime) 527f9bcf1e0SWanpeng Li return; 528f9bcf1e0SWanpeng Li 529f9bcf1e0SWanpeng Li cputime -= steal; 530f9bcf1e0SWanpeng Li account_idle_time(cputime); 5319fbc42eaSFrederic Weisbecker } 53273fbec60SFrederic Weisbecker 533d9a3c982SFrederic Weisbecker /* 53455eaa7c1SStanislaw Gruszka * Perform (stime * rtime) / total, but avoid multiplication overflow by 53555eaa7c1SStanislaw Gruszka * loosing precision when the numbers are big. 536d9a3c982SFrederic Weisbecker */ 5375613fda9SFrederic Weisbecker static u64 scale_stime(u64 stime, u64 rtime, u64 total) 53873fbec60SFrederic Weisbecker { 53955eaa7c1SStanislaw Gruszka u64 scaled; 54073fbec60SFrederic Weisbecker 54155eaa7c1SStanislaw Gruszka for (;;) { 54255eaa7c1SStanislaw Gruszka /* Make sure "rtime" is the bigger of stime/rtime */ 54384f9f3a1SStanislaw Gruszka if (stime > rtime) 54484f9f3a1SStanislaw Gruszka swap(rtime, stime); 54573fbec60SFrederic Weisbecker 54655eaa7c1SStanislaw Gruszka /* Make sure 'total' fits in 32 bits */ 54755eaa7c1SStanislaw Gruszka if (total >> 32) 54855eaa7c1SStanislaw Gruszka goto drop_precision; 54955eaa7c1SStanislaw Gruszka 55055eaa7c1SStanislaw Gruszka /* Does rtime (and thus stime) fit in 32 bits? */ 55155eaa7c1SStanislaw Gruszka if (!(rtime >> 32)) 55255eaa7c1SStanislaw Gruszka break; 55355eaa7c1SStanislaw Gruszka 55455eaa7c1SStanislaw Gruszka /* Can we just balance rtime/stime rather than dropping bits? */ 55555eaa7c1SStanislaw Gruszka if (stime >> 31) 55655eaa7c1SStanislaw Gruszka goto drop_precision; 55755eaa7c1SStanislaw Gruszka 55855eaa7c1SStanislaw Gruszka /* We can grow stime and shrink rtime and try to make them both fit */ 55955eaa7c1SStanislaw Gruszka stime <<= 1; 56055eaa7c1SStanislaw Gruszka rtime >>= 1; 56155eaa7c1SStanislaw Gruszka continue; 56255eaa7c1SStanislaw Gruszka 56355eaa7c1SStanislaw Gruszka drop_precision: 56455eaa7c1SStanislaw Gruszka /* We drop from rtime, it has more bits than stime */ 56555eaa7c1SStanislaw Gruszka rtime >>= 1; 56655eaa7c1SStanislaw Gruszka total >>= 1; 56755eaa7c1SStanislaw Gruszka } 56855eaa7c1SStanislaw Gruszka 56955eaa7c1SStanislaw Gruszka /* 57055eaa7c1SStanislaw Gruszka * Make sure gcc understands that this is a 32x32->64 multiply, 57155eaa7c1SStanislaw Gruszka * followed by a 64/32->64 divide. 57255eaa7c1SStanislaw Gruszka */ 57355eaa7c1SStanislaw Gruszka scaled = div_u64((u64) (u32) stime * (u64) (u32) rtime, (u32)total); 5745613fda9SFrederic Weisbecker return scaled; 57573fbec60SFrederic Weisbecker } 57673fbec60SFrederic Weisbecker 577fa092057SFrederic Weisbecker /* 5789d7fb042SPeter Zijlstra * Adjust tick based cputime random precision against scheduler runtime 5799d7fb042SPeter Zijlstra * accounting. 580347abad9SRik van Riel * 5819d7fb042SPeter Zijlstra * Tick based cputime accounting depend on random scheduling timeslices of a 5829d7fb042SPeter Zijlstra * task to be interrupted or not by the timer. Depending on these 5839d7fb042SPeter Zijlstra * circumstances, the number of these interrupts may be over or 5849d7fb042SPeter Zijlstra * under-optimistic, matching the real user and system cputime with a variable 5859d7fb042SPeter Zijlstra * precision. 5869d7fb042SPeter Zijlstra * 5879d7fb042SPeter Zijlstra * Fix this by scaling these tick based values against the total runtime 5889d7fb042SPeter Zijlstra * accounted by the CFS scheduler. 5899d7fb042SPeter Zijlstra * 5909d7fb042SPeter Zijlstra * This code provides the following guarantees: 5919d7fb042SPeter Zijlstra * 5929d7fb042SPeter Zijlstra * stime + utime == rtime 5939d7fb042SPeter Zijlstra * stime_i+1 >= stime_i, utime_i+1 >= utime_i 5949d7fb042SPeter Zijlstra * 5959d7fb042SPeter Zijlstra * Assuming that rtime_i+1 >= rtime_i. 596fa092057SFrederic Weisbecker */ 597d37f761dSFrederic Weisbecker static void cputime_adjust(struct task_cputime *curr, 5989d7fb042SPeter Zijlstra struct prev_cputime *prev, 5995613fda9SFrederic Weisbecker u64 *ut, u64 *st) 60073fbec60SFrederic Weisbecker { 6015613fda9SFrederic Weisbecker u64 rtime, stime, utime; 6029d7fb042SPeter Zijlstra unsigned long flags; 603fa092057SFrederic Weisbecker 6049d7fb042SPeter Zijlstra /* Serialize concurrent callers such that we can honour our guarantees */ 6059d7fb042SPeter Zijlstra raw_spin_lock_irqsave(&prev->lock, flags); 6065613fda9SFrederic Weisbecker rtime = curr->sum_exec_runtime; 60773fbec60SFrederic Weisbecker 608772c808aSStanislaw Gruszka /* 6099d7fb042SPeter Zijlstra * This is possible under two circumstances: 6109d7fb042SPeter Zijlstra * - rtime isn't monotonic after all (a bug); 6119d7fb042SPeter Zijlstra * - we got reordered by the lock. 6129d7fb042SPeter Zijlstra * 6139d7fb042SPeter Zijlstra * In both cases this acts as a filter such that the rest of the code 6149d7fb042SPeter Zijlstra * can assume it is monotonic regardless of anything else. 615772c808aSStanislaw Gruszka */ 616772c808aSStanislaw Gruszka if (prev->stime + prev->utime >= rtime) 617772c808aSStanislaw Gruszka goto out; 618772c808aSStanislaw Gruszka 6195a8e01f8SStanislaw Gruszka stime = curr->stime; 6205a8e01f8SStanislaw Gruszka utime = curr->utime; 6215a8e01f8SStanislaw Gruszka 622173be9a1SPeter Zijlstra /* 623173be9a1SPeter Zijlstra * If either stime or both stime and utime are 0, assume all runtime is 624173be9a1SPeter Zijlstra * userspace. Once a task gets some ticks, the monotonicy code at 625173be9a1SPeter Zijlstra * 'update' will ensure things converge to the observed ratio. 626173be9a1SPeter Zijlstra */ 627173be9a1SPeter Zijlstra if (stime == 0) { 628173be9a1SPeter Zijlstra utime = rtime; 6299d7fb042SPeter Zijlstra goto update; 630d9a3c982SFrederic Weisbecker } 63173fbec60SFrederic Weisbecker 632173be9a1SPeter Zijlstra if (utime == 0) { 633173be9a1SPeter Zijlstra stime = rtime; 6349d7fb042SPeter Zijlstra goto update; 6359d7fb042SPeter Zijlstra } 63673fbec60SFrederic Weisbecker 6375613fda9SFrederic Weisbecker stime = scale_stime(stime, rtime, stime + utime); 6389d7fb042SPeter Zijlstra 639173be9a1SPeter Zijlstra update: 6409d7fb042SPeter Zijlstra /* 6419d7fb042SPeter Zijlstra * Make sure stime doesn't go backwards; this preserves monotonicity 6429d7fb042SPeter Zijlstra * for utime because rtime is monotonic. 6439d7fb042SPeter Zijlstra * 6449d7fb042SPeter Zijlstra * utime_i+1 = rtime_i+1 - stime_i 6459d7fb042SPeter Zijlstra * = rtime_i+1 - (rtime_i - utime_i) 6469d7fb042SPeter Zijlstra * = (rtime_i+1 - rtime_i) + utime_i 6479d7fb042SPeter Zijlstra * >= utime_i 6489d7fb042SPeter Zijlstra */ 6499d7fb042SPeter Zijlstra if (stime < prev->stime) 6509d7fb042SPeter Zijlstra stime = prev->stime; 6519d7fb042SPeter Zijlstra utime = rtime - stime; 6529d7fb042SPeter Zijlstra 6539d7fb042SPeter Zijlstra /* 6549d7fb042SPeter Zijlstra * Make sure utime doesn't go backwards; this still preserves 6559d7fb042SPeter Zijlstra * monotonicity for stime, analogous argument to above. 6569d7fb042SPeter Zijlstra */ 6579d7fb042SPeter Zijlstra if (utime < prev->utime) { 6589d7fb042SPeter Zijlstra utime = prev->utime; 6599d7fb042SPeter Zijlstra stime = rtime - utime; 6609d7fb042SPeter Zijlstra } 6619d7fb042SPeter Zijlstra 6629d7fb042SPeter Zijlstra prev->stime = stime; 6639d7fb042SPeter Zijlstra prev->utime = utime; 664772c808aSStanislaw Gruszka out: 665d37f761dSFrederic Weisbecker *ut = prev->utime; 666d37f761dSFrederic Weisbecker *st = prev->stime; 6679d7fb042SPeter Zijlstra raw_spin_unlock_irqrestore(&prev->lock, flags); 668d37f761dSFrederic Weisbecker } 669d37f761dSFrederic Weisbecker 6705613fda9SFrederic Weisbecker void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st) 671d37f761dSFrederic Weisbecker { 672d37f761dSFrederic Weisbecker struct task_cputime cputime = { 673d37f761dSFrederic Weisbecker .sum_exec_runtime = p->se.sum_exec_runtime, 674d37f761dSFrederic Weisbecker }; 675d37f761dSFrederic Weisbecker 6766fac4829SFrederic Weisbecker task_cputime(p, &cputime.utime, &cputime.stime); 677d37f761dSFrederic Weisbecker cputime_adjust(&cputime, &p->prev_cputime, ut, st); 67873fbec60SFrederic Weisbecker } 6799eec50b8SAndrey Smetanin EXPORT_SYMBOL_GPL(task_cputime_adjusted); 68073fbec60SFrederic Weisbecker 6815613fda9SFrederic Weisbecker void thread_group_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st) 68273fbec60SFrederic Weisbecker { 68373fbec60SFrederic Weisbecker struct task_cputime cputime; 68473fbec60SFrederic Weisbecker 68573fbec60SFrederic Weisbecker thread_group_cputime(p, &cputime); 686d37f761dSFrederic Weisbecker cputime_adjust(&cputime, &p->signal->prev_cputime, ut, st); 68773fbec60SFrederic Weisbecker } 6889fbc42eaSFrederic Weisbecker #endif /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ 689abf917cdSFrederic Weisbecker 690abf917cdSFrederic Weisbecker #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN 691ff9a9b4cSRik van Riel static cputime_t vtime_delta(struct task_struct *tsk) 692abf917cdSFrederic Weisbecker { 693ff9a9b4cSRik van Riel unsigned long now = READ_ONCE(jiffies); 694abf917cdSFrederic Weisbecker 695ff9a9b4cSRik van Riel if (time_before(now, (unsigned long)tsk->vtime_snap)) 6966a61671bSFrederic Weisbecker return 0; 6976a61671bSFrederic Weisbecker 698ff9a9b4cSRik van Riel return jiffies_to_cputime(now - tsk->vtime_snap); 6996a61671bSFrederic Weisbecker } 7006a61671bSFrederic Weisbecker 7016a61671bSFrederic Weisbecker static cputime_t get_vtime_delta(struct task_struct *tsk) 7026a61671bSFrederic Weisbecker { 703ff9a9b4cSRik van Riel unsigned long now = READ_ONCE(jiffies); 704b58c3584SRik van Riel cputime_t delta, other; 7056a61671bSFrederic Weisbecker 70603cbc732SWanpeng Li /* 70703cbc732SWanpeng Li * Unlike tick based timing, vtime based timing never has lost 70803cbc732SWanpeng Li * ticks, and no need for steal time accounting to make up for 70903cbc732SWanpeng Li * lost ticks. Vtime accounts a rounded version of actual 71003cbc732SWanpeng Li * elapsed time. Limit account_other_time to prevent rounding 71103cbc732SWanpeng Li * errors from causing elapsed vtime to go negative. 71203cbc732SWanpeng Li */ 71357430218SRik van Riel delta = jiffies_to_cputime(now - tsk->vtime_snap); 714b58c3584SRik van Riel other = account_other_time(delta); 7157098c1eaSFrederic Weisbecker WARN_ON_ONCE(tsk->vtime_snap_whence == VTIME_INACTIVE); 716ff9a9b4cSRik van Riel tsk->vtime_snap = now; 717abf917cdSFrederic Weisbecker 718b58c3584SRik van Riel return delta - other; 719abf917cdSFrederic Weisbecker } 720abf917cdSFrederic Weisbecker 7216a61671bSFrederic Weisbecker static void __vtime_account_system(struct task_struct *tsk) 7226a61671bSFrederic Weisbecker { 7236a61671bSFrederic Weisbecker cputime_t delta_cpu = get_vtime_delta(tsk); 7246a61671bSFrederic Weisbecker 72540565b5aSStanislaw Gruszka account_system_time(tsk, irq_count(), delta_cpu); 7266a61671bSFrederic Weisbecker } 7276a61671bSFrederic Weisbecker 728abf917cdSFrederic Weisbecker void vtime_account_system(struct task_struct *tsk) 729abf917cdSFrederic Weisbecker { 730ff9a9b4cSRik van Riel if (!vtime_delta(tsk)) 731ff9a9b4cSRik van Riel return; 732ff9a9b4cSRik van Riel 733b7ce2277SFrederic Weisbecker write_seqcount_begin(&tsk->vtime_seqcount); 7346a61671bSFrederic Weisbecker __vtime_account_system(tsk); 735b7ce2277SFrederic Weisbecker write_seqcount_end(&tsk->vtime_seqcount); 7366a61671bSFrederic Weisbecker } 7376a61671bSFrederic Weisbecker 738abf917cdSFrederic Weisbecker void vtime_account_user(struct task_struct *tsk) 739abf917cdSFrederic Weisbecker { 7403f4724eaSFrederic Weisbecker cputime_t delta_cpu; 7413f4724eaSFrederic Weisbecker 742b7ce2277SFrederic Weisbecker write_seqcount_begin(&tsk->vtime_seqcount); 7436a61671bSFrederic Weisbecker tsk->vtime_snap_whence = VTIME_SYS; 744ff9a9b4cSRik van Riel if (vtime_delta(tsk)) { 745ff9a9b4cSRik van Riel delta_cpu = get_vtime_delta(tsk); 74623244a5cSFrederic Weisbecker account_user_time(tsk, cputime_to_nsecs(delta_cpu)); 747ff9a9b4cSRik van Riel } 748b7ce2277SFrederic Weisbecker write_seqcount_end(&tsk->vtime_seqcount); 7496a61671bSFrederic Weisbecker } 7506a61671bSFrederic Weisbecker 7516a61671bSFrederic Weisbecker void vtime_user_enter(struct task_struct *tsk) 7526a61671bSFrederic Weisbecker { 753b7ce2277SFrederic Weisbecker write_seqcount_begin(&tsk->vtime_seqcount); 754ff9a9b4cSRik van Riel if (vtime_delta(tsk)) 7556a61671bSFrederic Weisbecker __vtime_account_system(tsk); 756af2350bdSFrederic Weisbecker tsk->vtime_snap_whence = VTIME_USER; 757b7ce2277SFrederic Weisbecker write_seqcount_end(&tsk->vtime_seqcount); 7586a61671bSFrederic Weisbecker } 7596a61671bSFrederic Weisbecker 7606a61671bSFrederic Weisbecker void vtime_guest_enter(struct task_struct *tsk) 7616a61671bSFrederic Weisbecker { 7625b206d48SFrederic Weisbecker /* 7635b206d48SFrederic Weisbecker * The flags must be updated under the lock with 7645b206d48SFrederic Weisbecker * the vtime_snap flush and update. 7655b206d48SFrederic Weisbecker * That enforces a right ordering and update sequence 7665b206d48SFrederic Weisbecker * synchronization against the reader (task_gtime()) 7675b206d48SFrederic Weisbecker * that can thus safely catch up with a tickless delta. 7685b206d48SFrederic Weisbecker */ 769b7ce2277SFrederic Weisbecker write_seqcount_begin(&tsk->vtime_seqcount); 770ff9a9b4cSRik van Riel if (vtime_delta(tsk)) 7716a61671bSFrederic Weisbecker __vtime_account_system(tsk); 7726a61671bSFrederic Weisbecker current->flags |= PF_VCPU; 773b7ce2277SFrederic Weisbecker write_seqcount_end(&tsk->vtime_seqcount); 7746a61671bSFrederic Weisbecker } 77548d6a816SFrederic Weisbecker EXPORT_SYMBOL_GPL(vtime_guest_enter); 7766a61671bSFrederic Weisbecker 7776a61671bSFrederic Weisbecker void vtime_guest_exit(struct task_struct *tsk) 7786a61671bSFrederic Weisbecker { 779b7ce2277SFrederic Weisbecker write_seqcount_begin(&tsk->vtime_seqcount); 7806a61671bSFrederic Weisbecker __vtime_account_system(tsk); 7816a61671bSFrederic Weisbecker current->flags &= ~PF_VCPU; 782b7ce2277SFrederic Weisbecker write_seqcount_end(&tsk->vtime_seqcount); 783abf917cdSFrederic Weisbecker } 78448d6a816SFrederic Weisbecker EXPORT_SYMBOL_GPL(vtime_guest_exit); 785abf917cdSFrederic Weisbecker 786abf917cdSFrederic Weisbecker void vtime_account_idle(struct task_struct *tsk) 787abf917cdSFrederic Weisbecker { 7886a61671bSFrederic Weisbecker cputime_t delta_cpu = get_vtime_delta(tsk); 789abf917cdSFrederic Weisbecker 790abf917cdSFrederic Weisbecker account_idle_time(delta_cpu); 791abf917cdSFrederic Weisbecker } 7923f4724eaSFrederic Weisbecker 7936a61671bSFrederic Weisbecker void arch_vtime_task_switch(struct task_struct *prev) 7946a61671bSFrederic Weisbecker { 795b7ce2277SFrederic Weisbecker write_seqcount_begin(&prev->vtime_seqcount); 7967098c1eaSFrederic Weisbecker prev->vtime_snap_whence = VTIME_INACTIVE; 797b7ce2277SFrederic Weisbecker write_seqcount_end(&prev->vtime_seqcount); 7986a61671bSFrederic Weisbecker 799b7ce2277SFrederic Weisbecker write_seqcount_begin(¤t->vtime_seqcount); 8006a61671bSFrederic Weisbecker current->vtime_snap_whence = VTIME_SYS; 801ff9a9b4cSRik van Riel current->vtime_snap = jiffies; 802b7ce2277SFrederic Weisbecker write_seqcount_end(¤t->vtime_seqcount); 8036a61671bSFrederic Weisbecker } 8046a61671bSFrederic Weisbecker 80545eacc69SFrederic Weisbecker void vtime_init_idle(struct task_struct *t, int cpu) 8066a61671bSFrederic Weisbecker { 8076a61671bSFrederic Weisbecker unsigned long flags; 8086a61671bSFrederic Weisbecker 809b7ce2277SFrederic Weisbecker local_irq_save(flags); 810b7ce2277SFrederic Weisbecker write_seqcount_begin(&t->vtime_seqcount); 8116a61671bSFrederic Weisbecker t->vtime_snap_whence = VTIME_SYS; 812ff9a9b4cSRik van Riel t->vtime_snap = jiffies; 813b7ce2277SFrederic Weisbecker write_seqcount_end(&t->vtime_seqcount); 814b7ce2277SFrederic Weisbecker local_irq_restore(flags); 8156a61671bSFrederic Weisbecker } 8166a61671bSFrederic Weisbecker 81716a6d9beSFrederic Weisbecker u64 task_gtime(struct task_struct *t) 8186a61671bSFrederic Weisbecker { 8196a61671bSFrederic Weisbecker unsigned int seq; 82016a6d9beSFrederic Weisbecker u64 gtime; 8216a61671bSFrederic Weisbecker 822e5925394SFrederic Weisbecker if (!vtime_accounting_enabled()) 8232541117bSHiroshi Shimamoto return t->gtime; 8242541117bSHiroshi Shimamoto 8256a61671bSFrederic Weisbecker do { 826b7ce2277SFrederic Weisbecker seq = read_seqcount_begin(&t->vtime_seqcount); 8276a61671bSFrederic Weisbecker 8286a61671bSFrederic Weisbecker gtime = t->gtime; 829cab245d6SFrederic Weisbecker if (t->vtime_snap_whence == VTIME_SYS && t->flags & PF_VCPU) 83016a6d9beSFrederic Weisbecker gtime += cputime_to_nsecs(vtime_delta(t)); 8316a61671bSFrederic Weisbecker 832b7ce2277SFrederic Weisbecker } while (read_seqcount_retry(&t->vtime_seqcount, seq)); 8336a61671bSFrederic Weisbecker 8346a61671bSFrederic Weisbecker return gtime; 8356a61671bSFrederic Weisbecker } 8366a61671bSFrederic Weisbecker 8376a61671bSFrederic Weisbecker /* 8386a61671bSFrederic Weisbecker * Fetch cputime raw values from fields of task_struct and 8396a61671bSFrederic Weisbecker * add up the pending nohz execution time since the last 8406a61671bSFrederic Weisbecker * cputime snapshot. 8416a61671bSFrederic Weisbecker */ 8425613fda9SFrederic Weisbecker void task_cputime(struct task_struct *t, u64 *utime, u64 *stime) 8436a61671bSFrederic Weisbecker { 8445613fda9SFrederic Weisbecker u64 delta; 8456a61671bSFrederic Weisbecker unsigned int seq; 846353c50ebSStanislaw Gruszka 847353c50ebSStanislaw Gruszka if (!vtime_accounting_enabled()) { 848353c50ebSStanislaw Gruszka *utime = t->utime; 849353c50ebSStanislaw Gruszka *stime = t->stime; 850353c50ebSStanislaw Gruszka return; 851353c50ebSStanislaw Gruszka } 8526a61671bSFrederic Weisbecker 8536a61671bSFrederic Weisbecker do { 854b7ce2277SFrederic Weisbecker seq = read_seqcount_begin(&t->vtime_seqcount); 8556a61671bSFrederic Weisbecker 856353c50ebSStanislaw Gruszka *utime = t->utime; 857353c50ebSStanislaw Gruszka *stime = t->stime; 8586a61671bSFrederic Weisbecker 8596a61671bSFrederic Weisbecker /* Task is sleeping, nothing to add */ 860353c50ebSStanislaw Gruszka if (t->vtime_snap_whence == VTIME_INACTIVE || is_idle_task(t)) 8616a61671bSFrederic Weisbecker continue; 8626a61671bSFrederic Weisbecker 8635613fda9SFrederic Weisbecker delta = cputime_to_nsecs(vtime_delta(t)); 8646a61671bSFrederic Weisbecker 8656a61671bSFrederic Weisbecker /* 8666a61671bSFrederic Weisbecker * Task runs either in user or kernel space, add pending nohz time to 8676a61671bSFrederic Weisbecker * the right place. 8686a61671bSFrederic Weisbecker */ 869353c50ebSStanislaw Gruszka if (t->vtime_snap_whence == VTIME_USER || t->flags & PF_VCPU) 870353c50ebSStanislaw Gruszka *utime += delta; 871353c50ebSStanislaw Gruszka else if (t->vtime_snap_whence == VTIME_SYS) 872353c50ebSStanislaw Gruszka *stime += delta; 873b7ce2277SFrederic Weisbecker } while (read_seqcount_retry(&t->vtime_seqcount, seq)); 8746a61671bSFrederic Weisbecker } 875abf917cdSFrederic Weisbecker #endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */ 876