On Thursday, November 04, 2010 5:49:22 pm Matthew Fleming wrote:
> On Thu, Nov 4, 2010 at 2:22 PM, John Baldwin <j...@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

        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
freebsd-usb@freebsd.org mailing list
To unsubscribe, send any mail to "freebsd-usb-unsubscr...@freebsd.org"

Reply via email to