From patchwork Thu Oct 29 16:04:55 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: 7519891 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 831FB9F399 for ; Thu, 29 Oct 2015 16:06:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9519A2060D for ; Thu, 29 Oct 2015 16:06:13 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 1A0BD2069D for ; Thu, 29 Oct 2015 16:06:12 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EA38C6E6C5; Thu, 29 Oct 2015 09:06:09 -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 198B76E6A6 for ; Thu, 29 Oct 2015 09:05:32 -0700 (PDT) Received: from localhost (localhost.localdomain [127.0.0.1]) by pegasos-out.vodafone.de (Rohrpostix1 Daemon) with ESMTP id 2411526084C; Thu, 29 Oct 2015 17:05:25 +0100 (CET) X-Virus-Scanned: amavisd-new at vodafone.de X-Spam-Score: -0.044 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: rohrpostix1.prod.vfnet.de (amavisd-new); dkim=pass header.i=@vodafone.de Received: from pegasos-out.vodafone.de ([127.0.0.1]) by localhost (rohrpostix1.prod.vfnet.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id aZS5Y5YvJWFC; Thu, 29 Oct 2015 17:05:23 +0100 (CET) Received: from smtp-03.vodafone.de (smtp-03.vodafone.de [10.215.254.38]) by pegasos-out.vodafone.de (Rohrpostix1 Daemon) with ESMTP id 448C7260062; Thu, 29 Oct 2015 17:05:23 +0100 (CET) X-DKIM: OpenDKIM Filter v2.6.8 pegasos-out.vodafone.de 448C7260062 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vodafone.de; s=mail; t=1446134723; bh=vdVE3l9O0Zat+zlZazl4/Aq3zRZ9Gvezxc0doFvyfck=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=H0VvyXVG2pvQTtwFgNzBmCSiqX2aTGoY7RIQdEEFz+u3xApZQDIpKK8TnWQWg6FQM g5zDBsfO3/Bv4z75zLeKeNlQW8lq/pRyOqvihyy31wZhNaAfugH8UP5m2nenvHDdqD wbwpJaEu7F5zWEl+wrBvzteAG+oNwKC6N8BOCIhs= X-Virus-Scanned: amavisd-new at vodafone.de Received: from smtp-03.vodafone.de ([127.0.0.1]) by localhost (xsmail-dmz7.prod.vfnet.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ozHi5DSlyky7; Thu, 29 Oct 2015 17:05:20 +0100 (CET) From: =?UTF-8?q?Christian=20K=C3=B6nig?= To: alexdeucher@gmail.com Subject: [PATCH 1/9] dma-buf/fence: add fence_wait_any_timeout function v2 Date: Thu, 29 Oct 2015 17:04:55 +0100 Message-Id: <1446134703-32433-2-git-send-email-deathsimple@vodafone.de> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1446134703-32433-1-git-send-email-deathsimple@vodafone.de> References: <1446134703-32433-1-git-send-email-deathsimple@vodafone.de> 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 Reviewed-by: Maarten Lankhorst Acked-by: Sumit Semwal --- 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 39efee1..a4084d6 100644 --- a/include/linux/fence.h +++ b/include/linux/fence.h @@ -305,7 +305,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