# 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
|