[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Fix xtime_lock handling to avoid deadlock in sched_clock().



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID b63577ff53a3161ac73b55e0aa87803e76c8bde5
# Parent  5a33233a608e9d790228d03a23f3407988f1577f
Fix xtime_lock handling to avoid deadlock in sched_clock().
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 5a33233a608e -r b63577ff53a3 
linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Fri Aug  5 09:53:04 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Fri Aug  5 14:57:43 2005
@@ -233,6 +233,10 @@
        time_t wtm_sec, xtime_sec;
        u64 tmp, usec;
 
+       if ((shadow_tv.tv_sec == s->wc_sec) &&
+           (shadow_tv.tv_usec == s->wc_usec))
+               return;
+
        shadow_tv.tv_sec  = s->wc_sec;
        shadow_tv.tv_usec = s->wc_usec;
 
@@ -263,9 +267,9 @@
 
 /*
  * Reads a consistent set of time-base values from Xen, into a shadow data
- * area. Must be called with the xtime_lock held for writing.
- */
-static void __get_time_values_from_xen(void)
+ * area.
+ */
+static void get_time_values_from_xen(void)
 {
        shared_info_t           *s = HYPERVISOR_shared_info;
        struct vcpu_time_info   *src;
@@ -286,10 +290,6 @@
        while (dst->version != src->time_version1);
 
        dst->tsc_to_usec_mul = dst->tsc_to_nsec_mul / 1000;
-
-       if ((shadow_tv.tv_sec != s->wc_sec) ||
-           (shadow_tv.tv_usec != s->wc_usec))
-               update_wallclock();
 }
 
 static inline int time_values_up_to_date(int cpu)
@@ -341,10 +341,10 @@
        unsigned long seq;
        unsigned long usec, sec;
        unsigned long max_ntp_tick;
-       unsigned long flags;
        s64 nsec;
        unsigned int cpu;
        struct shadow_time_info *shadow;
+       u32 local_time_version;
 
        cpu = get_cpu();
        shadow = &per_cpu(shadow_time, cpu);
@@ -352,6 +352,7 @@
        do {
                unsigned long lost;
 
+               local_time_version = shadow->version;
                seq = read_seqbegin(&xtime_lock);
 
                usec = get_usec_offset(shadow);
@@ -387,12 +388,11 @@
                         * overflowed). Detect that and recalculate
                         * with fresh values.
                         */
-                       write_seqlock_irqsave(&xtime_lock, flags);
-                       __get_time_values_from_xen();
-                       write_sequnlock_irqrestore(&xtime_lock, flags);
+                       get_time_values_from_xen();
                        continue;
                }
-       } while (read_seqretry(&xtime_lock, seq));
+       } while (read_seqretry(&xtime_lock, seq) ||
+                (local_time_version != shadow->version));
 
        put_cpu();
 
@@ -435,7 +435,7 @@
  again:
        nsec = (s64)tv->tv_nsec - (s64)get_nsec_offset(shadow);
        if (unlikely(!time_values_up_to_date(cpu))) {
-               __get_time_values_from_xen();
+               get_time_values_from_xen();
                goto again;
        }
 
@@ -517,21 +517,21 @@
 {
        int cpu = get_cpu();
        struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
-       s64 off;
-       unsigned long flags;
-       
-       for ( ; ; ) {
-               off = get_nsec_offset(shadow);
-               if (time_values_up_to_date(cpu))
-                       break;
-               write_seqlock_irqsave(&xtime_lock, flags);
-               __get_time_values_from_xen();
-               write_sequnlock_irqrestore(&xtime_lock, flags);
-       }
+       u64 time;
+       u32 local_time_version;
+
+       do {
+               local_time_version = shadow->version;
+               smp_rmb();
+               time = shadow->system_timestamp + get_nsec_offset(shadow);
+               if (!time_values_up_to_date(cpu))
+                       get_time_values_from_xen();
+               smp_rmb();
+       } while (local_time_version != shadow->version);
 
        put_cpu();
 
-       return shadow->system_timestamp + off;
+       return time;
 }
 EXPORT_SYMBOL(monotonic_clock);
 
@@ -565,7 +565,7 @@
        struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
 
        do {
-               __get_time_values_from_xen();
+               get_time_values_from_xen();
 
                delta = delta_cpu = 
                        shadow->system_timestamp + get_nsec_offset(shadow);
@@ -602,6 +602,8 @@
                update_process_times(user_mode(regs));
                profile_tick(CPU_PROFILING, regs);
        }
+
+       update_wallclock();
 }
 
 /*
@@ -788,7 +790,8 @@
                return;
        }
 #endif
-       __get_time_values_from_xen();
+       get_time_values_from_xen();
+       update_wallclock();
        xtime.tv_sec = shadow_tv.tv_sec;
        xtime.tv_nsec = shadow_tv.tv_usec * NSEC_PER_USEC;
        set_normalized_timespec(&wall_to_monotonic,
@@ -872,7 +875,8 @@
        init_cpu_khz();
 
        /* Get timebases for new environment. */ 
-       __get_time_values_from_xen();
+       get_time_values_from_xen();
+       update_wallclock();
 
        /* Reset our own concept of passage of system time. */
        processed_system_time =

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.