panic: assertion: p->p_lock == 0 in kern_wait

YONETANI Tomokazu y0n3t4n1 at gmail.com
Thu May 19 04:05:21 PDT 2011


On Mon, Apr 25, 2011 at 09:13:04PM +0900, YONETANI Tomokazu wrote:
> On Sun, Apr 24, 2011 at 11:36:27AM +0900, YONETANI Tomokazu wrote:
> > >      With regards to getting rid of the timeout in the tsleep and using a
> > >      proactive wakeup(), we have to avoid calling wakeup() for 1->0
> > >      transitions unless someone is known to be waiting on p_lock.  This
> > >      can be implementing by adding a WAITING flag to the field and using
> > >      atomic_cmpset_int() to handle the (WAITING | 1) -> (0) transition and
> > >      then calling wakeup() if WAITING was set.
> > > 
> > >      I will augment the sys/refcount.h API and add refcount_wait() and
> > >      refcount_release_wakeup() which encapsulate the appropriate atomic
> > >      ops.  I will leave it up to you if you want to then use the new API
> > >      functions for PHOLD/PRELE, which would give the tsleep case a
> > >      proactive wakeup() instead of having to wait for it to timeout.
> > 
> > So what I need to do is to change PHOLD/PRELE to use refcount_acquire/
> > refcount_release_wakeup and replace p->p_lock loop with
> > refcount_release_wakeup?  I'll give it a try.
>  
> I've been running the kernel with patch(es) attached to this message
> and so far it's running fine under load.  It reduced the number of
> non-zero p->p_lock just before calling proc_remove_zombie() even without
> holding proc_token around the first wait loop.

I added a small code to PHOLD/PRELE to leave the last p->p_lock holder in
p->p_pad0 (well, far from perfect but better than nothing) and found that
it's always sysctl_kern_proc() who calls PHOLD() at a bad timing.
I guessed that's probably because it walks through zombproc and PHOLD()'s
on the processes, some of which are just about to be reaped.  So I added
the following code to skip such processes; the relavant part in kern_wait()
waits for processes whose p->p_nthreads > 0, so I thought it should be fine,
no?
I think I need to wait for a few more days before pbulk can spot other
possible bad callers of PHOLD().


Best Regards,
YONETANI Tomokazu.


diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 6d760e2..942ce6b 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -945,6 +945,11 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
 
 			if (!PRISON_CHECK(cr1, p->p_ucred))
 				continue;
+
+			/* don't touch processes about to be reaped */
+			if (p->p_nthreads == 0)
+				continue;
+
 			PHOLD(p);
 			error = sysctl_out_proc(p, req, flags);
 			PRELE(p);





More information about the Bugs mailing list