summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjb <jb@FreeBSD.org>2008-05-23 04:05:26 +0000
committerjb <jb@FreeBSD.org>2008-05-23 04:05:26 +0000
commite922b9b976815767ede31daab542ec332af39774 (patch)
tree8229e00054768ced2da8231e70691f0a466e9437 /sys
parent964def13e21f87de612c9d4ca76700f87ac7481d (diff)
downloadFreeBSD-src-e922b9b976815767ede31daab542ec332af39774.zip
FreeBSD-src-e922b9b976815767ede31daab542ec332af39774.tar.gz
Allow a rendezvous with just a specified CPU too.
Make the API work in the non-smp case too so that a kernel module can work the same regardless of whether or not it is loaded on a SMP kernel or not.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/subr_smp.c80
-rw-r--r--sys/sys/smp.h7
2 files changed, 67 insertions, 20 deletions
diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c
index 2d07756..0c53552 100644
--- a/sys/kern/subr_smp.c
+++ b/sys/kern/subr_smp.c
@@ -73,6 +73,9 @@ u_int mp_maxid;
SYSCTL_NODE(_kern, OID_AUTO, smp, CTLFLAG_RD, NULL, "Kernel SMP");
+SYSCTL_INT(_kern_smp, OID_AUTO, maxid, CTLFLAG_RD, &mp_maxid, 0,
+ "Max CPU ID.");
+
SYSCTL_INT(_kern_smp, OID_AUTO, maxcpus, CTLFLAG_RD, &mp_maxcpus, 0,
"Max number of CPUs that the system was compiled for.");
@@ -108,6 +111,7 @@ SYSCTL_INT(_kern_smp, OID_AUTO, forward_roundrobin_enabled, CTLFLAG_RW,
"Forwarding of roundrobin to all other CPUs");
/* Variables needed for SMP rendezvous. */
+static volatile cpumask_t smp_rv_cpumask;
static void (*volatile smp_rv_setup_func)(void *arg);
static void (*volatile smp_rv_action_func)(void *arg);
static void (*volatile smp_rv_teardown_func)(void *arg);
@@ -290,14 +294,6 @@ restart_cpus(cpumask_t map)
return 1;
}
-void
-smp_no_rendevous_barrier(void *dummy)
-{
-#ifdef SMP
- KASSERT((!smp_started),("smp_no_rendevous called and smp is started"));
-#endif
-}
-
/*
* All-CPU rendezvous. CPUs are signalled, all execute the setup function
* (if specified), rendezvous, execute the action function (if specified),
@@ -310,14 +306,20 @@ smp_no_rendevous_barrier(void *dummy)
void
smp_rendezvous_action(void)
{
+ cpumask_t map = smp_rv_cpumask;
+ int i, ncpus = 0;
void* local_func_arg = smp_rv_func_arg;
void (*local_setup_func)(void*) = smp_rv_setup_func;
void (*local_action_func)(void*) = smp_rv_action_func;
void (*local_teardown_func)(void*) = smp_rv_teardown_func;
+ for (i = 0; i < MAXCPU; i++)
+ if (((1 << i) & map) != 0 && pcpu_find(i) != NULL)
+ ncpus++;
+
/* Ensure we have up-to-date values. */
atomic_add_acq_int(&smp_rv_waiters[0], 1);
- while (smp_rv_waiters[0] < mp_ncpus)
+ while (smp_rv_waiters[0] < ncpus)
cpu_spinwait();
/* setup function */
@@ -327,7 +329,7 @@ smp_rendezvous_action(void)
/* spin on entry rendezvous */
atomic_add_int(&smp_rv_waiters[1], 1);
- while (smp_rv_waiters[1] < mp_ncpus)
+ while (smp_rv_waiters[1] < ncpus)
cpu_spinwait();
}
@@ -339,7 +341,7 @@ smp_rendezvous_action(void)
atomic_add_int(&smp_rv_waiters[2], 1);
if (local_teardown_func == smp_no_rendevous_barrier)
return;
- while (smp_rv_waiters[2] < mp_ncpus)
+ while (smp_rv_waiters[2] < ncpus)
cpu_spinwait();
/* teardown function */
@@ -348,11 +350,13 @@ smp_rendezvous_action(void)
}
void
-smp_rendezvous(void (* setup_func)(void *),
- void (* action_func)(void *),
- void (* teardown_func)(void *),
- void *arg)
+smp_rendezvous_cpus(cpumask_t map,
+ void (* setup_func)(void *),
+ void (* action_func)(void *),
+ void (* teardown_func)(void *),
+ void *arg)
{
+ int i, ncpus = 0;
if (!smp_started) {
if (setup_func != NULL)
@@ -363,11 +367,16 @@ smp_rendezvous(void (* setup_func)(void *),
teardown_func(arg);
return;
}
+
+ for (i = 0; i < MAXCPU; i++)
+ if (((1 << i) & map) != 0 && pcpu_find(i) != NULL)
+ ncpus++;
/* obtain rendezvous lock */
mtx_lock_spin(&smp_ipi_mtx);
/* set static function pointers */
+ smp_rv_cpumask = map;
smp_rv_setup_func = setup_func;
smp_rv_action_func = action_func;
smp_rv_teardown_func = teardown_func;
@@ -377,19 +386,29 @@ smp_rendezvous(void (* setup_func)(void *),
atomic_store_rel_int(&smp_rv_waiters[0], 0);
/* signal other processors, which will enter the IPI with interrupts off */
- ipi_all_but_self(IPI_RENDEZVOUS);
+ ipi_selected(map & ~(1 << curcpu), IPI_RENDEZVOUS);
- /* call executor function */
- smp_rendezvous_action();
+ /* Check if the current CPU is in the map */
+ if ((map & (1 << curcpu)) != 0)
+ smp_rendezvous_action();
if (teardown_func == smp_no_rendevous_barrier)
- while (atomic_load_acq_int(&smp_rv_waiters[2]) < mp_ncpus)
+ while (atomic_load_acq_int(&smp_rv_waiters[2]) < ncpus)
cpu_spinwait();
/* release lock */
mtx_unlock_spin(&smp_ipi_mtx);
}
+void
+smp_rendezvous(void (* setup_func)(void *),
+ void (* action_func)(void *),
+ void (* teardown_func)(void *),
+ void *arg)
+{
+ smp_rendezvous_cpus(all_cpus, setup_func, action_func, teardown_func, arg);
+}
+
static struct cpu_group group[MAXCPU];
struct cpu_group *
@@ -566,6 +585,21 @@ smp_topo_find(struct cpu_group *top, int cpu)
#else /* !SMP */
void
+smp_rendezvous_cpus(cpumask_t map,
+ void (*setup_func)(void *),
+ void (*action_func)(void *),
+ void (*teardown_func)(void *),
+ void *arg)
+{
+ if (setup_func != NULL)
+ setup_func(arg);
+ if (action_func != NULL)
+ action_func(arg);
+ if (teardown_func != NULL)
+ teardown_func(arg);
+}
+
+void
smp_rendezvous(void (*setup_func)(void *),
void (*action_func)(void *),
void (*teardown_func)(void *),
@@ -595,3 +629,11 @@ mp_setvariables_for_up(void *dummy)
SYSINIT(cpu_mp_setvariables, SI_SUB_TUNABLES, SI_ORDER_FIRST,
mp_setvariables_for_up, NULL);
#endif /* SMP */
+
+void
+smp_no_rendevous_barrier(void *dummy)
+{
+#ifdef SMP
+ KASSERT((!smp_started),("smp_no_rendevous called and smp is started"));
+#endif
+}
diff --git a/sys/sys/smp.h b/sys/sys/smp.h
index 1f0010a..8306d52 100644
--- a/sys/sys/smp.h
+++ b/sys/sys/smp.h
@@ -123,14 +123,19 @@ void forward_roundrobin(void);
int restart_cpus(cpumask_t);
int stop_cpus(cpumask_t);
void smp_rendezvous_action(void);
-void smp_no_rendevous_barrier(void *);
extern struct mtx smp_ipi_mtx;
#endif /* SMP */
+void smp_no_rendevous_barrier(void *);
void smp_rendezvous(void (*)(void *),
void (*)(void *),
void (*)(void *),
void *arg);
+void smp_rendezvous_cpus(cpumask_t,
+ void (*)(void *),
+ void (*)(void *),
+ void (*)(void *),
+ void *arg);
#endif /* !LOCORE */
#endif /* _KERNEL */
#endif /* _SYS_SMP_H_ */
OpenPOWER on IntegriCloud