Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 2 Dec 2008 17:07:41 -0500
From:      John Baldwin <jhb@freebsd.org>
To:        Lawrence Stewart <lstewart@freebsd.org>
Cc:        freebsd-arch@freebsd.org
Subject:   Re: kthread_exit(9) unexpectedness
Message-ID:  <200812021707.41545.jhb@freebsd.org>
In-Reply-To: <4929F90B.1040502@freebsd.org>
References:  <492412E8.3060700@freebsd.org> <200811211348.41536.jhb@freebsd.org> <4929F90B.1040502@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sunday 23 November 2008 07:44:59 pm Lawrence Stewart wrote:
> John Baldwin wrote:
> > On Thursday 20 November 2008 05:22:03 pm Lawrence Stewart wrote:
> >> John Baldwin wrote:
> >>> On Wednesday 19 November 2008 08:21:44 am Lawrence Stewart wrote:
> >>>> 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.
> >>> In 5.x/6.x/7.x kthreads are still processes and it has always been a 
> > wakeup on 
> >>> the proc pointer.  kthread_create() in 7.x returns a proc pointer, not a 
> >>> thread pointer for example.  In 8.x kthreads are actual threads and 
> >> Yep, but the processes have a *thread in them right? The API naming is 
> >> obviously slightly misleading, but it essentially creates a new single 
> >> threaded process prior to 8.x.
> > 
> > Yes, but you have to go explicitly use FIRST_THREAD_IN_PROC().  Most of 
the 
> > kernel modules I've written that use kthread's in < 8 do this:
> > 
> > static struct proc *foo_thread;
> > 
> > /* Called for MOD_LOAD. */
> > static void
> > load(...)
> > {
> > 
> > 	error = kthread_create(..., &foo_thread);
> > }
> > 
> > static void
> > unload(...)
> > {
> > 
> > 	/* set flag */
> > 	msleep(foo_thread, ...);
> > }
> > 
> > And never actually use the thread at all.  However, if you write the code 
for 
> > 8.x, now you _do_ get a kthread and sleep on the thread so it becomes:
> > 
> > static struct thread *foo_thread;
> > 
> > static void
> > load(...)
> > {
> > 
> > 	error = kproc_kthread_add(..., proc0, &foo_thread);
> > }
> > 
> > static void
> > unload(...)
> > {
> > 
> > 	/* set flag */
> > 	msleep(foo_thread, ...);
> > }
> > 
> 
> 
> Sure, but to write the code in this way means you are exercising 
> undocumented knowledge of the KPI. I suspect the average developer 
> completely unfamiliar with the KPI would (and should!) use the man page 
> to learn about the functionality it provides.
> 
> With that basis in mind, it seems unreasonable to expect the developer 
> to come to the conclusion that "...will initiate a call to wakeup(9) on 
> the thread handle." refers to sleeping on the *proc passed in to 
> kthread_create. Perhaps I'm not as switched on as the average developer, 
> but when I read it I certainly did not understand that the KPI created 
> processes and that the man page used the term thread to really mean a 
> single threaded process. I also did no equate "thread handle" with the 
> *proc returned by kthread_create.

This is why the API in 8 is better, it is far less confusing.

> Apart from the discussion thus far, you haven't actually commented yet 
> on my proposed single line change to kthread_exit() in 7.x to call 
> wakeup on the *thread as well as the *proc. Do you have any specific 
> thoughts on or objection to that idea?

I would rather fix the docs first and not encourage folks to use 
FIRST_THREAD_IN_PROC (a).  My only worry about the additional wakeup is other 
places that may be sleeping on the thread pointer for another reason.  It 
might even be better to add a dedicated condvar to 'struct thread' in 8.x 
that is used for the wakeup and do the wakeup on that rather than the thread 
pointer to be honest.

-- 
John Baldwin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812021707.41545.jhb>