summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2018-05-22 19:24:57 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2018-05-22 19:24:57 +0000
commit748b15fc02bd73c2aacc2404fb10e6bf1e424640 (patch)
treeed9d102ed2fef5d375056be82cee5f31536175fb
parentdefd918d798f39febc509d56614d3d39fa6ba275 (diff)
Notes
-rw-r--r--sys/kern/kern_switch.c69
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);
}