/* * Account a tick to a process and cpustat * @p: the process that the cpu time gets accounted to * @user_tick: is the tick from userspace * @rq: the pointer to rq * * Tick demultiplexing follows the order * - pending hardirq update * - pending softirq update * - user_time * - idle_time * - system time * - check for guest_time * - else account as system_time * * Check for hardirq is done both for system and user time as there is * no timer going off while we are on hardirq and hence we may never get an * opportunity to update it solely in system time. * p->stime and friends are only updated on system time and not on irq * softirq as those do not count in task exec_runtime any more. */ static void irqtime_account_process_tick(struct task_struct *p, int user_tick, struct rq *rq) { cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); u64 *cpustat = kcpustat_this_cpu->cpustat; if (steal_account_process_tick()) return; if (irqtime_account_hi_update()) { cpustat[CPUTIME_IRQ] += (__force u64) cputime_one_jiffy; } else if (irqtime_account_si_update()) { cpustat[CPUTIME_SOFTIRQ] += (__force u64) cputime_one_jiffy; } else if (this_cpu_ksoftirqd() == p) { /* * ksoftirqd time do not get accounted in cpu_softirq_time. * So, we have to handle it separately here. * Also, p->stime needs to be updated for ksoftirqd. */ __account_system_time(p, cputime_one_jiffy, one_jiffy_scaled, CPUTIME_SOFTIRQ); } else if (user_tick) { account_user_time(p, cputime_one_jiffy, one_jiffy_scaled); } else if (p == rq->idle) { account_idle_time(cputime_one_jiffy); } else if (p->flags & PF_VCPU) { /* System time or guest time */ account_guest_time(p, cputime_one_jiffy, one_jiffy_scaled); } else { __account_system_time(p, cputime_one_jiffy, one_jiffy_scaled, CPUTIME_SYSTEM); } }
/* * Account system cpu time to a process. * @p: the process that the cpu time gets accounted to * @hardirq_offset: the offset to subtract from hardirq_count() * @cputime: the cpu time spent in kernel space since the last update */ void account_system_time(struct task_struct *p, int hardirq_offset, u64 cputime) { int index; if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) { account_guest_time(p, cputime); return; } if (hardirq_count() - hardirq_offset) index = CPUTIME_IRQ; else if (in_serving_softirq()) index = CPUTIME_SOFTIRQ; else index = CPUTIME_SYSTEM; account_system_index_time(p, cputime, index); }
void vtime_flush(struct task_struct *tsk) { struct thread_info *ti = task_thread_info(tsk); u64 delta; if (ti->utime) account_user_time(tsk, cycle_to_nsec(ti->utime)); if (ti->gtime) account_guest_time(tsk, cycle_to_nsec(ti->gtime)); if (ti->idle_time) account_idle_time(cycle_to_nsec(ti->idle_time)); if (ti->stime) { delta = cycle_to_nsec(ti->stime); account_system_index_time(tsk, delta, CPUTIME_SYSTEM); } if (ti->hardirq_time) { delta = cycle_to_nsec(ti->hardirq_time); account_system_index_time(tsk, delta, CPUTIME_IRQ); } if (ti->softirq_time) { delta = cycle_to_nsec(ti->softirq_time); account_system_index_time(tsk, delta, CPUTIME_SOFTIRQ); } ti->utime = 0; ti->gtime = 0; ti->idle_time = 0; ti->stime = 0; ti->hardirq_time = 0; ti->softirq_time = 0; }