]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
[PATCH] improve precision of process accounting.
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 31 Dec 2008 14:11:39 +0000 (15:11 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 31 Dec 2008 14:11:47 +0000 (15:11 +0100)
The unit of the cputime accouting values that are stored per process is
currently a microsecond. The CPU timer has a maximum granularity of
2**-12 microseconds. There is no benefit in storing the per process values
in the lesser precision and there is the disadvantage that the backend
has to do the rounding to microseconds. The better solution is to use
the maximum granularity of the CPU timer as cputime unit.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/cputime.h
arch/s390/include/asm/lowcore.h
arch/s390/include/asm/system.h
arch/s390/include/asm/thread_info.h
arch/s390/kernel/vtime.c

index 133ce054fc8945dbe4d18a7fe8fd031908410c3b..521726430afac81fcb19e870e4765a44fa85e528 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <asm/div64.h>
 
-/* We want to use micro-second resolution. */
+/* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */
 
 typedef unsigned long long cputime_t;
 typedef unsigned long long cputime64_t;
@@ -53,9 +53,9 @@ __div(unsigned long long n, unsigned int base)
 #define cputime_ge(__a, __b)           ((__a) >= (__b))
 #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_jiffies(__ct)       (__div((__ct), 4096000000ULL / 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) * (4096000000ULL / HZ))
 
 #define cputime64_zero                 (0ULL)
 #define cputime64_add(__a, __b)                ((__a) + (__b))
@@ -64,7 +64,7 @@ __div(unsigned long long n, unsigned int base)
 static inline u64
 cputime64_to_jiffies64(cputime64_t cputime)
 {
-       do_div(cputime, 1000000 / HZ);
+       do_div(cputime, 4096000000ULL / HZ);
        return cputime;
 }
 
@@ -74,13 +74,13 @@ cputime64_to_jiffies64(cputime64_t cputime)
 static inline unsigned int
 cputime_to_msecs(const cputime_t cputime)
 {
-       return __div(cputime, 1000);
+       return __div(cputime, 4096000);
 }
 
 static inline cputime_t
 msecs_to_cputime(const unsigned int m)
 {
-       return (cputime_t) m * 1000;
+       return (cputime_t) m * 4096000;
 }
 
 /*
@@ -89,13 +89,13 @@ msecs_to_cputime(const unsigned int m)
 static inline unsigned int
 cputime_to_secs(const cputime_t cputime)
 {
-       return __div(cputime, 1000000);
+       return __div(cputime, 2048000000) >> 1;
 }
 
 static inline cputime_t
 secs_to_cputime(const unsigned int s)
 {
-       return (cputime_t) s * 1000000;
+       return (cputime_t) s * 4096000000ULL;
 }
 
 /*
@@ -104,7 +104,7 @@ secs_to_cputime(const unsigned int s)
 static inline cputime_t
 timespec_to_cputime(const struct timespec *value)
 {
-        return value->tv_nsec / 1000 + (u64) value->tv_sec * 1000000;
+       return value->tv_nsec * 4096 / 1000 + (u64) value->tv_sec * 4096000000ULL;
 }
 
 static inline void
@@ -114,12 +114,12 @@ cputime_to_timespec(const cputime_t cputime, struct timespec *value)
        register_pair rp;
 
        rp.pair = cputime >> 1;
-       asm ("dr %0,%1" : "+d" (rp) : "d" (1000000 >> 1));
-       value->tv_nsec = rp.subreg.even * 1000;
+       asm ("dr %0,%1" : "+d" (rp) : "d" (2048000000UL));
+       value->tv_nsec = rp.subreg.even * 1000 / 4096;
        value->tv_sec = rp.subreg.odd;
 #else
-       value->tv_nsec = (cputime % 1000000) * 1000;
-       value->tv_sec = cputime / 1000000;
+       value->tv_nsec = (cputime % 4096000000ULL) * 1000 / 4096;
+       value->tv_sec = cputime / 4096000000ULL;
 #endif
 }
 
@@ -131,7 +131,7 @@ cputime_to_timespec(const cputime_t cputime, struct timespec *value)
 static inline cputime_t
 timeval_to_cputime(const struct timeval *value)
 {
-        return value->tv_usec + (u64) value->tv_sec * 1000000;
+       return value->tv_usec * 4096 + (u64) value->tv_sec * 4096000000ULL;
 }
 
 static inline void
@@ -141,12 +141,12 @@ cputime_to_timeval(const cputime_t cputime, struct timeval *value)
        register_pair rp;
 
        rp.pair = cputime >> 1;
-       asm ("dr %0,%1" : "+d" (rp) : "d" (1000000 >> 1));
-       value->tv_usec = rp.subreg.even;
+       asm ("dr %0,%1" : "+d" (rp) : "d" (2048000000UL));
+       value->tv_usec = rp.subreg.even / 4096;
        value->tv_sec = rp.subreg.odd;
 #else
-       value->tv_usec = cputime % 1000000;
-       value->tv_sec = cputime / 1000000;
+       value->tv_usec = cputime % 4096000000ULL;
+       value->tv_sec = cputime / 4096000000ULL;
 #endif
 }
 
@@ -156,13 +156,13 @@ cputime_to_timeval(const cputime_t cputime, struct timeval *value)
 static inline clock_t
 cputime_to_clock_t(cputime_t cputime)
 {
-       return __div(cputime, 1000000 / USER_HZ);
+       return __div(cputime, 4096000000ULL / USER_HZ);
 }
 
 static inline cputime_t
 clock_t_to_cputime(unsigned long x)
 {
-       return (cputime_t) x * (1000000 / USER_HZ);
+       return (cputime_t) x * (4096000000ULL / USER_HZ);
 }
 
 /*
@@ -171,7 +171,7 @@ clock_t_to_cputime(unsigned long x)
 static inline clock_t
 cputime64_to_clock_t(cputime64_t cputime)
 {
-       return __div(cputime, 1000000 / USER_HZ);
+       return __div(cputime, 4096000000ULL / USER_HZ);
 }
 
 #endif /* _S390_CPUTIME_H */
index 0bc51d52a899d5b1d07b3bd1dceafa6858a0a3ef..a547817cf1ab538453e844b867810f00d04267c1 100644 (file)
 #define __LC_SYNC_ENTER_TIMER          0x248
 #define __LC_ASYNC_ENTER_TIMER         0x250
 #define __LC_EXIT_TIMER                        0x258
-#define __LC_LAST_UPDATE_TIMER         0x260
-#define __LC_USER_TIMER                        0x268
-#define __LC_SYSTEM_TIMER              0x270
-#define __LC_LAST_UPDATE_CLOCK         0x278
-#define __LC_STEAL_CLOCK               0x280
+#define __LC_USER_TIMER                        0x260
+#define __LC_SYSTEM_TIMER              0x268
+#define __LC_STEAL_TIMER               0x270
+#define __LC_LAST_UPDATE_TIMER         0x278
+#define __LC_LAST_UPDATE_CLOCK         0x280
 #define __LC_RETURN_MCCK_PSW            0x288
 #define __LC_KERNEL_STACK               0xC40
 #define __LC_THREAD_INFO               0xC44
 #define __LC_SYNC_ENTER_TIMER          0x250
 #define __LC_ASYNC_ENTER_TIMER         0x258
 #define __LC_EXIT_TIMER                        0x260
-#define __LC_LAST_UPDATE_TIMER         0x268
-#define __LC_USER_TIMER                        0x270
-#define __LC_SYSTEM_TIMER              0x278
-#define __LC_LAST_UPDATE_CLOCK         0x280
-#define __LC_STEAL_CLOCK               0x288
+#define __LC_USER_TIMER                        0x268
+#define __LC_SYSTEM_TIMER              0x270
+#define __LC_STEAL_TIMER               0x278
+#define __LC_LAST_UPDATE_TIMER         0x280
+#define __LC_LAST_UPDATE_CLOCK         0x288
 #define __LC_RETURN_MCCK_PSW            0x290
 #define __LC_KERNEL_STACK               0xD40
 #define __LC_THREAD_INFO               0xD48
@@ -252,11 +252,11 @@ struct _lowcore
        __u64        sync_enter_timer;         /* 0x248 */
        __u64        async_enter_timer;        /* 0x250 */
        __u64        exit_timer;               /* 0x258 */
-       __u64        last_update_timer;        /* 0x260 */
-       __u64        user_timer;               /* 0x268 */
-       __u64        system_timer;             /* 0x270 */
-       __u64        last_update_clock;        /* 0x278 */
-       __u64        steal_clock;              /* 0x280 */
+       __u64        user_timer;               /* 0x260 */
+       __u64        system_timer;             /* 0x268 */
+       __u64        steal_timer;              /* 0x270 */
+       __u64        last_update_timer;        /* 0x278 */
+       __u64        last_update_clock;        /* 0x280 */
         psw_t        return_mcck_psw;          /* 0x288 */
        __u8         pad8[0xc00-0x290];        /* 0x290 */
 
@@ -343,11 +343,11 @@ struct _lowcore
        __u64        sync_enter_timer;         /* 0x250 */
        __u64        async_enter_timer;        /* 0x258 */
        __u64        exit_timer;               /* 0x260 */
-       __u64        last_update_timer;        /* 0x268 */
-       __u64        user_timer;               /* 0x270 */
-       __u64        system_timer;             /* 0x278 */
-       __u64        last_update_clock;        /* 0x280 */
-       __u64        steal_clock;              /* 0x288 */
+       __u64        user_timer;               /* 0x268 */
+       __u64        system_timer;             /* 0x270 */
+       __u64        steal_timer;              /* 0x278 */
+       __u64        last_update_timer;        /* 0x280 */
+       __u64        last_update_clock;        /* 0x288 */
         psw_t        return_mcck_psw;          /* 0x290 */
         __u8         pad8[0xc00-0x2a0];        /* 0x2a0 */
         /* System info area */
index 024ef42ed6d73e44d510466680f7fbc54710b05c..3a8b26eb1f2e827d3d6de72b508dd307c08de6a0 100644 (file)
@@ -99,7 +99,7 @@ static inline void restore_access_regs(unsigned int *acrs)
        prev = __switch_to(prev,next);                                       \
 } while (0)
 
