summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/softint.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/os/softint.c')
-rw-r--r--usr/src/uts/common/os/softint.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/usr/src/uts/common/os/softint.c b/usr/src/uts/common/os/softint.c
index 47d384e724..9728dd93cc 100644
--- a/usr/src/uts/common/os/softint.c
+++ b/usr/src/uts/common/os/softint.c
@@ -168,6 +168,7 @@ static void (*kdi_softcall_func)(void);
extern void siron_poke_cpu(cpuset_t);
extern void siron(void);
+extern void kdi_siron(void);
void
softcall_init(void)
@@ -220,8 +221,15 @@ softcall_choose_cpu()
*/
cp = cplist;
do {
+ /*
+ * Don't select this CPU if :
+ * - in cpuset already
+ * - CPU is not accepting interrupts
+ * - CPU is being offlined
+ */
if (CPU_IN_SET(*softcall_cpuset, cp->cpu_id) ||
- (cp->cpu_flags & CPU_ENABLE) == 0)
+ (cp->cpu_flags & CPU_ENABLE) == 0 ||
+ (cp == cpu_inmotion))
continue;
/* if CPU is not busy */
@@ -351,7 +359,7 @@ kdi_softcall(void (*func)(void))
kdi_softcall_func = func;
if (softhead == NULL)
- siron();
+ kdi_siron();
}
/*
@@ -374,6 +382,19 @@ softint(void)
caddr_t arg;
int cpu_id = CPU->cpu_id;
+ /*
+ * Don't process softcall queue if current CPU is quiesced or
+ * offlined. This can happen when a CPU is running pause
+ * thread but softcall already sent a xcall.
+ */
+ if (CPU->cpu_flags & (CPU_QUIESCED|CPU_OFFLINE)) {
+ if (softcall_cpuset != NULL &&
+ CPU_IN_SET(*softcall_cpuset, cpu_id)) {
+ CPUSET_DEL(*softcall_cpuset, cpu_id);
+ goto out;
+ }
+ }
+
mutex_enter(&softcall_lock);
if (softcall_state & (SOFT_STEAL|SOFT_PEND)) {