diff options
author | jhb <jhb@FreeBSD.org> | 2011-05-24 13:36:41 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2011-05-24 13:36:41 +0000 |
commit | 7028e129fd10d1c1da25e7ac0581af6637d89df5 (patch) | |
tree | 161c9f4346bf81e25d9e3ad8a6d2d4673c9ee8a8 /contrib/bind9/lib/dns/diff.c | |
parent | 4d0fe668f783d3ba8aff483a99e55b514bf9cba0 (diff) | |
download | FreeBSD-src-7028e129fd10d1c1da25e7ac0581af6637d89df5.zip FreeBSD-src-7028e129fd10d1c1da25e7ac0581af6637d89df5.tar.gz |
Fix an issue with critical sections and SMP rendezvous handlers.
Specifically, a critical_exit() call that drops the nesting level to zero
has a brief window where the pending preemption flag is set and the
nesting level is set to zero. This is done purposefully to avoid races
where a preemption scheduled by an interrupt could be lost otherwise (see
revision 144777). However, this does mean that if an interrupt fires
during this window and enters and exits a critical section, it may preempt
from the interrupt context. This is generally fine as the interrupt code
is careful to arrange critical sections so that they are not exited until
it is safe to preempt (e.g. interrupts EOI'd and masked if necessary).
However, the SMP rendezvous IPI handler does not quite follow this rule,
and in general a rendezvous can never be preempted. Rendezvous handlers
are also not permitted to schedule threads to execute, so they will not
typically trigger preemptions. SMP rendezvous handlers may use
spinlocks (carefully) such as the rm_cleanIPI() handler used in rmlocks,
but using a spinlock also enters and exits a critical section. If the
interrupted top-half code is in the brief window of critical_exit() where
the nesting level is zero but a preemption is pending, then releasing the
spinlock can trigger a preemption. Because we know that SMP rendezvous
handlers can never schedule a thread, we know that a critical_exit() in
an SMP rendezvous handler will only preempt in this edge case. We also
know that the top-half thread will happily handle the deferred preemption
once the SMP rendezvous has completed, so the preemption will not be lost.
This makes it safe to employ a workaround where we use a nested critical
section in the SMP rendezvous code itself around rendezvous action
routines to prevent any preemptions during an SMP rendezvous. The
workaround intentionally avoids checking for a deferred preemption
when leaving the critical section on the assumption that if there is a
pending preemption it will be handled by the interrupted top-half code.
Submitted by: mlaier (variation specific to rm_cleanIPI())
Obtained from: Isilon
MFC after: 1 week
Diffstat (limited to 'contrib/bind9/lib/dns/diff.c')
0 files changed, 0 insertions, 0 deletions