vserver 1.9.5.x5
[linux-2.6.git] / arch / s390 / kernel / time.c
index 12f46a6..995e2cd 100644 (file)
@@ -150,71 +150,9 @@ int do_settimeofday(struct timespec *tv)
 
 EXPORT_SYMBOL(do_settimeofday);
 
-#ifndef CONFIG_ARCH_S390X
-
-static inline __u32
-__calculate_ticks(__u64 elapsed)
-{
-       register_pair rp;
-
-       rp.pair = elapsed >> 1;
-       asm ("dr %0,%1" : "+d" (rp) : "d" (CLK_TICKS_PER_JIFFY >> 1));
-       return rp.subreg.odd;
-}
-
-#else /* CONFIG_ARCH_S390X */
-
-static inline __u32
-__calculate_ticks(__u64 elapsed)
-{
-       return elapsed / CLK_TICKS_PER_JIFFY;
-}
-
-#endif /* CONFIG_ARCH_S390X */
-
 
 #ifdef CONFIG_PROFILING
-extern char _stext, _etext;
-
-/*
- * The profiling function is SMP safe. (nothing can mess
- * around with "current", and the profiling counters are
- * updated with atomic operations). This is especially
- * useful with a profiling multiplier != 1
- */
-static inline void s390_do_profile(struct pt_regs * regs)
-{
-       unsigned long eip;
-       extern cpumask_t prof_cpu_mask;
-
-       profile_hook(regs);
-
-       if (user_mode(regs))
-               return;
-
-       if (!prof_buffer)
-               return;
-
-       eip = instruction_pointer(regs);
-
-       /*
-        * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-        * (default is all CPUs.)
-        */
-       if (!cpu_isset(smp_processor_id(), prof_cpu_mask))
-               return;
-
-       eip -= (unsigned long) &_stext;
-       eip >>= prof_shift;
-       /*
-        * Don't ignore out-of-bounds EIP values silently,
-        * put them into the last histogram slot, so if
-        * present, they will show up as a sharp peak.
-        */
-       if (eip > prof_len-1)
-               eip = prof_len-1;
-       atomic_inc((atomic_t *)&prof_buffer[eip]);
-}
+#define s390_do_profile(regs)  profile_tick(CPU_PROFILING, regs)
 #else
 #define s390_do_profile(regs)  do { ; } while(0)
 #endif /* CONFIG_PROFILING */
@@ -227,14 +165,14 @@ static inline void s390_do_profile(struct pt_regs * regs)
 void account_ticks(struct pt_regs *regs)
 {
        __u64 tmp;
-       __u32 ticks;
+       __u32 ticks, xticks;
 
        /* Calculate how many ticks have passed. */
        if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer)
                return;
        tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer;
        if (tmp >= 2*CLK_TICKS_PER_JIFFY) {  /* more than two ticks ? */
-               ticks = __calculate_ticks(tmp) + 1;
+               ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1;
                S390_lowcore.jiffy_timer +=
                        CLK_TICKS_PER_JIFFY * (__u64) ticks;
        } else if (tmp >= CLK_TICKS_PER_JIFFY) {
@@ -256,11 +194,9 @@ void account_ticks(struct pt_regs *regs)
         */
        write_seqlock(&xtime_lock);
        if (S390_lowcore.jiffy_timer > xtime_cc) {
-               __u32 xticks;
-
                tmp = S390_lowcore.jiffy_timer - xtime_cc;
                if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
-                       xticks = __calculate_ticks(tmp);
+                       xticks = __div(tmp, CLK_TICKS_PER_JIFFY);
                        xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY;
                } else {
                        xticks = 1;
@@ -270,12 +206,18 @@ void account_ticks(struct pt_regs *regs)
                        do_timer(regs);
        }
        write_sequnlock(&xtime_lock);
-       while (ticks--)
-               update_process_times(user_mode(regs));
 #else
-       while (ticks--)
+       for (xticks = ticks; xticks > 0; xticks--)
                do_timer(regs);
 #endif
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+       account_user_vtime(current);
+#else
+       while (ticks--)
+               update_process_times(user_mode(regs));
+#endif
+
        s390_do_profile(regs);
 }
 
@@ -298,18 +240,21 @@ static inline void stop_hz_timer(void)
        if (sysctl_hz_timer != 0)
                return;
 
+       cpu_set(smp_processor_id(), nohz_cpu_mask);
+
        /*
         * Leave the clock comparator set up for the next timer
         * tick if either rcu or a softirq is pending.
         */
-       if (rcu_pending(smp_processor_id()) || local_softirq_pending())
+       if (rcu_pending(smp_processor_id()) || local_softirq_pending()) {
+               cpu_clear(smp_processor_id(), nohz_cpu_mask);
                return;
+       }
 
        /*
         * This cpu is going really idle. Set up the clock comparator
         * for the next event.
         */
-       cpu_set(smp_processor_id(), nohz_cpu_mask);
        timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64;
        timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
        asm volatile ("SCKC %0" : : "m" (timer));