> From: Dave Voutila <[email protected]>
> Date: Mon, 29 Nov 2021 07:18:23 -0500
>
> Mark Kettenis <[email protected]> writes:
>
> >> From: Dave Voutila <[email protected]>
> >> Date: Sun, 28 Nov 2021 22:51:59 -0500
> >>
> >> The last vmm diff I'll be sending tonight...promise! This swaps out
> >> usage of printf(9) outside the autoconf(4) functions.
> >>
> >> The reason for this change is printf(9) could acquire a sleepable
> >> lock.
> >
> > Huh?
> >
> > /*
> > * printf: print a message to the console and the log
> > */
> > int
> > printf(const char *fmt, ...)
> > {
> > va_list ap;
> > int retval;
> >
> > va_start(ap, fmt);
> > mtx_enter(&kprintf_mutex);
> > retval = kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap);
>
> The thread I'm pulling on here is longer than kprintf.
Well, my point is that it doesn't matter how long the thread is. The
kernel is not supposed to sleep while holding a mutex. And
assertwaitok() enforces this. If that kprintf() ends up sleeping we
have a serious bug as we call printf(9) from things like interrupt
context.
> Calling kprintf with TOCONS results in calls to kputchar, which can call
> tputchar as a result as it can add the TOTTY flag:
>
>
> 305 void
> 306 kputchar(int c, int flags, struct tty *tp)
> 307 {
> 308 extern int msgbufmapped;
>
> 309 if (panicstr)
> 310 constty = NULL;
>
> 311 if ((flags & TOCONS) && tp == NULL && constty != NULL
> && !db_active) {
> 312 tp = constty;
> 313 flags |= TOTTY;
> 314 }
> 315 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
> 316 (flags & TOCONS) && tp == constty)
> 317 constty = NULL;
> 318 if ((flags & TOLOG) &&
> 319 c != '\0' && c != '\r' && c != 0177 && msgbufmapped)
> 320 msgbuf_putchar(msgbufp, c);
> 321 if ((flags & TOCONS) && (constty == NULL || db_active)
> && c != '\0')
> 322 (*v_putc)(c);
> 323 #ifdef DDB
> 324 if (flags & TODDB)
> 325 db_putchar(c);
> 326 #endif
> 327 }
>
>
> tputchar() can end up calling ttstart(), which on my system results in
> calling ptsstart(). Which results in a call to ptsstart(). Then
> selwakeup() which attempts to grab KERNEL_LOCK.
But that's fine; KERNEL_LOCK does not sleep, it spins.
> > mtx_leave(&kprintf_mutex);
> > va_end(ap);
> > if (!panicstr)
> > logwakeup();
> >
> > return(retval);
> > }
> >
> > The guts of the the code runs while holding a mutex, which means it
> > can't sleep. And logwakeup() doesn't sleep either.
>
> witness(4) begs to differ here. /shrug
In what way?