aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/platform_hypercall.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-03-22 10:29:13 +0000
committerKeir Fraser <keir.fraser@citrix.com>2010-03-22 10:29:13 +0000
commit21980127e69600d3cbf6a0289989e29317b04c94 (patch)
tree08b89728e504f2e7b62080614945db2eab5360cc /xen/arch/x86/platform_hypercall.c
parent078632963422644ee3a52f7d0fecb4af1026c235 (diff)
downloadxen-21980127e69600d3cbf6a0289989e29317b04c94.tar.gz
xen-21980127e69600d3cbf6a0289989e29317b04c94.tar.bz2
xen-21980127e69600d3cbf6a0289989e29317b04c94.zip
Do not spin on locks that may be held by stop_machine_run() callers.
Currently stop_machine_run() will try to bring all CPUs to softirq context, with some locks held, like xenpf_lock or cpu_add_remove_lock etc. However, if another CPU is trying to get these locks, it may cause deadlock. This patch replace all such spin_lock with spin_trylock. For xenpf_lock and sysctl_lock, we try to use hypercall_continuation, so that we will not cause trouble to user space tools. For cpu_hot_remove_lock, we simply return EBUSY if failure, since it will only impact small number of user space tools. In the end, we should try to make the stop_machine_run as spinlock free. Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
Diffstat (limited to 'xen/arch/x86/platform_hypercall.c')
-rw-r--r--xen/arch/x86/platform_hypercall.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c
index 6461d4f0bc..dc2214930a 100644
--- a/xen/arch/x86/platform_hypercall.c
+++ b/xen/arch/x86/platform_hypercall.c
@@ -73,7 +73,11 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
if ( op->interface_version != XENPF_INTERFACE_VERSION )
return -EACCES;
- spin_lock(&xenpf_lock);
+ /* spin_trylock() avoids deadlock with stop_machine_run(). */
+ while ( !spin_trylock(&xenpf_lock) )
+ if ( hypercall_preempt_check() )
+ return hypercall_create_continuation(
+ __HYPERVISOR_platform_op, "h", u_xenpf_op);
switch ( op->cmd )
{
@@ -398,7 +402,12 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
g_info = &op->u.pcpu_info;
- spin_lock(&cpu_add_remove_lock);
+ /* spin_trylock() avoids deadlock with stop_machine_run(). */
+ if ( !spin_trylock(&cpu_add_remove_lock) )
+ {
+ ret = -EBUSY;
+ break;
+ }
if ( (g_info->xen_cpuid >= NR_CPUS) ||
(g_info->xen_cpuid < 0) ||