From owner-freebsd-hackers@FreeBSD.ORG Wed Oct 9 08:56:19 2013 Return-Path: Delivered-To: freebsd-hackers@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 7E564466 for ; Wed, 9 Oct 2013 08:56:19 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from citadel.icyb.net.ua (citadel.icyb.net.ua [212.40.38.140]) by mx1.freebsd.org (Postfix) with ESMTP id CB9FE25FA for ; Wed, 9 Oct 2013 08:56:18 +0000 (UTC) Received: from porto.starpoint.kiev.ua (porto-e.starpoint.kiev.ua [212.40.38.100]) by citadel.icyb.net.ua (8.8.8p3/ICyb-2.3exp) with ESMTP id LAA28342 for ; Wed, 09 Oct 2013 11:56:10 +0300 (EEST) (envelope-from avg@FreeBSD.org) Received: from localhost ([127.0.0.1]) by porto.starpoint.kiev.ua with esmtp (Exim 4.34 (FreeBSD)) id 1VTpYw-000OZn-CE for freebsd-hackers@FreeBSD.org; Wed, 09 Oct 2013 11:56:10 +0300 Message-ID: <525519F1.3050703@FreeBSD.org> Date: Wed, 09 Oct 2013 11:55:13 +0300 From: Andriy Gapon User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:24.0) Gecko/20100101 Thunderbird/24.0 MIME-Version: 1.0 To: freebsd-hackers@FreeBSD.org Subject: taskqueue_drain_all X-Enigmail-Version: 1.5.2 Content-Type: text/plain; charset=X-VIET-VPS Content-Transfer-Encoding: 7bit X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 09 Oct 2013 08:56:19 -0000 I would like to propose to extend taskqueue API with taskqueue_drain_all. A potential use case: I have a private taskqueue, several kinds of tasks get executed via it and then I want to make sure that all of them are completed. Obviously, I have a way to ensure that no new ones get enqueued. Is this a good addition? Or should like consider looping over all of my tasks externally to taskqueue implementation? A quick prototype: --- a/sys/kern/subr_taskqueue.c +++ b/sys/kern/subr_taskqueue.c @@ -316,6 +316,7 @@ taskqueue_run_locked(struct taskqueue *queue) wakeup(task); } TAILQ_REMOVE(&queue->tq_active, &tb, tb_link); + wakeup(&queue->tq_active); } void @@ -402,6 +403,22 @@ taskqueue_drain(struct taskqueue *queue, struct task *task) } void +taskqueue_drain_all(struct taskqueue *queue) +{ + struct task *task; + + TQ_LOCK(queue); + while ((task = STAILQ_FIRST(&queue->tq_queue)) != NULL) { + while (task->ta_pending != 0 || task_is_running(queue, task)) + TQ_SLEEP(queue, task, &queue->tq_mutex, PWAIT, "-", 0); + } + while (TAILQ_FIRST(&queue->tq_active) != NULL) + TQ_SLEEP(queue, &queue->tq_active, + &queue->tq_mutex, PWAIT, "-", 0); + TQ_UNLOCK(queue); +} + +void taskqueue_drain_timeout(struct taskqueue *queue, struct timeout_task *timeout_task) { -- Andriy Gapon