diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index 5ad5272af7d8..da559a580de1 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -125,6 +125,8 @@ struct ktr_desc { callout_t ktd_wakch; /* delayed wakeup */ kcondvar_t ktd_sync_cv; kcondvar_t ktd_cv; + + bool ktd_callout_pending; }; static void ktrwrite(struct ktr_desc *, struct ktrace_entry *); @@ -175,16 +177,24 @@ static void ktd_wakeup(struct ktr_desc *ktd) { - callout_stop(&ktd->ktd_wakch); - cv_signal(&ktd->ktd_cv); + KASSERT(mutex_owned(&ktrace_lock)); + KASSERT(ktd->ktd_callout_pending || !callout_pending(&ktd->ktd_wakch)); + + ktd->ktd_callout_pending = false; + if (!callout_halt(&ktd->ktd_wakch, &ktrace_lock)) { + cv_signal(&ktd->ktd_cv); + } } static void ktd_callout(void *arg) { + struct ktr_desc *ktd = arg; mutex_enter(&ktrace_lock); - ktd_wakeup(arg); + KASSERT(ktd->ktd_callout_pending); + ktd->ktd_callout_pending = false; + cv_signal(&ktd->ktd_cv); mutex_exit(&ktrace_lock); } @@ -390,11 +400,16 @@ ktraddentry(lwp_t *l, struct ktrace_entry *kte, int flags) /* Schedule delayed wakeup */ if (ktd->ktd_qcount > ktd->ktd_delayqcnt) ktd_wakeup(ktd); /* Wakeup now */ - else if (!callout_pending(&ktd->ktd_wakch)) + else if (!callout_pending(&ktd->ktd_wakch)) { + KASSERT(!ktd->ktd_callout_pending); + ktd->ktd_callout_pending = true; callout_reset(&ktd->ktd_wakch, ktd->ktd_flags & KTDF_INTERACTIVE ? ktd->ktd_intrwakdl : ktd->ktd_wakedelay, ktd_callout, ktd); + } else { + KASSERT(callout_pending(&ktd->ktd_wakch)); + } } skip_sync: @@ -1025,6 +1040,7 @@ ktrace_common(lwp_t *curl, int ops, int facs, int pid, file_t **fpp) nktd = kmem_alloc(sizeof(*nktd), KM_SLEEP); TAILQ_INIT(&nktd->ktd_queue); callout_init(&nktd->ktd_wakch, CALLOUT_MPSAFE); + nktd->ktd_callout_pending = false; cv_init(&nktd->ktd_cv, "ktrwait"); cv_init(&nktd->ktd_sync_cv, "ktrsync"); nktd->ktd_flags = 0; @@ -1409,7 +1425,10 @@ ktrace_thread(void *arg) /* nothing, collision in KTROP_SET */ } - callout_halt(&ktd->ktd_wakch, &ktrace_lock); + KASSERT(!cv_has_waiters(&ktd->ktd_cv)); + if (!callout_halt(&ktd->ktd_wakch, &ktrace_lock)) + ktd->ktd_callout_pending = false; + KASSERT(!ktd->ktd_callout_pending); callout_destroy(&ktd->ktd_wakch); mutex_exit(&ktrace_lock); @@ -1421,6 +1440,7 @@ ktrace_thread(void *arg) */ closef(fp); + KASSERT(!ktd->ktd_callout_pending); cv_destroy(&ktd->ktd_sync_cv); cv_destroy(&ktd->ktd_cv);