Skip to content

Commit

Permalink
sched/cputime, ia64: Accumulate cputime and account only on tick/task…
Browse files Browse the repository at this point in the history
… switch

Currently CONFIG_VIRT_CPU_ACCOUNTING_NATIVE=y accounts the cputime on
any context boundary: irq entry/exit, guest entry/exit, context switch,
etc...

Calling functions such as account_system_time(), account_user_time()
and such can be costly, especially if they are called on many fastpath
such as twice per IRQ. Those functions do more than just accounting to
kcpustat and task cputime. Depending on the config, some subsystems can
perform unpleasant multiplications and divisions, among other things.

So lets accumulate the cputime instead and delay the accounting on ticks
and context switches only.

Signed-off-by: Frederic Weisbecker <[email protected]>
Acked-by: Thomas Gleixner <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Christian Borntraeger <[email protected]>
Cc: Fenghua Yu <[email protected]>
Cc: Heiko Carstens <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Martin Schwidefsky <[email protected]>
Cc: Michael Ellerman <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Rik van Riel <[email protected]>
Cc: Stanislaw Gruszka <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Wanpeng Li <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
fweisbec authored and Ingo Molnar committed Jan 14, 2017
1 parent a19ff1a commit 7dd5823
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 15 deletions.
6 changes: 6 additions & 0 deletions arch/ia64/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ struct thread_info {
mm_segment_t addr_limit; /* user-level address space limit */
int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
__u64 utime;
__u64 stime;
__u64 gtime;
__u64 hardirq_time;
__u64 softirq_time;
__u64 idle_time;
__u64 ac_stamp;
__u64 ac_leave;
__u64 ac_stime;
Expand Down
62 changes: 47 additions & 15 deletions arch/ia64/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,39 @@ extern cputime_t cycle_to_cputime(u64 cyc);

void vtime_account_user(struct task_struct *tsk)
{
cputime_t delta_utime;
struct thread_info *ti = task_thread_info(tsk);
cputime_t delta;

if (ti->ac_utime) {
delta_utime = cycle_to_cputime(ti->ac_utime);
account_user_time(tsk, delta_utime);
ti->ac_utime = 0;
if (ti->utime)
account_user_time(tsk, cycle_to_cputime(ti->utime));

if (ti->gtime)
account_guest_time(tsk, cycle_to_cputime(ti->gtime));

if (ti->idle_time)
account_idle_time(cycle_to_cputime(ti->idle_time));

if (ti->stime) {
delta = cycle_to_cputime(ti->stime);
account_system_index_time(tsk, delta, CPUTIME_SYSTEM);
}

if (ti->hardirq_time) {
delta = cycle_to_cputime(ti->hardirq_time);
account_system_index_time(tsk, delta, CPUTIME_IRQ);
}

if (ti->softirq_time) {
delta = cycle_to_cputime(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;
}

/*
Expand All @@ -91,34 +116,41 @@ void arch_vtime_task_switch(struct task_struct *prev)
* Account time for a transition between system, hard irq or soft irq state.
* Note that this function is called with interrupts enabled.
*/
static cputime_t vtime_delta(struct task_struct *tsk)
static __u64 vtime_delta(struct task_struct *tsk)
{
struct thread_info *ti = task_thread_info(tsk);
cputime_t delta_stime;
__u64 now;
__u64 now, delta_stime;

WARN_ON_ONCE(!irqs_disabled());

now = ia64_get_itc();

delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp));
ti->ac_stime = 0;
delta_stime = now - ti->ac_stamp;
ti->ac_stamp = now;

return delta_stime;
}

void vtime_account_system(struct task_struct *tsk)
{
cputime_t delta = vtime_delta(tsk);

account_system_time(tsk, 0, delta);
struct thread_info *ti = task_thread_info(tsk);
__u64 stime = vtime_delta(tsk);

if ((tsk->flags & PF_VCPU) && !irq_count())
ti->gtime += stime;
else if (hardirq_count())
ti->hardirq_time += stime;
else if (in_serving_softirq())
ti->softirq_time += stime;
else
ti->stime += stime;
}
EXPORT_SYMBOL_GPL(vtime_account_system);

void vtime_account_idle(struct task_struct *tsk)
{
account_idle_time(vtime_delta(tsk));
struct thread_info *ti = task_thread_info(tsk);

ti->idle_time += vtime_delta(tsk);
}

#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
Expand Down

0 comments on commit 7dd5823

Please sign in to comment.