diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index 036f29fa41d3..bdeb7c4e5f06 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -126,6 +126,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 *); @@ -176,16 +178,25 @@ 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)); + + if (!callout_halt(&ktd->ktd_wakch, &ktrace_lock)) { + KASSERT(ktd->ktd_callout_pending); + ktd->ktd_callout_pending = false; + 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); } @@ -391,11 +402,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: @@ -1070,6 +1086,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; @@ -1493,6 +1510,7 @@ ktrace_thread(void *arg) } callout_halt(&ktd->ktd_wakch, &ktrace_lock); + KASSERT(!ktd->ktd_callout_pending); callout_destroy(&ktd->ktd_wakch); mutex_exit(&ktrace_lock); @@ -1504,6 +1522,7 @@ ktrace_thread(void *arg) */ closef(fp); + KASSERT(!ktd->ktd_callout_pending); cv_destroy(&ktd->ktd_sync_cv); cv_destroy(&ktd->ktd_cv);