svn commit: r225580 - stable/8/sys/kern
Andriy Gapon
avg at FreeBSD.org
Thu Sep 15 10:51:32 UTC 2011
Author: avg
Date: Thu Sep 15 10:51:31 2011
New Revision: 225580
URL: http://svn.freebsd.org/changeset/base/225580
Log:
MFC r213736: generic_stop_cpus: prevent parallel execution
Addendum to the original commit message:
This is mostly useful to protect kdb_trap() from concurrent entry as it
doesn't have any protection like e.g. panic(9) has. Even if kdb_trap()
had that protection there would still be a need for protection
between concurrect panic() and kdb_trap() entries. That protection
could be implemented externally, but doing it in generic_stop_cpus()
seems to be OK as well (stopping CPUs on panic is in the works).
Modified:
stable/8/sys/kern/subr_smp.c
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
Modified: stable/8/sys/kern/subr_smp.c
==============================================================================
--- stable/8/sys/kern/subr_smp.c Thu Sep 15 10:42:55 2011 (r225579)
+++ stable/8/sys/kern/subr_smp.c Thu Sep 15 10:51:31 2011 (r225580)
@@ -198,22 +198,32 @@ forward_signal(struct thread *td)
* 0: NA
* 1: ok
*
- * XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
- * from executing at same time.
*/
static int
generic_stop_cpus(cpumask_t map, u_int type)
{
+ static volatile u_int stopping_cpu = NOCPU;
int i;
- KASSERT(type == IPI_STOP || type == IPI_STOP_HARD,
+ KASSERT(
+#if defined(__amd64__)
+ type == IPI_STOP || type == IPI_STOP_HARD || type == IPI_SUSPEND,
+#else
+ type == IPI_STOP || type == IPI_STOP_HARD,
+#endif
("%s: invalid stop type", __func__));
if (!smp_started)
- return 0;
+ return (0);
CTR2(KTR_SMP, "stop_cpus(%x) with %u type", map, type);
+ if (stopping_cpu != PCPU_GET(cpuid))
+ while (atomic_cmpset_int(&stopping_cpu, NOCPU,
+ PCPU_GET(cpuid)) == 0)
+ while (stopping_cpu != NOCPU)
+ cpu_spinwait(); /* spin */
+
/* send the stop IPI to all CPUs in map */
ipi_selected(map, type);
@@ -230,7 +240,8 @@ generic_stop_cpus(cpumask_t map, u_int t
#endif
}
- return 1;
+ stopping_cpu = NOCPU;
+ return (1);
}
int
@@ -248,50 +259,11 @@ stop_cpus_hard(cpumask_t map)
}
#if defined(__amd64__)
-/*
- * When called the executing CPU will send an IPI to all other CPUs
- * requesting that they halt execution.
- *
- * Usually (but not necessarily) called with 'other_cpus' as its arg.
- *
- * - Signals all CPUs in map to suspend.
- * - Waits for each to suspend.
- *
- * Returns:
- * -1: error
- * 0: NA
- * 1: ok
- *
- * XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
- * from executing at same time.
- */
int
suspend_cpus(cpumask_t map)
{
- int i;
- if (!smp_started)
- return (0);
-
- CTR1(KTR_SMP, "suspend_cpus(%x)", map);
-
- /* send the suspend IPI to all CPUs in map */
- ipi_selected(map, IPI_SUSPEND);
-
- i = 0;
- while ((stopped_cpus & map) != map) {
- /* spin */
- cpu_spinwait();
- i++;
-#ifdef DIAGNOSTIC
- if (i == 100000) {
- printf("timeout suspending cpus\n");
- break;
- }
-#endif
- }
-
- return (1);
+ return (generic_stop_cpus(map, IPI_SUSPEND));
}
#endif
More information about the svn-src-stable
mailing list