From patchwork Mon Oct 26 12:29:19 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: 7487791 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 9ED8CBF90C for ; Mon, 26 Oct 2015 12:29:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 480D2207EA for ; Mon, 26 Oct 2015 12:29:49 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id D1346207E8 for ; Mon, 26 Oct 2015 12:29:46 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 08A9089826; Mon, 26 Oct 2015 05:29:45 -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 BAE9E6E577 for ; Mon, 26 Oct 2015 05:29:42 -0700 (PDT) Received: from localhost (localhost.localdomain [127.0.0.1]) by pegasos-out.vodafone.de (Rohrpostix2 Daemon) with ESMTP id 2A0BA4FE9A9 for ; Mon, 26 Oct 2015 13:29:42 +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: 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 wwQwRs3uzO-0 for ; Mon, 26 Oct 2015 13:29:40 +0100 (CET) Received: from smtp-02.vodafone.de (smtp-02.vodafone.de [10.215.254.37]) by pegasos-out.vodafone.de (Rohrpostix2 Daemon) with ESMTP id 639C94FE97C; Mon, 26 Oct 2015 13:29:39 +0100 (CET) X-DKIM: OpenDKIM Filter v2.6.8 pegasos-out.vodafone.de 639C94FE97C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vodafone.de; s=mail; t=1445862579; bh=zfoEpg+d1axPFriMYZVE6iy5HCVgGkOPDy4XFRNOLvE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=3k5wBzh2B4ksrFwh/nBc6njwTSDSXR3zeOikFBcJXYUkb3W5j3FXZqzJ7LrWiq+v7 fyWv4IVwUfDbMYnEtqGefHgUOvsTCJrXCr3w8OmpsfLCX/y/NwSFzpQJAuFAn/EwcC nkJdpZxhKQba5VyizAFN9nPDdH4oeN6GtpI+nkyo= X-Virus-Scanned: amavisd-new at vodafone.de Received: from smtp-02.vodafone.de ([127.0.0.1]) by localhost (xsmail-dmz6.prod.vfnet.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id jnv1HRsw+oTl; Mon, 26 Oct 2015 13:29:37 +0100 (CET) From: =?UTF-8?q?Christian=20K=C3=B6nig?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 01/10] dma-buf/fence: add fence_wait_any_timeout function Date: Mon, 26 Oct 2015 13:29:19 +0100 Message-Id: <1445862568-9901-2-git-send-email-deathsimple@vodafone.de> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1445862568-9901-1-git-send-email-deathsimple@vodafone.de> References: <1445862568-9901-1-git-send-email-deathsimple@vodafone.de> MIME-Version: 1.0 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. Signed-off-by: Christian König Reviewed-by: Alex Deucher --- drivers/dma-buf/fence.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fence.h | 3 +- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/drivers/dma-buf/fence.c b/drivers/dma-buf/fence.c index 50ef8bd..218623f 100644 --- a/drivers/dma-buf/fence.c +++ b/drivers/dma-buf/fence.c @@ -397,6 +397,102 @@ 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)) + return -EINVAL; + + 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 == NULL) + continue; + + 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: + for (i = 0; i < count; ++i) { + struct fence *fence = fences[i]; + if (fence && cb[i].base.func) + fence_remove_callback(fence, &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