Index: sparc/cpu.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/cpu.c,v retrieving revision 1.225 diff -p -r1.225 cpu.c *** sparc/cpu.c 22 Jan 2011 12:13:25 -0000 1.225 --- sparc/cpu.c 26 Jan 2011 10:38:34 -0000 *************** cpu_init_evcnt(struct cpu_info *cpi) *** 301,314 **** { /* ! * Setup the per-cpu savefpstate counters. The "savefp null" ! * counter should go away when the NULL struct fpstate * bug ! * is fixed. */ evcnt_attach_dynamic(&cpi->ci_savefpstate, EVCNT_TYPE_MISC, NULL, cpu_name(cpi), "savefp ipi"); evcnt_attach_dynamic(&cpi->ci_savefpstate_null, EVCNT_TYPE_MISC, NULL, cpu_name(cpi), "savefp null ipi"); } /* --- 301,319 ---- { /* ! * Setup the per-cpu counters. ! * ! * The "savefp null" counter should go away when the NULL ! * struct fpstate * bug is fixed. */ evcnt_attach_dynamic(&cpi->ci_savefpstate, EVCNT_TYPE_MISC, NULL, cpu_name(cpi), "savefp ipi"); evcnt_attach_dynamic(&cpi->ci_savefpstate_null, EVCNT_TYPE_MISC, NULL, cpu_name(cpi), "savefp null ipi"); + evcnt_attach_dynamic(&cpi->ci_xpmsg_mutex_fail, EVCNT_TYPE_MISC, + NULL, cpu_name(cpi), "IPI mutex_trylock fail"); + evcnt_attach_dynamic(&cpi->ci_xpmsg_mutex_fail_call, EVCNT_TYPE_MISC, + NULL, cpu_name(cpi), "IPI mutex_trylock fail with call"); } /* *************** xcall(xcall_func_t func, xcall_trap_t tr *** 592,598 **** --- 597,633 ---- cpuset &= cpu_ready_mask; /* prevent interrupts that grab the kernel lock */ + #if 0 mutex_spin_enter(&xpmsg_mutex); + #else + /* + * There's a deadlock potential between multiple CPUs trying + * to xcall() at the same time, and the thread that loses the + * race to get xpmsg_lock is at an IPL above the incoming IPI + * IPL level, so it sits around waiting to take the lock while + * the other CPU is waiting for this CPU to handle the IPI and + * mark it as completed. + * + * If we fail to get the mutex, and we're at high enough IPL, + * call xcallintr() if there is a valid msg.tag. + */ + { + u_int pil = (getpsr() & PSR_PIL) >> 8; + + if (cold || pil < 13) + mutex_spin_enter(&xpmsg_mutex); + else { + while (mutex_tryenter(&xpmsg_mutex) == 0) { + void xcallintr(void *); + cpuinfo.ci_xpmsg_mutex_fail.ev_count++; + if (cpuinfo.msg.tag) { + cpuinfo.ci_xpmsg_mutex_fail_call.ev_count++; + xcallintr(NULL); + } + } + } + } + #endif /* * Firstly, call each CPU. We do this so that they might have Index: sparc/cpuvar.h =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/cpuvar.h,v retrieving revision 1.84 diff -p -r1.84 cpuvar.h *** sparc/cpuvar.h 13 Jan 2011 05:20:27 -0000 1.84 --- sparc/cpuvar.h 26 Jan 2011 10:38:34 -0000 *************** struct cpu_info { *** 340,345 **** --- 340,347 ---- struct evcnt ci_lev14; struct evcnt ci_savefpstate; struct evcnt ci_savefpstate_null; + struct evcnt ci_xpmsg_mutex_fail; + struct evcnt ci_xpmsg_mutex_fail_call; }; /* Index: sparc/intr.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/intr.c,v retrieving revision 1.109 diff -p -r1.109 intr.c *** sparc/intr.c 22 Jan 2011 10:37:22 -0000 1.109 --- sparc/intr.c 26 Jan 2011 10:38:34 -0000 *************** nmi_soft(struct trapframe *tf) *** 378,384 **** /* * Respond to an xcall() request from another CPU. */ ! static void xcallintr(void *v) { --- 378,385 ---- /* * Respond to an xcall() request from another CPU. */ ! void xcallintr(void *); ! /*static*/ void xcallintr(void *v) {