-extern void account_vtime(struct task_struct *);
+extern void account_vtime(struct task_struct *, struct task_struct *);
 extern void account_tick_vtime(struct task_struct *);
 extern void account_system_vtime(struct task_struct *);
 
@@ -121,7 +121,7 @@ static inline void cmma_init(void) { }
 
 #define finish_arch_switch(prev) do {                                       \
        set_fs(current->thread.mm_segment);                                  \
-       account_vtime(prev);                                                 \
+       account_vtime(prev, current);                                        \
 } while (0)
 
 #define nop() asm volatile("nop")
index c1eaf9604da73363832a88756f7a4118af5c4023..c544aa5245350c2e517c8712352b3b54648df569 100644 (file)
@@ -47,6 +47,8 @@ struct thread_info {
        unsigned int            cpu;            /* current CPU */
        int                     preempt_count;  /* 0 => preemptable, <0 => BUG */
        struct restart_block    restart_block;
+       __u64                   user_timer;
+       __u64                   system_timer;
 };
 
 /*
index 4a4a34caec55cdb277806b8e0ddbc787cedc1003..1254a4d0d7622d051a3d2b58762dadf4fb86922e 100644 (file)
@@ -31,11 +31,10 @@ static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
  * Update process times based on virtual cpu times stored by entry.S
  * to the lowcore fields user_timer, system_timer & steal_clock.
  */
