Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79741dd3 authored by Martin Schwidefsky's avatar Martin Schwidefsky
Browse files

[PATCH] idle cputime accounting



The cpu time spent by the idle process actually doing something is
currently accounted as idle time. This is plain wrong, the architectures
that support VIRT_CPU_ACCOUNTING=y can do better: distinguish between the
time spent doing nothing and the time spent by idle doing work. The first
is accounted with account_idle_time and the second with account_system_time.
The architectures that use the account_xxx_time interface directly and not
the account_xxx_ticks interface now need to do the check for the idle
process in their arch code. In particular to improve the system vs true
idle time accounting the arch code needs to measure the true idle time
instead of just testing for the idle process.
To improve the tick based accounting as well we would need an architecture
primitive that can tell us if the pt_regs of the interrupted context
points to the magic instruction that halts the cpu.

In addition idle time is no more added to the stime of the idle process.
This field now contains the system time of the idle process as it should
be. On systems without VIRT_CPU_ACCOUNTING this will always be zero as
every tick that occurs while idle is running will be accounted as idle
time.

This patch contains the necessary common code changes to be able to
distinguish idle system time and true idle time. The architectures with
support for VIRT_CPU_ACCOUNTING need some changes to exploit this.

Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 457533a7
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -93,7 +93,10 @@ void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next)
	now = ia64_get_itc();

	delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp));
	if (idle_task(smp_processor_id()) != prev)
		account_system_time(prev, 0, delta_stime, delta_stime);
	else
		account_idle_time(delta_stime);

	if (pi->ac_utime) {
		delta_utime = cycle_to_cputime(pi->ac_utime);
@@ -120,7 +123,10 @@ void account_system_vtime(struct task_struct *tsk)
	now = ia64_get_itc();

	delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp));
	if (irq_count() || idle_task(smp_processor_id()) != tsk)
		account_system_time(tsk, 0, delta_stime, delta_stime);
	else
		account_idle_time(delta_stime);
	ti->ac_stime = 0;

	ti->ac_stamp = now;
+1 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include <linux/mqueue.h>
#include <linux/hardirq.h>
#include <linux/utsname.h>
#include <linux/kernel_stat.h>

#include <asm/pgtable.h>
#include <asm/uaccess.h>
+10 −3
Original line number Diff line number Diff line
@@ -256,7 +256,10 @@ void account_system_vtime(struct task_struct *tsk)
		delta += sys_time;
		get_paca()->system_time = 0;
	}
	if (in_irq() || idle_task(smp_processor_id()) != tsk)
		account_system_time(tsk, 0, delta, deltascaled);
	else
		account_idle_time(delta);
	per_cpu(cputime_last_delta, smp_processor_id()) = delta;
	per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled;
	local_irq_restore(flags);
@@ -335,8 +338,12 @@ void calculate_steal_time(void)
	tb = mftb();
	purr = mfspr(SPRN_PURR);
	stolen = (tb - pme->tb) - (purr - pme->purr);
	if (stolen > 0)
		account_steal_time(current, stolen);
	if (stolen > 0) {
		if (idle_task(smp_processor_id()) != current)
			account_steal_time(stolen);
		else
			account_idle_time(stolen);
	}
	pme->tb = tb;
	pme->purr = purr;
}
+16 −4
Original line number Diff line number Diff line
@@ -55,13 +55,19 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
	cputime =  S390_lowcore.system_timer >> 12;
	S390_lowcore.system_timer -= cputime << 12;
	S390_lowcore.steal_clock -= cputime << 12;
	if (idle_task(smp_processor_id()) != current)
		account_system_time(tsk, HARDIRQ_OFFSET, cputime, cputime);
	else
		account_idle_time(cputime);

	cputime = S390_lowcore.steal_clock;
	if ((__s64) cputime > 0) {
		cputime >>= 12;
		S390_lowcore.steal_clock -= cputime << 12;
		account_steal_time(tsk, cputime);
		if (idle_task(smp_processor_id()) != current)
			account_steal_time(cputime);
		else
			account_idle_time(cputime);
	}
}

@@ -87,7 +93,10 @@ void account_vtime(struct task_struct *tsk)
	cputime =  S390_lowcore.system_timer >> 12;
	S390_lowcore.system_timer -= cputime << 12;
	S390_lowcore.steal_clock -= cputime << 12;
	if (idle_task(smp_processor_id()) != current)
		account_system_time(tsk, 0, cputime, cputime);
	else
		account_idle_time(cputime);
}

/*
@@ -107,7 +116,10 @@ void account_system_vtime(struct task_struct *tsk)
	cputime =  S390_lowcore.system_timer >> 12;
	S390_lowcore.system_timer -= cputime << 12;
	S390_lowcore.steal_clock -= cputime << 12;
	if (in_irq() || idle_task(smp_processor_id()) != current)
		account_system_time(tsk, 0, cputime, cputime);
	else
		account_idle_time(cputime);
}
EXPORT_SYMBOL_GPL(account_system_vtime);

+4 −6
Original line number Diff line number Diff line
@@ -132,8 +132,7 @@ static void do_stolen_accounting(void)
	*snap = state;

	/* Add the appropriate number of ticks of stolen time,
	   including any left-overs from last time.  Passing NULL to
	   account_steal_time accounts the time as stolen. */
	   including any left-overs from last time. */
	stolen = runnable + offline + __get_cpu_var(residual_stolen);

	if (stolen < 0)
@@ -141,11 +140,10 @@ static void do_stolen_accounting(void)

	ticks = iter_div_u64_rem(stolen, NS_PER_TICK, &stolen);
	__get_cpu_var(residual_stolen) = stolen;
	account_steal_time(NULL, ticks);
	account_steal_ticks(ticks);

	/* Add the appropriate number of ticks of blocked time,
	   including any left-overs from last time.  Passing idle to
	   account_steal_time accounts the time as idle/wait. */
	   including any left-overs from last time. */
	blocked += __get_cpu_var(residual_blocked);

	if (blocked < 0)
@@ -153,7 +151,7 @@ static void do_stolen_accounting(void)

	ticks = iter_div_u64_rem(blocked, NS_PER_TICK, &blocked);
	__get_cpu_var(residual_blocked) = blocked;
	account_steal_time(idle_task(smp_processor_id()), ticks);
	account_idle_ticks(ticks);
}

/*
Loading