kthread_exit(9) unexpectedness

Lawrence Stewart lstewart at freebsd.org
Wed Nov 19 05:51:32 PST 2008


Hi all,

I tracked down a deadlock in some of my code today to some weird 
behaviour in the kthread(9) KPI. The executive summary is that 
kthread_exit() thread termination notification using wakeup() behaves as 
expected intuitively in 8.x, but not in 7.x.

 From sys/kern/kern_kthread.c

----------------------begin 8.x kthread_exit()--------------------------
void
kthread_exit(void)
{
         struct proc *p;

         /* A module may be waiting for us to exit. */
         wakeup(curthread);

         /*
          * We could rely on thread_exit to call exit1() but
          * there is extra work that needs to be done
          */
         if (curthread->td_proc->p_numthreads == 1)
                 kproc_exit(0);  /* never returns */

         p = curthread->td_proc;
         PROC_LOCK(p);
         PROC_SLOCK(p);
         thread_exit();
}
----------------------end 8.x kthread_exit()----------------------------

---------------------begin 7.x kthread_exit()---------------------------
void
kthread_exit(int ecode)
{
         struct thread *td;
         struct proc *p;

         td = curthread;
         p = td->td_proc;

         /*
          * Reparent curthread from proc0 to init so that the zombie
          * is harvested.
          */
         sx_xlock(&proctree_lock);
         PROC_LOCK(p);
         proc_reparent(p, initproc);
         PROC_UNLOCK(p);
         sx_xunlock(&proctree_lock);

         /*
          * Wakeup anyone waiting for us to exit.
          */
         wakeup(p);

         /* Buh-bye! */
         exit1(td, W_EXITCODE(ecode, 0));
}
----------------------end 7.x kthread_exit()----------------------------

 From the 7.x kthread(9) manpage:

"While exiting, the function exit1(9) will initiate a call to wakeup(9) 
on the thread handle."

The 8.x kthread manpage has no mention of the wakeup behaviour whatsoever.

So from the code above, we can see that the 7.x kthread_exit() calls 
wakeup() on the *proc instead of the *thread. In 8.x, kthread_exit() 
calls wakeup() on the *thread and the newly added kproc_exit() function 
will wakeup() anyone waiting on the *proc.

Looking at: 
http://svn.freebsd.org/viewvc/base/head/sys/kern/kern_kthread.c?view=log
the confusion seems to have crept in around r173004 during the KPI 
refactoring to support true kernel threads.

Historically it seems that kthread_exit() called wakeup on the *proc 
(which to my mind seems counter intuitive, but whatever). Then in 
r173052 we switch to the 8.x style of calling wakeup on the *thread, 
which matches the function naming convention and 7.x man page comment.

At a minimum we need a better discussion of the differences in the man 
page, but the behaviour change seems unnecessarily intrusive to me and 
has nasty side effects i.e. deadlock. Keeping consistent wakeup 
behaviour between 7.x and 8.x would I suspect be desirable and avoid 
this issue biting others.

Thoughts?

Cheers,
Lawrence


More information about the freebsd-arch mailing list