taskstats scaled time cleanup
This moves the ability to scale cputime into generic code. This allows us to fix the issue in kernel/timer.c (noticed by Balbir) where we could only add an unscaled value to the scaled utime/stime. This adds a cputime_to_scaled function. As before, the POWERPC version does the scaling based on the last SPURR/PURR ratio calculated. The generic and s390 (only other arch to implement asm/cputime.h) versions are both NOPs. Also moves the SPURR and PURR snapshots closer. Signed-off-by: Michael Neuling <mikey@neuling.org> Cc: Jay Lan <jlan@engr.sgi.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
d9afa43532
Коммит
06b8e878a9
|
@ -66,6 +66,7 @@
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
#include <asm/vdso_datapage.h>
|
#include <asm/vdso_datapage.h>
|
||||||
#include <asm/firmware.h>
|
#include <asm/firmware.h>
|
||||||
|
#include <asm/cputime.h>
|
||||||
#ifdef CONFIG_PPC_ISERIES
|
#ifdef CONFIG_PPC_ISERIES
|
||||||
#include <asm/iseries/it_lp_queue.h>
|
#include <asm/iseries/it_lp_queue.h>
|
||||||
#include <asm/iseries/hv_call_xm.h>
|
#include <asm/iseries/hv_call_xm.h>
|
||||||
|
@ -189,6 +190,8 @@ u64 __cputime_sec_factor;
|
||||||
EXPORT_SYMBOL(__cputime_sec_factor);
|
EXPORT_SYMBOL(__cputime_sec_factor);
|
||||||
u64 __cputime_clockt_factor;
|
u64 __cputime_clockt_factor;
|
||||||
EXPORT_SYMBOL(__cputime_clockt_factor);
|
EXPORT_SYMBOL(__cputime_clockt_factor);
|
||||||
|
DEFINE_PER_CPU(unsigned long, cputime_last_delta);
|
||||||
|
DEFINE_PER_CPU(unsigned long, cputime_scaled_last_delta);
|
||||||
|
|
||||||
static void calc_cputime_factors(void)
|
static void calc_cputime_factors(void)
|
||||||
{
|
{
|
||||||
|
@ -257,8 +260,8 @@ void account_system_vtime(struct task_struct *tsk)
|
||||||
}
|
}
|
||||||
account_system_time(tsk, 0, delta);
|
account_system_time(tsk, 0, delta);
|
||||||
account_system_time_scaled(tsk, deltascaled);
|
account_system_time_scaled(tsk, deltascaled);
|
||||||
get_paca()->purrdelta = delta;
|
per_cpu(cputime_last_delta, smp_processor_id()) = delta;
|
||||||
get_paca()->spurrdelta = deltascaled;
|
per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled;
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,10 +279,7 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
|
||||||
get_paca()->user_time = 0;
|
get_paca()->user_time = 0;
|
||||||
account_user_time(tsk, utime);
|
account_user_time(tsk, utime);
|
||||||
|
|
||||||
/* Estimate the scaled utime by scaling the real utime based
|
utimescaled = cputime_to_scaled(utime);
|
||||||
* on the last spurr to purr ratio */
|
|
||||||
utimescaled = utime * get_paca()->spurrdelta / get_paca()->purrdelta;
|
|
||||||
get_paca()->spurrdelta = get_paca()->purrdelta = 0;
|
|
||||||
account_user_time_scaled(tsk, utimescaled);
|
account_user_time_scaled(tsk, utimescaled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ typedef unsigned long cputime_t;
|
||||||
#define cputime_lt(__a, __b) ((__a) < (__b))
|
#define cputime_lt(__a, __b) ((__a) < (__b))
|
||||||
#define cputime_le(__a, __b) ((__a) <= (__b))
|
#define cputime_le(__a, __b) ((__a) <= (__b))
|
||||||
#define cputime_to_jiffies(__ct) (__ct)
|
#define cputime_to_jiffies(__ct) (__ct)
|
||||||
|
#define cputime_to_scaled(__ct) (__ct)
|
||||||
#define jiffies_to_cputime(__hz) (__hz)
|
#define jiffies_to_cputime(__hz) (__hz)
|
||||||
|
|
||||||
typedef u64 cputime64_t;
|
typedef u64 cputime64_t;
|
||||||
|
|
|
@ -52,12 +52,26 @@ typedef u64 cputime64_t;
|
||||||
* Convert cputime <-> jiffies
|
* Convert cputime <-> jiffies
|
||||||
*/
|
*/
|
||||||
extern u64 __cputime_jiffies_factor;
|
extern u64 __cputime_jiffies_factor;
|
||||||
|
DECLARE_PER_CPU(unsigned long, cputime_last_delta);
|
||||||
|
DECLARE_PER_CPU(unsigned long, cputime_scaled_last_delta);
|
||||||
|
|
||||||
static inline unsigned long cputime_to_jiffies(const cputime_t ct)
|
static inline unsigned long cputime_to_jiffies(const cputime_t ct)
|
||||||
{
|
{
|
||||||
return mulhdu(ct, __cputime_jiffies_factor);
|
return mulhdu(ct, __cputime_jiffies_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Estimate the scaled cputime by scaling the real cputime based on
|
||||||
|
* the last scaled to real ratio */
|
||||||
|
static inline cputime_t cputime_to_scaled(const cputime_t ct)
|
||||||
|
{
|
||||||
|
if (cpu_has_feature(CPU_FTR_SPURR) &&
|
||||||
|
per_cpu(cputime_last_delta, smp_processor_id()))
|
||||||
|
return ct *
|
||||||
|
per_cpu(cputime_scaled_last_delta, smp_processor_id())/
|
||||||
|
per_cpu(cputime_last_delta, smp_processor_id());
|
||||||
|
return ct;
|
||||||
|
}
|
||||||
|
|
||||||
static inline cputime_t jiffies_to_cputime(const unsigned long jif)
|
static inline cputime_t jiffies_to_cputime(const unsigned long jif)
|
||||||
{
|
{
|
||||||
cputime_t ct;
|
cputime_t ct;
|
||||||
|
|
|
@ -115,8 +115,6 @@ struct paca_struct {
|
||||||
u64 system_time; /* accumulated system TB ticks */
|
u64 system_time; /* accumulated system TB ticks */
|
||||||
u64 startpurr; /* PURR/TB value snapshot */
|
u64 startpurr; /* PURR/TB value snapshot */
|
||||||
u64 startspurr; /* SPURR value snapshot */
|
u64 startspurr; /* SPURR value snapshot */
|
||||||
u64 purrdelta; /* FIXME: document */
|
|
||||||
u64 spurrdelta; /* FIXME: document */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct paca_struct paca[];
|
extern struct paca_struct paca[];
|
||||||
|
|
|
@ -54,6 +54,7 @@ __div(unsigned long long n, unsigned int base)
|
||||||
#define cputime_lt(__a, __b) ((__a) < (__b))
|
#define cputime_lt(__a, __b) ((__a) < (__b))
|
||||||
#define cputime_le(__a, __b) ((__a) <= (__b))
|
#define cputime_le(__a, __b) ((__a) <= (__b))
|
||||||
#define cputime_to_jiffies(__ct) (__div((__ct), 1000000 / HZ))
|
#define cputime_to_jiffies(__ct) (__div((__ct), 1000000 / HZ))
|
||||||
|
#define cputime_to_scaled(__ct) (__ct)
|
||||||
#define jiffies_to_cputime(__hz) ((cputime_t)(__hz) * (1000000 / HZ))
|
#define jiffies_to_cputime(__hz) ((cputime_t)(__hz) * (1000000 / HZ))
|
||||||
|
|
||||||
#define cputime64_zero (0ULL)
|
#define cputime64_zero (0ULL)
|
||||||
|
|
|
@ -818,12 +818,14 @@ unsigned long next_timer_interrupt(void)
|
||||||
#ifndef CONFIG_VIRT_CPU_ACCOUNTING
|
#ifndef CONFIG_VIRT_CPU_ACCOUNTING
|
||||||
void account_process_tick(struct task_struct *p, int user_tick)
|
void account_process_tick(struct task_struct *p, int user_tick)
|
||||||
{
|
{
|
||||||
|
cputime_t one_jiffy = jiffies_to_cputime(1);
|
||||||
|
|
||||||
if (user_tick) {
|
if (user_tick) {
|
||||||
account_user_time(p, jiffies_to_cputime(1));
|
account_user_time(p, one_jiffy);
|
||||||
account_user_time_scaled(p, jiffies_to_cputime(1));
|
account_user_time_scaled(p, cputime_to_scaled(one_jiffy));
|
||||||
} else {
|
} else {
|
||||||
account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1));
|
account_system_time(p, HARDIRQ_OFFSET, one_jiffy);
|
||||||
account_system_time_scaled(p, jiffies_to_cputime(1));
|
account_system_time_scaled(p, cputime_to_scaled(one_jiffy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Загрузка…
Ссылка в новой задаче