From patchwork Mon Aug 29 07:08:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 9303197 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A63AC6077C for ; Mon, 29 Aug 2016 07:25:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 92E5526E54 for ; Mon, 29 Aug 2016 07:25:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 873E5286BD; Mon, 29 Aug 2016 07:25:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0C37126E54 for ; Mon, 29 Aug 2016 07:25:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756125AbcH2HZi (ORCPT ); Mon, 29 Aug 2016 03:25:38 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:35202 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750828AbcH2HZg (ORCPT ); Mon, 29 Aug 2016 03:25:36 -0400 Received: by mail-wm0-f68.google.com with SMTP id i5so8260679wmg.2 for ; Mon, 29 Aug 2016 00:25:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=BZpTtzIRQ8W6vkHpAgxJQDPr9AOVT7biDqOiecX/8Gg=; b=oujjBkTHV261Uc7yCbM0yT56x09EBA9uqfuxlrGnZaqexuPtW6e7mud7tL9RfJH5j0 a7Ux8t68IuCf6jPpInu394jbNnh9oplp04Biy35EztzLvVkAJhde0dimK21ue560Wus6 zthqTaP712cgs96zea3nIxm1wLIkT44r9n5WcpScx7dvzSSPyeYC/gj54sc1yGGdWbR9 /SHOiNZzhFdZ3zxYJDiAadPNEiNM0gznpS8+7qVCgv/BeFGfk/ZZFuNMdzeGoN66XntX QwxhSjcX0RVZLaksBMDFt44hgGuTJ4+3Y5BQfD/zo1w0fU2m1Cphzoq/kq7gmpKGvml4 IWtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=BZpTtzIRQ8W6vkHpAgxJQDPr9AOVT7biDqOiecX/8Gg=; b=DUqiGKqHIOLyGgNDip5ksA1v/JcvSufz1dxsVRCQmDFjxEY5bGQRMmZLxHsx1YuYyT X5nRMoZTHWfPSi+Ev0Hqd62tFVJFpn2Sa7rbGsqquuUBP1uwIekG+AH6J/gQl/mGRA+e HEvoRew7QDMblL9E7vMawjG/xIm6YYgIBcScm3P09y0bhUl6hNEBxXeHKN1k7+VefTGh SfrWbpBM0JIRdcX7qoxBRw19HspQujyFio+qqMgPa4bH+hb8fFDZ7nRsqNkIvTAMoZZP uhdV3tG4np+c9Tqr5QK9q/Ps3qc48sUd3etzr04samzKJEyMFwRaDCkiFM6Pq4S6YYTp fXpA== X-Gm-Message-State: AE9vXwMR2K6LJL5ZWJ88t2su7Rn4ZRW/kkLCahlhw+FGo+mq4WsGiOkd8qm6wYU3G+7lFw== X-Received: by 10.194.149.113 with SMTP id tz17mr13749014wjb.64.1472454528151; Mon, 29 Aug 2016 00:08:48 -0700 (PDT) Received: from haswell.alporthouse.com ([78.156.65.138]) by smtp.gmail.com with ESMTPSA id v203sm11954826wmv.2.2016.08.29.00.08.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 29 Aug 2016 00:08:47 -0700 (PDT) From: Chris Wilson To: dri-devel@lists.freedesktop.org Cc: intel-gfx@lists.freedesktop.org, Chris Wilson , Daniel Vetter , Sumit Semwal , linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org Subject: [PATCH 06/11] dma-buf: Introduce fence_get_rcu_safe() Date: Mon, 29 Aug 2016 08:08:29 +0100 Message-Id: <20160829070834.22296-6-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20160829070834.22296-1-chris@chris-wilson.co.uk> References: <20160829070834.22296-1-chris@chris-wilson.co.uk> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This variant of fence_get_rcu() takes an RCU protected pointer to a fence and carefully returns a reference to the fence ensuring that it is not reallocated as it does. This is required when mixing fences and SLAB_DESTROY_BY_RCU - although it serves a more pedagogical function atm Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Sumit Semwal Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-sig@lists.linaro.org Reviewed-by: Daniel Vetter --- include/linux/fence.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/include/linux/fence.h b/include/linux/fence.h index 0d763053f97a..c9c5ba98c302 100644 --- a/include/linux/fence.h +++ b/include/linux/fence.h @@ -183,6 +183,16 @@ void fence_release(struct kref *kref); void fence_free(struct fence *fence); /** + * fence_put - decreases refcount of the fence + * @fence: [in] fence to reduce refcount of + */ +static inline void fence_put(struct fence *fence) +{ + if (fence) + kref_put(&fence->refcount, fence_release); +} + +/** * fence_get - increases refcount of the fence * @fence: [in] fence to increase refcount of * @@ -210,13 +220,49 @@ static inline struct fence *fence_get_rcu(struct fence *fence) } /** - * fence_put - decreases refcount of the fence - * @fence: [in] fence to reduce refcount of + * fence_get_rcu_safe - acquire a reference to an RCU tracked fence + * @fence: [in] pointer to fence to increase refcount of + * + * Function returns NULL if no refcount could be obtained, or the fence. + * This function handles acquiring a reference to a fence that may be + * reallocated within the RCU grace period (such as with SLAB_DESTROY_BY_RCU), + * so long as the caller is using RCU on the pointer to the fence. + * + * An alternative mechanism is to employ a seqlock to protect a bunch of + * fences, such as used by struct reservation_object. When using a seqlock, + * the seqlock must be taken before and checked after a reference to the + * fence is acquired (as shown here). + * + * The caller is required to hold the RCU read lock. */ -static inline void fence_put(struct fence *fence) +static inline struct fence *fence_get_rcu_safe(struct fence * __rcu *fencep) { - if (fence) - kref_put(&fence->refcount, fence_release); + do { + struct fence *fence; + + fence = rcu_dereference(*fencep); + if (!fence || !fence_get_rcu(fence)) + return NULL; + + /* The atomic_inc_not_zero() inside fence_get_rcu() + * provides a full memory barrier upon success (such as now). + * This is paired with the write barrier from assigning + * to the __rcu protected fence pointer so that if that + * pointer still matches the current fence, we know we + * have successfully acquire a reference to it. If it no + * longer matches, we are holding a reference to some other + * reallocated pointer. This is possible if the allocator + * is using a freelist like SLAB_DESTROY_BY_RCU where the + * fence remains valid for the RCU grace period, but it + * may be reallocated. When using such allocators, we are + * responsible for ensuring the reference we get is to + * the right fence, as below. + */ + if (fence == rcu_access_pointer(*fencep)) + return rcu_pointer_handoff(fence); + + fence_put(fence); + } while (1); } int fence_signal(struct fence *fence);