SMP gettimeofday patch

From: Larry Woodman (woodman@missioncriticallinux.com)
Date: Mon Apr 24 2000 - 11:19:57 EST


Here is a patch to make the gettimeofday system call more accurate for
Alpha SMP. Rather than
just returning xtime.tv_sec and xtime.tv_usec this patch makes each CPU
record its process cycle
counter in the cpuinfo_alpha structure for that CPU in
smp_percpu_timer_interrupt(). When
gettimeofday is called it adds the difference between the current
process cycle counter and last one
stored in the cpuinfo_alpha structure to the time.tv_sec and
xtime.tv_usec. This is not perfect but if
you stay on the same CPU its close to what is returned on a non-SMP
alpha kernel.

Larry Woodman
http://www.missioncriticallinux.com

diff -u --recursive linux-2.3.99-pre3.vanilla/arch/alpha/kernel/smp.c linux-2.3.99-pre3.clock/arch/alpha/kernel/smp.c
--- linux-2.3.99-pre3.vanilla/arch/alpha/kernel/smp.c Fri Mar 17 16:02:05 2000
+++ linux-2.3.99-pre3.clock/arch/alpha/kernel/smp.c Fri Apr 24 09:58:04 2020
@@ -613,6 +613,13 @@
                                unsigned long user, unsigned long system,
                                int cpu);
 
+static inline __u32 rpcc(void)
+{
+ __u32 result;
+ asm volatile ("rpcc %0" : "=r"(result));
+ return result;
+}
+
 void
 smp_percpu_timer_interrupt(struct pt_regs *regs)
 {
@@ -620,6 +627,8 @@
         unsigned long user = user_mode(regs);
         struct cpuinfo_alpha *data = &cpu_data[cpu];
 
+ /* remember the process cycle counter */
+ data->last_rpcc = rpcc();
         /* Record kernel PC. */
         if (!user)
                 alpha_do_profile(regs->pc);
diff -u --recursive linux-2.3.99-pre3.vanilla/arch/alpha/kernel/time.c linux-2.3.99-pre3.clock/arch/alpha/kernel/time.c
--- linux-2.3.99-pre3.vanilla/arch/alpha/kernel/time.c Wed Mar 15 14:08:04 2000
+++ linux-2.3.99-pre3.clock/arch/alpha/kernel/time.c Fri Apr 24 09:59:24 2020
@@ -304,10 +304,15 @@
 {
         unsigned long sec, usec, lost, flags;
         unsigned long delta_cycles, delta_usec, partial_tick;
+ struct cpuinfo_alpha *data = &cpu_data[smp_processor_id()];
 
         read_lock_irqsave(&xtime_lock, flags);
 
+#ifdef __SMP__
+ delta_cycles = rpcc() - data->last_rpcc;
+#else
         delta_cycles = rpcc() - state.last_time;
+#endif
         sec = xtime.tv_sec;
         usec = xtime.tv_usec;
         partial_tick = state.partial_tick;
@@ -315,11 +320,6 @@
 
         read_unlock_irqrestore(&xtime_lock, flags);
 
-#ifdef __SMP__
- /* Until and unless we figure out how to get cpu cycle counters
- in sync and keep them there, we can't use the rpcc tricks. */
- delta_usec = lost * (1000000 / HZ);
-#else
         /*
          * usec = cycles * ticks_per_cycle * 2**48 * 1e6 / (2**48 * ticks)
          * = cycles * (s_t_p_c) * 1e6 / (2**48 * ticks)
@@ -334,10 +334,11 @@
          */
 
         delta_usec = (delta_cycles * state.scaled_ticks_per_cycle
+#ifndef __SMP__
                       + partial_tick
+#endif
                       + (lost << FIX_SHIFT)) * 15625;
         delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
-#endif
 
         usec += delta_usec;
         if (usec >= 1000000) {
diff -u --recursive linux-2.3.99-pre3.vanilla/include/asm-alpha/smp.h linux-2.3.99-pre3.clock/include/asm-alpha/smp.h
--- linux-2.3.99-pre3.vanilla/include/asm-alpha/smp.h Fri Mar 17 16:02:05 2000
+++ linux-2.3.99-pre3.clock/include/asm-alpha/smp.h Fri Apr 24 10:00:35 2020
@@ -21,6 +21,7 @@
 
 #include <linux/threads.h>
 #include <asm/irq.h>
+#include <linux/types.h>
 
 struct cpuinfo_alpha {
         unsigned long loops_per_sec;
@@ -33,6 +34,7 @@
         unsigned long prof_multiplier;
         unsigned long prof_counter;
         int irq_count, bh_count;
+ __u32 last_rpcc;
         unsigned char mcheck_expected;
         unsigned char mcheck_taken;
         unsigned char mcheck_extra;



This archive was generated by hypermail 2b29 : Sun Apr 30 2000 - 21:00:20 EST