All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] rendezvous-based local time calibration WOW!
@ 2008-08-03 16:50 Dan Magenheimer
  2008-08-03 17:24 ` Keir Fraser
  0 siblings, 1 reply; 27+ messages in thread
From: Dan Magenheimer @ 2008-08-03 16:50 UTC (permalink / raw)
  To: Xen-Devel (E-mail), Keir Fraser; +Cc: Ian Pratt, Dave Winchell

[-- Attachment #1: Type: text/plain, Size: 1684 bytes --]

The synchronization of local_time_calibration (l_t_c) via
round-to-nearest-epoch provided some improvement, but I was
still seeing skew up to 16usec and higher.  I measured the
temporal distance between the rounded-epoch vs when ltc
was actually running to ensure there wasn't some kind of
bug and found that l_t_c was running up to 150us after the
round-epoch and sometimes up to 50us before.  I guess this
is the granularity of setting a Xen timer.  While it seemed
that +/- 100us shouldn't cause that much skew, I finally
decided to try synchronization-via-rendezvous, as suggested
by Ian here:

http://lists.xensource.com/archives/html/xen-devel/2008-07/msg01074.html
http://lists.xensource.com/archives/html/xen-devel/2008-07/msg01080.html

The result is phenomenal... using this approach (in attached
patch), I have yet to see a skew exceed 1usec!!!  So this is
about a 10-fold increase in accuracy vs the rounded-epoch
method and about 20-fold over the one-epoch-from-NOW() method.

The platform time is now read once for all processors rather
than once per processor.  (Actually, it is read once again
in platform_time_calibration()... by "inlining" that routine
into master_local_time_calibration() that extra read can
be -- and probably should be -- avoided too.)

It may be too late to get this into 3.3.0 but, if so, please
consider it asap for 3.3.1 rather than just xen-unstable/3.4.

Dan

===================================
Thanks... for the memory
I really could use more / My throughput's on the floor
The balloon is flat / My swap disk's fat / I've OOM's in store
Overcommitted so much
(with apologies to the late great Bob Hope)

[-- Attachment #2: rendezcalib.patch --]
[-- Type: application/octet-stream, Size: 5020 bytes --]

diff -r 8951c3b84e2a xen/arch/x86/time.c
--- a/xen/arch/x86/time.c	Fri Aug 01 09:54:54 2008 +0100
+++ b/xen/arch/x86/time.c	Sun Aug 03 10:34:11 2008 -0600
@@ -876,7 +876,8 @@ void do_settime(unsigned long secs, unsi
     rcu_read_unlock(&domlist_read_lock);
 }
 
-static void local_time_calibration(void *unused)
+static void local_time_calibration(s_time_t curr_master_stime,
+    s_time_t curr_local_stime, u64 curr_tsc)
 {
     struct cpu_time *t = &this_cpu(cpu_time);
 
@@ -884,11 +885,11 @@ static void local_time_calibration(void 
      * System timestamps, extrapolated from local and master oscillators,
      * taken during this calibration and the previous calibration.
      */
-    s_time_t prev_local_stime, curr_local_stime;
-    s_time_t prev_master_stime, curr_master_stime;
+    s_time_t prev_local_stime;
+    s_time_t prev_master_stime;
 
     /* TSC timestamps taken during this calibration and prev calibration. */
-    u64 prev_tsc, curr_tsc;
+    u64 prev_tsc;
 
     /*
      * System time and TSC ticks elapsed during the previous calibration
@@ -909,14 +910,6 @@ static void local_time_calibration(void 
     /* The overall calibration scale multiplier. */
     u32 calibration_mul_frac;
 
-    if ( platform_timer_is_tsc() )
-    {
-        make_tsctimer_record(); 
-        update_vcpu_system_time(current);
-        set_timer(&t->calibration_timer, NOW() + MILLISECS(10*1000));
-        return;
-    }
-
     prev_tsc          = t->local_tsc_stamp;
     prev_local_stime  = t->stime_local_stamp;
     prev_master_stime = t->stime_master_stamp;
@@ -925,12 +918,6 @@ static void local_time_calibration(void 
      * Disable IRQs to get 'instantaneous' current timestamps. We read platform
      * time first, as we may be delayed when acquiring platform_timer_lock.
      */
-    local_irq_disable();
-    curr_master_stime = read_platform_stime();
-    curr_local_stime  = get_s_time();
-    rdtscll(curr_tsc);
-    local_irq_enable();
-
 #if 0
     printk("PRE%d: tsc=%"PRIu64" stime=%"PRIu64" master=%"PRIu64"\n",
            smp_processor_id(), prev_tsc, prev_local_stime, prev_master_stime);
@@ -952,7 +939,7 @@ static void local_time_calibration(void 
      * We could be smarter here: resync platform timer with local timer?
      */
     if ( ((s64)stime_elapsed64 < (EPOCH / 2)) )
-        goto out;
+        return;
 
     /*
      * Calculate error-correction factor. This only slows down a fast local
@@ -1020,12 +1007,71 @@ static void local_time_calibration(void 
     local_irq_enable();
 
     update_vcpu_system_time(current);
+}
 
- out:
+static cpumask_t local_time_calibrate_cpumask = CPU_MASK_NONE;
+s_time_t curr_master_stime;
+
+static void slave_local_time_calibration(void *unused)
+{
+    unsigned int cpu = smp_processor_id();
+    u64 curr_tsc;
+    s_time_t curr_local_stime;
+
+    if ( platform_timer_is_tsc() )
+    {
+        make_tsctimer_record(); 
+        update_vcpu_system_time(current);
+        return;
+    }
+
+    local_irq_disable();
+    while ( !cpu_isset(cpu, local_time_calibrate_cpumask) )
+        cpu_relax();
+    curr_local_stime  = get_s_time();
+    rdtscll(curr_tsc);
+    cpu_clear(cpu, local_time_calibrate_cpumask);
+    local_irq_enable();
+
+    local_time_calibration(curr_master_stime, curr_local_stime, curr_tsc);
+}
+
+static void master_local_time_calibration(void *unused)
+{
+    unsigned int cpu = smp_processor_id();
+    static DEFINE_SPINLOCK(lock);
+    u64 curr_tsc;
+    s_time_t curr_local_stime;
+    struct cpu_time *t = &this_cpu(cpu_time);
+
+    if ( platform_timer_is_tsc() )
+    {
+        smp_call_function(slave_local_time_calibration, NULL, 0, 0);
+        make_tsctimer_record(); 
+        update_vcpu_system_time(current);
+        set_timer(&t->calibration_timer, NOW() + MILLISECS(10*1000));
+        return;
+    }
+
+    spin_lock(&lock);
+
+    smp_call_function(slave_local_time_calibration, NULL, 0, 0);
+
+    local_irq_disable();
+    curr_master_stime = read_platform_stime();
+    local_time_calibrate_cpumask = cpu_online_map;
+    curr_local_stime  = get_s_time();
+    rdtscll(curr_tsc);
+    cpu_clear(cpu, local_time_calibrate_cpumask);
+    local_irq_enable();
+
+    local_time_calibration(curr_master_stime, curr_local_stime, curr_tsc);
+
+    spin_unlock(&lock);
+
     set_timer(&t->calibration_timer, NEXT_EPOCH(curr_local_stime));
 
-    if ( smp_processor_id() == 0 )
-        platform_time_calibration();
+    platform_time_calibration();
 }
 
 void init_percpu_time(void)
@@ -1049,9 +1095,12 @@ void init_percpu_time(void)
     t->stime_local_stamp  = now;
 
  out:
-    init_timer(&t->calibration_timer, local_time_calibration,
+    if ( smp_processor_id() == 0 )
+    {
+        init_timer(&t->calibration_timer, master_local_time_calibration,
                NULL, smp_processor_id());
-    set_timer(&t->calibration_timer, NEXT_EPOCH(NOW()));
+        set_timer(&t->calibration_timer, NEXT_EPOCH(NOW()));
+    }
 }
 
 /* Late init function (after all CPUs are booted). */

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2008-08-11 18:41 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-03 16:50 [PATCH] rendezvous-based local time calibration WOW! Dan Magenheimer
2008-08-03 17:24 ` Keir Fraser
2008-08-04 15:24   ` Dan Magenheimer
2008-08-04 15:36     ` Keir Fraser
2008-08-04 17:10     ` Keir Fraser
2008-08-04 17:37       ` Dan Magenheimer
2008-08-04 19:40         ` Dan Magenheimer
2008-08-04 19:47           ` Keir Fraser
2008-08-05 18:56           ` John Levon
2008-08-05 20:49             ` Dan Magenheimer
2008-08-05 21:12               ` John Levon
2008-08-05 21:27                 ` Dan Magenheimer
2008-08-05 21:43                   ` Keir Fraser
2008-08-06 13:25                 ` Dan Magenheimer
2008-08-06 13:38                   ` John Levon
2008-08-06 15:09                     ` Dan Magenheimer
2008-08-06 15:21                       ` John Levon
2008-08-06 15:34                         ` Dan Magenheimer
2008-08-09 14:47                         ` Nils Nieuwejaar
2008-08-09 20:55                           ` Dan Magenheimer
2008-08-11 14:37                             ` John Levon
2008-08-11 14:38                               ` Keir Fraser
2008-08-11 14:43                                 ` John Levon
2008-08-11 14:46                                   ` Keir Fraser
2008-08-11 14:49                                     ` John Levon
2008-08-11 14:50                                       ` Keir Fraser
2008-08-11 18:41                                         ` John Levon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.