Re: [RFC] Outline of USB process integration in the kernel taskqueue system

From: John Baldwin <jhb_at_freebsd.org>
Date: Fri, 5 Nov 2010 08:58:33 -0400
On Thursday, November 04, 2010 5:49:22 pm Matthew Fleming wrote:
> On Thu, Nov 4, 2010 at 2:22 PM, John Baldwin <jhb_at_freebsd.org> wrote:
> > On Thursday, November 04, 2010 4:15:16 pm Hans Petter Selasky wrote:
> >> I think that if a task is currently executing, then there should be a drain
> >> method for that. I.E. two methods: One to stop and one to cancel/drain. Can
> >> you implement this?
> >
> > I agree, this would also be consistent with the callout_*() API if you had
> > both "stop()" and "drain()" methods.
> 
> Here's my proposed code.  Note that this builds but is not yet tested.
> 
> 
> Implement a taskqueue_cancel(9), to cancel a task from a queue.
> 
> Requested by:       hps
> Original code:      jeff
> MFC after:  1 week
> 
> 
> http://people.freebsd.org/~mdf/bsd-taskqueue-cancel.diff

For FreeBSD taskqueue_cancel() should return EBUSY, not -EBUSY.  However, I
would prefer that it follow the semantics of callout_stop() and return true
if it stopped the task and false otherwise.  The Linux wrapper for
taskqueue_cancel() can convert the return value.

I'm not sure I like reusing the memory allocation flags (M_NOWAIT / M_WAITOK)
for this blocking flag.  In the case of callout(9) we just have two functions
that pass an internal boolean to the real routine (callout_stop() and
callout_drain() are wrappers for _callout_stop_safe()).  It is a bit
unfortunate that taskqueue_drain() already exists and has different semantics
than callout_drain().  It would have been nice to have the two APIs mirror each
other instead.

Hmm, I wonder if the blocking behavior cannot safely be provided by just
doing:

	if (!taskqueue_cancel(queue, task, M_NOWAIT)
		taskqueue_drain(queue, task);

If that works ok (I think it does), I would rather have taskqueue_cancel()
always be non-blocking.  Even though there is a "race" where the task could
be rescheduled by another thread in between cancel and drain, the race still
exists since if the task could be scheduled between the two, it could also
be scheduled just before the call to taskqueue_cancel() (in which case a
taskqueue_cancel(queue, task, M_WAITOK) would have blocked to wait for it
matching the taskqueue_drain() above).  The caller still always has to
provide synchronization for preventing a task's execution outright via their
own locking.

-- 
John Baldwin
Received on Fri Nov 05 2010 - 12:02:49 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:08 UTC