diff options
author | Mateusz Guzik <mjg@FreeBSD.org> | 2018-05-22 19:24:57 +0000 |
---|---|---|
committer | Mateusz Guzik <mjg@FreeBSD.org> | 2018-05-22 19:24:57 +0000 |
commit | 748b15fc02bd73c2aacc2404fb10e6bf1e424640 (patch) | |
tree | ed9d102ed2fef5d375056be82cee5f31536175fb | |
parent | defd918d798f39febc509d56614d3d39fa6ba275 (diff) |
Notes
-rw-r--r-- | sys/kern/kern_switch.c | 69 |
1 files changed, 35 insertions, 34 deletions
diff --git a/sys/kern/kern_switch.c b/sys/kern/kern_switch.c index ea2791673edf9..2d2805fd7445d 100644 --- a/sys/kern/kern_switch.c +++ b/sys/kern/kern_switch.c @@ -209,48 +209,49 @@ critical_enter(void) (long)td->td_proc->p_pid, td->td_name, td->td_critnest); } +static void __noinline +critical_exit_preempt(void) +{ + struct thread *td; + int flags; + + td = curthread; + KASSERT(td->td_owepreempt != 0, + ("critical_exit: td_owepreempt == 0")); + if (td->td_critnest != 0) + return; + if (kdb_active) + return; + + /* + * Microoptimization: we committed to switch, + * disable preemption in interrupt handlers + * while spinning for the thread lock. + */ + td->td_critnest = 1; + thread_lock(td); + td->td_critnest--; + flags = SW_INVOL | SW_PREEMPT; + if (TD_IS_IDLETHREAD(td)) + flags |= SWT_IDLE; + else + flags |= SWT_OWEPREEMPT; + mi_switch(flags, NULL); + thread_unlock(td); +} + void critical_exit(void) { struct thread *td; - int flags; td = curthread; KASSERT(td->td_critnest != 0, ("critical_exit: td_critnest == 0")); - - if (td->td_critnest == 1) { - td->td_critnest = 0; - - /* - * Interrupt handlers execute critical_exit() on - * leave, and td_owepreempt may be left set by an - * interrupt handler only when td_critnest > 0. If we - * are decrementing td_critnest from 1 to 0, read - * td_owepreempt after decrementing, to not miss the - * preempt. Disallow compiler to reorder operations. - */ - __compiler_membar(); - if (td->td_owepreempt && !kdb_active) { - /* - * Microoptimization: we committed to switch, - * disable preemption in interrupt handlers - * while spinning for the thread lock. - */ - td->td_critnest = 1; - thread_lock(td); - td->td_critnest--; - flags = SW_INVOL | SW_PREEMPT; - if (TD_IS_IDLETHREAD(td)) - flags |= SWT_IDLE; - else - flags |= SWT_OWEPREEMPT; - mi_switch(flags, NULL); - thread_unlock(td); - } - } else - td->td_critnest--; - + td->td_critnest--; + __compiler_membar(); + if (__predict_false(td->td_owepreempt)) + critical_exit_preempt(); CTR4(KTR_CRITICAL, "critical_exit by thread %p (%ld, %s) to %d", td, (long)td->td_proc->p_pid, td->td_name, td->td_critnest); } |