xref: /openbmc/linux/kernel/sched/cputime.c (revision be9095ed4fb3cf69e9fdf64e28ff6b5bd0ec7215)
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(&paravirt_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(&current->vtime_seqcount);
8006a61671bSFrederic Weisbecker 	current->vtime_snap_whence = VTIME_SYS;
801ff9a9b4cSRik van Riel 	current->vtime_snap = jiffies;
802b7ce2277SFrederic Weisbecker 	write_seqcount_end(&current->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