diff options
author | jeff <jeff@FreeBSD.org> | 2012-11-15 00:51:57 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2012-11-15 00:51:57 +0000 |
commit | f40f3c3255364f472ec06d9ba5ad0b66f16a6572 (patch) | |
tree | dc9bfdaab60c5892bec647736baab766ea8ee213 /sys/kern/subr_smp.c | |
parent | e8ae50d444598a029ceb39f734aeda3b5ee77521 (diff) | |
download | FreeBSD-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.c | 50 |
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); +} |