From patchwork Tue Oct 27 16:04:13 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Christian_K=C3=B6nig?= X-Patchwork-Id: 7497661 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id F15EFBEEA4 for ; Tue, 27 Oct 2015 16:04:35 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 600742072B for ; Tue, 27 Oct 2015 16:04:32 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 900222087A for ; Tue, 27 Oct 2015 16:04:26 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 66FB96EB0E; Tue, 27 Oct 2015 09:04:24 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from pegasos-out.vodafone.de (pegasos-out.vodafone.de [80.84.1.38]) by gabe.freedesktop.org (Postfix) with ESMTP id 09ED86EB0E for ; Tue, 27 Oct 2015 09:04:21 -0700 (PDT) Received: from localhost (localhost.localdomain [127.0.0.1]) by pegasos-out.vodafone.de (Rohrpostix2 Daemon) with ESMTP id B15575370DF; Tue, 27 Oct 2015 17:04:19 +0100 (CET) X-Virus-Scanned: amavisd-new at vodafone.de X-Spam-Score: 0.201 X-Spam-Level: X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, FREEMAIL_FROM,RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Authentication-Results: rohrpostix2.prod.vfnet.de (amavisd-new); dkim=pass header.i=@vodafone.de Received: from pegasos-out.vodafone.de ([127.0.0.1]) by localhost (rohrpostix2.prod.vfnet.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 79o6DZcza8ZJ; Tue, 27 Oct 2015 17:04:17 +0100 (CET) Received: from smtp-04.vodafone.de (xsmail-dmz10.prod.vfnet.de [10.215.254.41]) by pegasos-out.vodafone.de (Rohrpostix2 Daemon) with ESMTP id 9AF55537130; Tue, 27 Oct 2015 17:04:17 +0100 (CET) X-DKIM: OpenDKIM Filter v2.6.8 pegasos-out.vodafone.de 9AF55537130 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vodafone.de; s=mail; t=1445961857; bh=j0nx/e9gyggJTY4kS9kBQPqeLYsNGdAVRNEjoRJ2L4s=; h=From:To:Cc:Subject:Date; b=PSyqYeM95jQ0muK/TtaOCcZBM3kph8wBpmNFrxQVkPJYWx9TpxuA0jZprAZ7dtTom ZY7w8EKmcvRSh82AONl8OrRKbsFIrcJCEobDiUciYPfE4kQvXyeHl9YC+vdLA6364k BgAI06mP1/ssreggvOGfw7C7dPpsvyrtZsf6T2fw= X-Virus-Scanned: amavisd-new at vodafone.de Received: from smtp-04.vodafone.de ([127.0.0.1]) by localhost (xsmail-dmz10.prod.vfnet.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id OX4WvDsThRJ8; Tue, 27 Oct 2015 17:04:15 +0100 (CET) From: =?UTF-8?q?Christian=20K=C3=B6nig?= To: maarten.lankhorst@linux.intel.com Subject: [PATCH 1/2] dma-buf/fence: add fence_wait_any_timeout function v2 Date: Tue, 27 Oct 2015 17:04:13 +0100 Message-Id: <1445961854-2188-1-git-send-email-deathsimple@vodafone.de> X-Mailer: git-send-email 1.9.1 MIME-Version: 1.0 Cc: dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Christian König Waiting for the first fence in an array of fences to signal. This is useful for device driver specific resource managers and also Vulkan needs something similar. v2: more parameter checks, handling for timeout==0, remove NULL entry support, better callback removal. Signed-off-by: Christian König Reviewed-by: Alex Deucher --- drivers/dma-buf/fence.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fence.h | 3 +- 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/drivers/dma-buf/fence.c b/drivers/dma-buf/fence.c index 50ef8bd..7b05dbe 100644 --- a/drivers/dma-buf/fence.c +++ b/drivers/dma-buf/fence.c @@ -397,6 +397,104 @@ out: } EXPORT_SYMBOL(fence_default_wait); +static bool +fence_test_signaled_any(struct fence **fences, uint32_t count) +{ + int i; + + for (i = 0; i < count; ++i) { + struct fence *fence = fences[i]; + if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + return true; + } + return false; +} + +/** + * fence_wait_any_timeout - sleep until any fence gets signaled + * or until timeout elapses + * @fences: [in] array of fences to wait on + * @count: [in] number of fences to wait on + * @intr: [in] if true, do an interruptible wait + * @timeout: [in] timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT + * + * Returns -EINVAL on custom fence wait implementation, -ERESTARTSYS if + * interrupted, 0 if the wait timed out, or the remaining timeout in jiffies + * on success. + * + * Synchronous waits for the first fence in the array to be signaled. The + * caller needs to hold a reference to all fences in the array, otherwise a + * fence might be freed before return, resulting in undefined behavior. + */ +signed long +fence_wait_any_timeout(struct fence **fences, uint32_t count, + bool intr, signed long timeout) +{ + struct default_wait_cb *cb; + signed long ret = timeout; + unsigned i; + + if (WARN_ON(!fences || !count || timeout < 0)) + return -EINVAL; + + if (timeout == 0) { + for (i = 0; i < count; ++i) + if (fence_is_signaled(fences[i])) + return 1; + + return 0; + } + + cb = kcalloc(count, sizeof(struct default_wait_cb), GFP_KERNEL); + if (cb == NULL) { + ret = -ENOMEM; + goto err_free_cb; + } + + for (i = 0; i < count; ++i) { + struct fence *fence = fences[i]; + + if (fence->ops->wait != fence_default_wait) { + ret = -EINVAL; + goto fence_rm_cb; + } + + cb[i].task = current; + if (fence_add_callback(fence, &cb[i].base, + fence_default_wait_cb)) { + /* This fence is already signaled */ + goto fence_rm_cb; + } + } + + while (ret > 0) { + if (intr) + set_current_state(TASK_INTERRUPTIBLE); + else + set_current_state(TASK_UNINTERRUPTIBLE); + + if (fence_test_signaled_any(fences, count)) + break; + + ret = schedule_timeout(ret); + + if (ret > 0 && intr && signal_pending(current)) + ret = -ERESTARTSYS; + } + + __set_current_state(TASK_RUNNING); + +fence_rm_cb: + while (i-- > 0) + fence_remove_callback(fences[i], &cb[i].base); + +err_free_cb: + kfree(cb); + + return ret; +} +EXPORT_SYMBOL(fence_wait_any_timeout); + /** * fence_init - Initialize a custom fence. * @fence: [in] the fence to initialize diff --git a/include/linux/fence.h b/include/linux/fence.h index ddc0f26..bb52201 100644 --- a/include/linux/fence.h +++ b/include/linux/fence.h @@ -321,7 +321,8 @@ static inline struct fence *fence_later(struct fence *f1, struct fence *f2) } signed long fence_wait_timeout(struct fence *, bool intr, signed long timeout); - +signed long fence_wait_any_timeout(struct fence **fences, uint32_t count, + bool intr, signed long timeout); /** * fence_wait - sleep until the fence gets signaled