From: Christian Ludwig Subject: Re: pool: Check that we can sleep early To: Jonathan Gray Cc: Date: Thu, 31 Jul 2025 18:40:00 +0200 On Fri, Aug 01, 2025 at 12:20:33AM +1000 Jonathan Gray wrote: > On Thu, Jul 31, 2025 at 04:01:12PM +0200, Christian Ludwig wrote: > > Hi, > > > > bluhm@ has hit a bug earlier ([1]) that panics pretty late, after a > > context switch to a different thread. The resulting backtrace is rather > > useless. The problem was a missing mtx_leave() before calling > > pool_get(..., PR_WAITOK) in a completely different code path. > > > > This diff adds a check in pool_get() that we actually are in a sleepable > > context when PR_WAITOK is given. There is an equivalent check present in > > malloc() already. > > > > Tests and feedback welcome. > > Why after the pool_do_get() call? Ah, good catch! > For a long time my tree has had the following without issue > > Index: subr_pool.c > =================================================================== > RCS file: /cvs/src/sys/kern/subr_pool.c,v > diff -u -p -r1.241 subr_pool.c > --- subr_pool.c 21 Jul 2025 20:36:41 -0000 1.241 > +++ subr_pool.c 22 Jul 2025 02:52:13 -0000 > @@ -562,6 +562,9 @@ pool_get(struct pool *pp, int flags) > void *v = NULL; > int slowdown = 0; > > + if (flags & PR_WAITOK) > + assertwaitok(); > + > KASSERT(flags & (PR_WAITOK | PR_NOWAIT)); > if (pp->pr_flags & PR_RWLOCK) > KASSERT(flags & PR_WAITOK); > That is better for sure. > > > > > > - Christian > > > > [1] https://marc.info/?l=openbsd-bugs&m=175139531419854 > > > > > > diff --git a/sys/kern/subr_pool.c b/sys/kern/subr_pool.c > > index d76e8b27cd57..7fb57d569d1c 100644 > > --- a/sys/kern/subr_pool.c > > +++ b/sys/kern/subr_pool.c > > @@ -584,8 +584,13 @@ pool_get(struct pool *pp, int flags) > > } > > pl_leave(pp, &pp->pr_lock); > > > > - if ((slowdown || pool_debug == 2) && ISSET(flags, PR_WAITOK)) > > - yield(); > > + if (ISSET(flags, PR_WAITOK)) { > > +#ifdef DIAGNOSTIC > > + assertwaitok(); > > +#endif > > + if (slowdown || pool_debug == 2) > > + yield(); > > + } > > > > if (v == NULL) { > > struct pool_get_memory mem = { .v = NULL }; > >