Hi,
In schedule.c, schedule() and sched_adjust() call trace functions during
acquiring lock of schedule_lock in each cpu's schedule_data. When trace
buffers are enabled, the trace function (__trace_var()) may call
vcpu_wake() by calling send_guest_global_virq(). In the case, a deadlock
occurs when acquiring lock of schedule_lock.
Attached patch fixes this problem.
Signed-off-by: Naoki Nishiguchi <nisiguti@xxxxxxxxxxxxxx>
Regards,
Naoki Nishiguchi
diff -r 77dec8732cde xen/common/schedule.c
--- a/xen/common/schedule.c Wed Apr 23 16:58:44 2008 +0100
+++ b/xen/common/schedule.c Thu Apr 24 11:19:25 2008 +0900
@@ -605,11 +605,13 @@ long sched_adjust(struct domain *d, stru
if ( d == current->domain )
vcpu_schedule_lock_irq(current);
- if ( (ret = SCHED_OP(adjust, d, op)) == 0 )
- TRACE_1D(TRC_SCHED_ADJDOM, d->domain_id);
+ ret = SCHED_OP(adjust, d, op);
if ( d == current->domain )
vcpu_schedule_unlock_irq(current);
+
+ if ( ret == 0 )
+ TRACE_1D(TRC_SCHED_ADJDOM, d->domain_id);
for_each_vcpu ( d, v )
{
@@ -654,6 +656,7 @@ static void schedule(void)
struct schedule_data *sd;
struct task_slice next_slice;
s32 r_time; /* time for new dom to run */
+ uint64_t prev_state_time, next_state_time;
ASSERT(!in_irq());
ASSERT(this_cpu(mc_state).flags == 0);
@@ -682,14 +685,10 @@ static void schedule(void)
return continue_running(prev);
}
- TRACE_2D(TRC_SCHED_SWITCH_INFPREV,
- prev->domain->domain_id,
- now - prev->runstate.state_entry_time);
- TRACE_3D(TRC_SCHED_SWITCH_INFNEXT,
- next->domain->domain_id,
- (next->runstate.state == RUNSTATE_runnable) ?
- (now - next->runstate.state_entry_time) : 0,
- r_time);
+ /* Temporarily save the period of previous runstate. */
+ prev_state_time = now - prev->runstate.state_entry_time;
+ next_state_time = (next->runstate.state == RUNSTATE_runnable) ?
+ (now - next->runstate.state_entry_time) : 0;
ASSERT(prev->runstate.state == RUNSTATE_running);
vcpu_runstate_change(
@@ -705,6 +704,12 @@ static void schedule(void)
next->is_running = 1;
spin_unlock_irq(&sd->schedule_lock);
+
+ /* Avoid deadlock by calling the trace function after unlock. */
+ TRACE_2D(TRC_SCHED_SWITCH_INFPREV,
+ prev->domain->domain_id, prev_state_time);
+ TRACE_3D(TRC_SCHED_SWITCH_INFNEXT,
+ next->domain->domain_id, next_state_time, r_time);
perfc_incr(sched_ctx);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|