]> xenbits.xensource.com Git - xen.git/commitdiff
sched: avoid races on time values read from NOW()
authorDario Faggioli <dario.faggioli@citrix.com>
Fri, 27 May 2016 12:50:19 +0000 (14:50 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 27 May 2016 12:50:19 +0000 (14:50 +0200)
or (even in cases where there is no race, e.g., outside
of Credit2) avoid using a time sample which may be rather
old, and hence stale.

In fact, we should only sample NOW() from _inside_
the critical region within which the value we read is
used. If we don't, in case we have to spin for a while
before entering the region, when actually using it:

 1) we will use something that, at the veryy least, is
    not really "now", because of the spinning,

 2) if someone else sampled NOW() during a critical
    region protected by the lock we are spinning on,
    and if we compare the two samples when we get
    inside our region, our one will be 'earlier',
    even if we actually arrived later, which is a
    race.

In Credit2, we see an instance of 2), in runq_tickle(),
when it is called by csched2_context_saved() as it samples
NOW() before acquiring the runq lock. This makes things
look like the time went backwards, and it confuses the
algorithm (there's even a d2printk() about it, which would
trigger all the time, if enabled).

In RTDS, something similar happens in repl_timer_handler(),
and there's another instance in schedule() (in generic code),
so fix these cases too.

While there, improve csched2_vcpu_wake() and and rt_vcpu_wake()
a little as well (removing a pointless initialization, and
moving the sampling a bit closer to its use). These two hunks
entail no further functional changes.

Signed-off-by: Dario Faggioli <dario.faggioli@citrix.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
Reviewed-by: Meng Xu <mengxu@cis.upenn.edu>
RTDS: fix another instance of the 'read NOW()' race

which was overlooked in 779511f4bf5ae ("sched: avoid
races on time values read from NOW()").

Reported-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Dario Faggioli <dario.faggioli@citrix.com>
Reviewed-by: Meng Xu <mengxu@cis.upenn.edu>
master commit: 779511f4bf5ae34820a85e4eb20d50c60f69e977
master date: 2016-05-23 14:39:51 +0200
master commit: 4074e4ebe9115ac4986f963a13feada3e0560460
master date: 2016-05-25 14:33:57 +0200

xen/common/sched_credit2.c
xen/common/sched_rt.c
xen/common/schedule.c

index 1ca521bd941fd5a1ddf32d30ab5a0e9cc02a4edd..db9e1c4a104dde90102ca62238b12fa36c04aa8b 100644 (file)
@@ -948,7 +948,7 @@ static void
 csched2_vcpu_wake(const struct scheduler *ops, struct vcpu *vc)
 {
     struct csched2_vcpu * const svc = CSCHED2_VCPU(vc);
-    s_time_t now = 0;
+    s_time_t now;
 
     /* Schedule lock should be held at this point. */
 
@@ -1001,8 +1001,8 @@ static void
 csched2_context_saved(const struct scheduler *ops, struct vcpu *vc)
 {
     struct csched2_vcpu * const svc = CSCHED2_VCPU(vc);
-    s_time_t now = NOW();
     spinlock_t *lock = vcpu_schedule_lock_irq(vc);
+    s_time_t now = NOW();
 
     BUG_ON( !is_idle_vcpu(vc) && svc->rqd != RQD(ops, vc->processor));
 
index 062178088bb819844e74e20f4e1cab7dcf2983b2..a77e80800a8cc0856b02ade52499590a3aa2a0c9 100644 (file)
@@ -547,7 +547,7 @@ static void
 rt_vcpu_insert(const struct scheduler *ops, struct vcpu *vc)
 {
     struct rt_vcpu *svc = rt_vcpu(vc);
-    s_time_t now = NOW();
+    s_time_t now;
     spinlock_t *lock;
 
     /* not addlocate idle vcpu to dom vcpu list */
@@ -555,6 +555,8 @@ rt_vcpu_insert(const struct scheduler *ops, struct vcpu *vc)
         return;
 
     lock = vcpu_schedule_lock_irq(vc);
+
+    now = NOW();
     if ( now >= svc->cur_deadline )
         rt_update_deadline(now, svc);
 
@@ -959,7 +961,7 @@ static void
 rt_vcpu_wake(const struct scheduler *ops, struct vcpu *vc)
 {
     struct rt_vcpu * const svc = rt_vcpu(vc);
-    s_time_t now = NOW();
+    s_time_t now;
     struct rt_private *prv = rt_priv(ops);
     struct rt_vcpu *snext = NULL; /* highest priority on RunQ */
     struct rt_dom *sdom = NULL;
@@ -984,6 +986,7 @@ rt_vcpu_wake(const struct scheduler *ops, struct vcpu *vc)
         return;
     }
 
+    now = NOW();
     if ( now >= svc->cur_deadline)
         rt_update_deadline(now, svc);
 
index 64a619f7ce6a1ba15d87d795d67d2e41b7d40f78..3e30047a4a72ff14956169d8aea820125b568569 100644 (file)
@@ -1162,7 +1162,7 @@ static void vcpu_periodic_timer_work(struct vcpu *v)
 static void schedule(void)
 {
     struct vcpu          *prev = current, *next = NULL;
-    s_time_t              now = NOW();
+    s_time_t              now;
     struct scheduler     *sched;
     unsigned long        *tasklet_work = &this_cpu(tasklet_work_to_do);
     bool_t                tasklet_work_scheduled = 0;
@@ -1196,6 +1196,8 @@ static void schedule(void)
 
     lock = pcpu_schedule_lock_irq(cpu);
 
+    now = NOW();
+
     stop_timer(&sd->s_timer);
     
     /* get policy-specific decision on scheduling... */