Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/sparc/sparc to quote a new comment:
details: https://anonhg.NetBSD.org/src/rev/4a59911ee29c
branches: trunk
changeset: 761427:4a59911ee29c
user: mrg <mrg%NetBSD.org@localhost>
date: Thu Jan 27 05:31:13 2011 +0000
description:
to quote a new comment:
* 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.
this seems to fix the xcall() failed to ping cpus problem.
idea from martin, tested by macallan and myself.
diffstat:
sys/arch/sparc/sparc/cpu.c | 43 ++++++++++++++++++++++++++++++++++++++-----
sys/arch/sparc/sparc/cpuvar.h | 6 +++++-
sys/arch/sparc/sparc/intr.c | 9 ++++++---
3 files changed, 49 insertions(+), 9 deletions(-)
diffs (142 lines):
diff -r 95f93183cd69 -r 4a59911ee29c sys/arch/sparc/sparc/cpu.c
--- a/sys/arch/sparc/sparc/cpu.c Thu Jan 27 04:54:40 2011 +0000
+++ b/sys/arch/sparc/sparc/cpu.c Thu Jan 27 05:31:13 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.225 2011/01/22 12:13:25 mrg Exp $ */
+/* $NetBSD: cpu.c,v 1.226 2011/01/27 05:31:13 mrg Exp $ */
/*
* Copyright (c) 1996
@@ -52,7 +52,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.225 2011/01/22 12:13:25 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.226 2011/01/27 05:31:13 mrg Exp $");
#include "opt_multiprocessor.h"
#include "opt_lockdebug.h"
@@ -301,14 +301,19 @@
{
/*
- * Setup the per-cpu savefpstate counters. The "savefp null"
- * counter should go away when the NULL struct fpstate * bug
- * is fixed.
+ * 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");
}
/*
@@ -581,6 +586,7 @@
struct cpu_info *cpi;
int n, i, done, callself, mybit;
volatile struct xpmsg_func *p;
+ u_int pil;
int fasttrap;
int is_noop = func == (xcall_func_t)sparc_noop;
@@ -592,7 +598,34 @@
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.
+ */
+ pil = (getpsr() & PSR_PIL) >> 8;
+
+ if (cold || pil < 13)
+ mutex_spin_enter(&xpmsg_mutex);
+ else {
+ while (mutex_tryenter(&xpmsg_mutex) == 0) {
+ 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
diff -r 95f93183cd69 -r 4a59911ee29c sys/arch/sparc/sparc/cpuvar.h
--- a/sys/arch/sparc/sparc/cpuvar.h Thu Jan 27 04:54:40 2011 +0000
+++ b/sys/arch/sparc/sparc/cpuvar.h Thu Jan 27 05:31:13 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpuvar.h,v 1.84 2011/01/13 05:20:27 mrg Exp $ */
+/* $NetBSD: cpuvar.h,v 1.85 2011/01/27 05:31:14 mrg Exp $ */
/*
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -340,6 +340,8 @@
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;
};
/*
@@ -453,6 +455,8 @@
typedef void (*xcall_func_t)(int, int, int);
typedef void (*xcall_trap_t)(int, int, int);
void xcall(xcall_func_t, xcall_trap_t, int, int, int, u_int);
+/* from intr.c */
+void xcallintr(void *);
/* Shorthand */
#define XCALL0(f,cpuset) \
xcall((xcall_func_t)f, NULL, 0, 0, 0, cpuset)
diff -r 95f93183cd69 -r 4a59911ee29c sys/arch/sparc/sparc/intr.c
--- a/sys/arch/sparc/sparc/intr.c Thu Jan 27 04:54:40 2011 +0000
+++ b/sys/arch/sparc/sparc/intr.c Thu Jan 27 05:31:13 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.c,v 1.109 2011/01/22 10:37:22 mrg Exp $ */
+/* $NetBSD: intr.c,v 1.110 2011/01/27 05:31:14 mrg Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.109 2011/01/22 10:37:22 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.110 2011/01/27 05:31:14 mrg Exp $");
#include "opt_multiprocessor.h"
#include "opt_sparc_arch.h"
@@ -377,8 +377,11 @@
#if defined(MULTIPROCESSOR)
/*
* Respond to an xcall() request from another CPU.
+ *
+ * This is also called directly from xcall() if we notice an
+ * incoming message while we're waiting to grab the xpmsg_lock.
*/
-static void
+void
xcallintr(void *v)
{
Home |
Main Index |
Thread Index |
Old Index