taskstats scaled time cleanup
Michael Neuling [Wed, 6 Feb 2008 09:36:12 +0000 (01:36 -0800)]
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>

arch/powerpc/kernel/time.c
include/asm-generic/cputime.h
include/asm-powerpc/cputime.h
include/asm-powerpc/paca.h
include/asm-s390/cputime.h
kernel/timer.c

index 5cd3db5..3b26fbd 100644 (file)
@@ -66,6 +66,7 @@
 #include <asm/smp.h>
 #include <asm/vdso_datapage.h>
 #include <asm/firmware.h>
+#include <asm/cputime.h>
 #ifdef CONFIG_PPC_ISERIES
 #include <asm/iseries/it_lp_queue.h>
 #include <asm/iseries/hv_call_xm.h>
@@ -189,6 +190,8 @@ u64 __cputime_sec_factor;
 EXPORT_SYMBOL(__cputime_sec_factor);
 u64 __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)
 {
@@ -257,8 +260,8 @@ void account_system_vtime(struct task_struct *tsk)
        }
        account_system_time(tsk, 0, delta);
        account_system_time_scaled(tsk, deltascaled);
-       get_paca()->purrdelta = delta;
-       get_paca()->spurrdelta = deltascaled;
+       per_cpu(cputime_last_delta, smp_processor_id()) = delta;
+       per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled;
        local_irq_restore(flags);
 }
 
@@ -276,10 +279,7 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
        get_paca()->user_time = 0;
        account_user_time(tsk, utime);
 
-       /* Estimate the scaled utime by scaling the real utime based
-        * on the last spurr to purr ratio */
-       utimescaled = utime * get_paca()->spurrdelta / get_paca()->purrdelta;
-       get_paca()->spurrdelta = get_paca()->purrdelta = 0;
+       utimescaled = cputime_to_scaled(utime);
        account_user_time_scaled(tsk, utimescaled);
 }
 
index 09204e4..1c1fa42 100644 (file)
@@ -18,6 +18,7 @@ typedef unsigned long cputime_t;
 #define cputime_lt(__a, __b)           ((__a) <  (__b))
 #define cputime_le(__a, __b)           ((__a) <= (__b))
 #define cputime_to_jiffies(__ct)       (__ct)
+#define cputime_to_scaled(__ct)                (__ct)
 #define jiffies_to_cputime(__hz)       (__hz)
 
 typedef u64 cputime64_t;
index 3108044..f42e623 100644 (file)
@@ -52,12 +52,26 @@ typedef u64 cputime64_t;
  * Convert cputime <-> jiffies
  */
 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)
 {
        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)
 {
        cputime_t ct;
index f6dfce0..748b35a 100644 (file)
@@ -115,8 +115,6 @@ struct paca_struct {
        u64 system_time;                /* accumulated system TB ticks */
        u64 startpurr;                  /* PURR/TB value snapshot */
        u64 startspurr;                 /* SPURR value snapshot */
-       u64 purrdelta;                  /* FIXME: document */
-       u64 spurrdelta;                 /* FIXME: document */
 };
 
 extern struct paca_struct paca[];
index 4b3ef7c..133ce05 100644 (file)
@@ -54,6 +54,7 @@ __div(unsigned long long n, unsigned int base)
 #define cputime_lt(__a, __b)           ((__a) <  (__b))
 #define cputime_le(__a, __b)           ((__a) <= (__b))
 #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 cputime64_zero                 (0ULL)
index 9fbb472..70b29b5 100644 (file)
@@ -818,12 +818,14 @@ unsigned long next_timer_interrupt(void)
 #ifndef CONFIG_VIRT_CPU_ACCOUNTING
 void account_process_tick(struct task_struct *p, int user_tick)
 {
+       cputime_t one_jiffy = jiffies_to_cputime(1);
+
        if (user_tick) {
-               account_user_time(p, jiffies_to_cputime(1));
-               account_user_time_scaled(p, jiffies_to_cputime(1));
+               account_user_time(p, one_jiffy);
+               account_user_time_scaled(p, cputime_to_scaled(one_jiffy));
        } else {
-               account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1));
-               account_system_time_scaled(p, jiffies_to_cputime(1));
+               account_system_time(p, HARDIRQ_OFFSET, one_jiffy);
+               account_system_time_scaled(p, cputime_to_scaled(one_jiffy));
        }
 }
 #endif