-void account_process_tick(struct task_struct *tsk, int user_tick)
+static void do_account_vtime(struct task_struct *tsk, int hardirq_offset)
 {
-       cputime_t cputime;
-       __u64 timer, clock;
-       int rcu_user_flag;
+       struct thread_info *ti = task_thread_info(tsk);
+       __u64 timer, clock, user, system, steal;
 
        timer = S390_lowcore.last_update_timer;
        clock = S390_lowcore.last_update_clock;
@@ -44,59 +43,47 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
                      : "=m" (S390_lowcore.last_update_timer),
                        "=m" (S390_lowcore.last_update_clock) );
        S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
-       S390_lowcore.steal_clock += S390_lowcore.last_update_clock - clock;
+       S390_lowcore.steal_timer += S390_lowcore.last_update_clock - clock;
 
-       cputime = S390_lowcore.user_timer >> 12;
-       rcu_user_flag = cputime != 0;
-       S390_lowcore.user_timer -= cputime << 12;
-       S390_lowcore.steal_clock -= cputime << 12;
-       account_user_time(tsk, cputime, cputime);
+       user = S390_lowcore.user_timer - ti->user_timer;
+       S390_lowcore.steal_timer -= user;
+       ti->user_timer = S390_lowcore.user_timer;
+       account_user_time(tsk, user, user);
 
