summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_smp.c
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2012-11-15 00:51:57 +0000
committerjeff <jeff@FreeBSD.org>2012-11-15 00:51:57 +0000
commitf40f3c3255364f472ec06d9ba5ad0b66f16a6572 (patch)
treedc9bfdaab60c5892bec647736baab766ea8ee213 /sys/kern/subr_smp.c
parente8ae50d444598a029ceb39f734aeda3b5ee77521 (diff)
downloadFreeBSD-src-f40f3c3255364f472ec06d9ba5ad0b66f16a6572.zip
FreeBSD-src-f40f3c3255364f472ec06d9ba5ad0b66f16a6572.tar.gz
- Implement run-time expansion of the KTR buffer via sysctl.
- Implement a function to ensure that all preempted threads have switched back out at least once. Use this to make sure there are no stale references to the old ktr_buf or the lock profiling buffers before updating them. Reviewed by: marius (sparc64 parts), attilio (earlier patch) Sponsored by: EMC / Isilon Storage Division
Diffstat (limited to 'sys/kern/subr_smp.c')
-rw-r--r--sys/kern/subr_smp.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c
index 4c73b61..3b27dce 100644
--- a/sys/kern/subr_smp.c
+++ b/sys/kern/subr_smp.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/pcpu.h>
+#include <sys/sched.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
@@ -734,3 +735,52 @@ smp_no_rendevous_barrier(void *dummy)
KASSERT((!smp_started),("smp_no_rendevous called and smp is started"));
#endif
}
+
+/*
+ * Wait specified idle threads to switch once. This ensures that even
+ * preempted threads have cycled through the switch function once,
+ * exiting their codepaths. This allows us to change global pointers
+ * with no other synchronization.
+ */
+int
+quiesce_cpus(cpuset_t map, const char *wmesg, int prio)
+{
+ struct pcpu *pcpu;
+ u_int gen[MAXCPU];
+ int error;
+ int cpu;
+
+ error = 0;
+ for (cpu = 0; cpu <= mp_maxid; cpu++) {
+ if (!CPU_ISSET(cpu, &map) || CPU_ABSENT(cpu))
+ continue;
+ pcpu = pcpu_find(cpu);
+ gen[cpu] = pcpu->pc_idlethread->td_generation;
+ }
+ for (cpu = 0; cpu <= mp_maxid; cpu++) {
+ if (!CPU_ISSET(cpu, &map) || CPU_ABSENT(cpu))
+ continue;
+ pcpu = pcpu_find(cpu);
+ thread_lock(curthread);
+ sched_bind(curthread, cpu);
+ thread_unlock(curthread);
+ while (gen[cpu] == pcpu->pc_idlethread->td_generation) {
+ error = tsleep(quiesce_cpus, prio, wmesg, 1);
+ if (error)
+ goto out;
+ }
+ }
+out:
+ thread_lock(curthread);
+ sched_unbind(curthread);
+ thread_unlock(curthread);
+
+ return (error);
+}
+
+int
+quiesce_all_cpus(const char *wmesg, int prio)
+{
+
+ return quiesce_cpus(all_cpus, wmesg, prio);
+}
OpenPOWER on IntegriCloud