Date: Tue, 19 Nov 2013 16:32:33 +0200 From: Andriy Gapon <avg@FreeBSD.org> To: freebsd-hackers@FreeBSD.org Subject: Fwd: taskqueue_block Message-ID: <528B7681.6090806@FreeBSD.org> In-Reply-To: <5287BDB9.10201@FreeBSD.org> References: <5287BDB9.10201@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Forwarding this to the larger audience for a discussion. -------- Original Message -------- Message-ID: <5287BDB9.10201@FreeBSD.org> Date: Sat, 16 Nov 2013 20:47:21 +0200 From: Andriy Gapon <avg@FreeBSD.org> Subject: taskqueue_block It seems that either I do not understand something about taskqueue_block code or it is a quite dangerous and abused API. The fact that it is not properly documented does not help either. The commit message said: > Implement taskqueue_block() and taskqueue_unblock(). These functions allow the > owner of a queue to block and unblock execution of the tasks in the queue while > allowing tasks to continue to be added queue. Combining this with > taskqueue_drain() allows a queue to be safely disabled. The unblock function may [...] I indeed see this (anti?) pattern being used in the code. But what about the following case. One thread calls taskqueue_block() and sets TQ_FLAGS_BLOCKED. Another thread calls taskqueue_enqueue, this adds a task to the queue and sets ta_pending of the task to 1. tq_enqueue is not called, so an actual queue runner is not called or waken up. Then the first thread calls taskqueue_drain() on the task. As far as I can see, the thread would then just wait forever because the task is pending and is not going to be executed. Additionally, it is impossible to reason about the taskqueue's state after taskqueue_block call, because the call just sets the flag and does not do any synchronization. And as described above, it is not safe to call APIs that could allow the taskqueue or the task state to become known. I think that taskqueue_block() should wait on the currently active tasks to complete. I don't think that this behavior could be optional. I do see any reasonable and safe use for "non-blocking" taskqueue_block(). taskqueue_drain() calls after taskqueue_block() must be removed. The code should either use taskqueue_drain() or "blocking" taskqueue_block() depending on concrete circumstances. What do you think? Thank you. -- Andriy Gapon
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?528B7681.6090806>