-       cputime =  S390_lowcore.system_timer >> 12;
-       S390_lowcore.system_timer -= cputime << 12;
-       S390_lowcore.steal_clock -= cputime << 12;
+       system = S390_lowcore.system_timer - ti->system_timer;
+       S390_lowcore.steal_timer -= system;
+       ti->system_timer = S390_lowcore.system_timer;
        if (idle_task(smp_processor_id()) != current)
-               account_system_time(tsk, HARDIRQ_OFFSET, cputime, cputime);
+               account_system_time(tsk, hardirq_offset, system, system);
        else
-               account_idle_time(cputime);
+               account_idle_time(system);
 
-       cputime = S390_lowcore.steal_clock;
-       if ((__s64) cputime > 0) {
-               cputime >>= 12;
-               S390_lowcore.steal_clock -= cputime << 12;
+       steal = S390_lowcore.steal_timer;
+       if ((s64) steal > 0) {
+               S390_lowcore.steal_timer = 0;
                if (idle_task(smp_processor_id()) != current)
-                       account_steal_time(cputime);
+                       account_steal_time(steal);
                else
-                       account_idle_time(cputime);
+                       account_idle_time(steal);
        }
 }
 
-/*
- * Update process times based on virtual cpu times stored by entry.S
- * to the lowcore fields user_timer, system_timer & steal_clock.
- */
-void account_vtime(struct task_struct *tsk)
+void account_vtime(struct task_struct *prev, struct task_struct *next)
 {
-       cputime_t cputime;
-       __u64 timer;
-
-       timer = S390_lowcore.last_update_timer;
-       asm volatile ("  STPT %0"    /* Store current cpu timer value */
-                     : "=m" (S390_lowcore.last_update_timer) );
-       S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
-
-       cputime = S390_lowcore.user_timer >> 12;
-       S390_lowcore.user_timer -= cputime << 12;
-       S390_lowcore.steal_clock -= cputime << 12;
-       account_user_time(tsk, cputime, cputime);
+       struct thread_info *ti;
+
+       do_account_vtime(prev, 0);
+       ti = task_thread_info(prev);
+       ti->user_timer = S390_lowcore.user_timer;
+       ti->system_timer = S390_lowcore.system_timer;
+       ti = task_thread_info(next);
+       S390_lowcore.user_timer = ti->user_timer;
+       S390_lowcore.system_timer = ti->system_timer;
+}
 
-       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);
+void account_process_tick(struct task_struct *tsk, int user_tick)
+{
+       do_account_vtime(tsk, HARDIRQ_OFFSET);
 }
 
 /*
@@ -105,21 +92,21 @@ void account_vtime(struct task_struct *tsk)
  */
 void account_system_vtime(struct task_struct *tsk)
 {
-       cputime_t cputime;
-       __u64 timer;
+       struct thread_info *ti = task_thread_info(tsk);
+       __u64 timer, system;
 
        timer = S390_lowcore.last_update_timer;
        asm volatile ("  STPT %0"    /* Store current cpu timer value */
                      : "=m" (S390_lowcore.last_update_timer) );
        S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
 
-       cputime =  S390_lowcore.system_timer >> 12;
-       S390_lowcore.system_timer -= cputime << 12;
-       S390_lowcore.steal_clock -= cputime << 12;
+       system = S390_lowcore.system_timer - ti->system_timer;
+       S390_lowcore.steal_timer -= system;
+       ti->system_timer = S390_lowcore.system_timer;
        if (in_irq() || idle_task(smp_processor_id()) != current)
-               account_system_time(tsk, 0, cputime, cputime);
+               account_system_time(tsk, 0, system, system);
        else
-               account_idle_time(cputime);
+               account_idle_time(system);
 }
 EXPORT_SYMBOL_GPL(account_system_vtime);
 
@@ -490,8 +477,8 @@ void init_cpu_vtimer(void)
        /* kick the virtual timer */
        S390_lowcore.exit_timer = VTIMER_MAX_SLICE;
        S390_lowcore.last_update_timer = VTIMER_MAX_SLICE;
-       asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer));
        asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock));
+       asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer));
 
        /* enable cpu timer interrupts */
        __ctl_set_bit(0,10);