From patchwork Tue Jun 5 23:45:54 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Erik Gilling X-Patchwork-Id: 9129 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id A3B3D23E5A for ; Tue, 5 Jun 2012 23:46:29 +0000 (UTC) Received: from mail-yw0-f52.google.com (mail-yw0-f52.google.com [209.85.213.52]) by fiordland.canonical.com (Postfix) with ESMTP id 73890A189E0 for ; Tue, 5 Jun 2012 23:46:29 +0000 (UTC) Received: by mail-yw0-f52.google.com with SMTP id p61so4963687yhp.11 for ; Tue, 05 Jun 2012 16:46:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to :date:message-id:x-mailer:in-reply-to:references:subject:x-beenthere :x-mailman-version:precedence:list-id:list-unsubscribe:list-archive :list-post:list-help:list-subscribe:mime-version:content-type :content-transfer-encoding:sender:errors-to:x-gm-message-state; bh=zY3xyeH0yYvAMZmGsktZtJo5hSrYEpUXZ/jqn3+lRJs=; b=jSBLRISpuwxYmRw5V/yT+XOZ7yMxog92/Ao7rIM/KPb89G0k4PQsLhSxA8yehahEnU QqOr44u7xA9ms/fDKP39Od/2p6HoLoIB2KR+10w+7Oqeq8Q+/S2yo7TlChE/SwjBBaR3 BEOlZgdQFPOucb1mKBnL++x0j5sa/6dttbvWp9I0veDagRZfIhUYrN9HnX8ZYC6xL+VZ qDABHMqtFbVxzWVrry2vFTa/0osIr4Am8yAs/6p6jTdJ63X7AQHnUr3ezPzAZqXRYvwm hVoMopT5genBffU8S4tG0R55zfbrfFkf46lO8co5GsNS03lZFpCW3bFDZHR+lemGq0tv qhtQ== Received: by 10.42.210.193 with SMTP id gl1mr12230628icb.57.1338939988867; Tue, 05 Jun 2012 16:46:28 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.24.148 with SMTP id v20csp52399ibb; Tue, 5 Jun 2012 16:46:28 -0700 (PDT) Received: by 10.68.203.73 with SMTP id ko9mr52979542pbc.66.1338939988100; Tue, 05 Jun 2012 16:46:28 -0700 (PDT) Received: from mombin.canonical.com (mombin.canonical.com. [91.189.95.16]) by mx.google.com with ESMTP id nm7si28789pbc.328.2012.06.05.16.46.25; Tue, 05 Jun 2012 16:46:28 -0700 (PDT) Received-SPF: neutral (google.com: 91.189.95.16 is neither permitted nor denied by best guess record for domain of linaro-mm-sig-bounces@lists.linaro.org) client-ip=91.189.95.16; Authentication-Results: mx.google.com; spf=neutral (google.com: 91.189.95.16 is neither permitted nor denied by best guess record for domain of linaro-mm-sig-bounces@lists.linaro.org) smtp.mail=linaro-mm-sig-bounces@lists.linaro.org Received: from localhost ([127.0.0.1] helo=mombin.canonical.com) by mombin.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1Sc3S8-0005mC-UW; Tue, 05 Jun 2012 23:46:21 +0000 Received: from mail-yx0-f202.google.com ([209.85.213.202]) by mombin.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1Sc3Rx-0005he-A6 for linaro-mm-sig@lists.linaro.org; Tue, 05 Jun 2012 23:46:09 +0000 Received: by yenl3 with SMTP id l3so657196yen.1 for ; Tue, 05 Jun 2012 16:46:08 -0700 (PDT) Received: by 10.101.11.39 with SMTP id o39mr8255441ani.7.1338939968737; Tue, 05 Jun 2012 16:46:08 -0700 (PDT) Received: by 10.101.11.39 with SMTP id o39mr8255436ani.7.1338939968685; Tue, 05 Jun 2012 16:46:08 -0700 (PDT) Received: from wpzn4.hot.corp.google.com (216-239-44-65.google.com [216.239.44.65]) by gmr-mx.google.com with ESMTPS id v25si2015090yhm.0.2012.06.05.16.46.08 (version=TLSv1/SSLv3 cipher=AES128-SHA); Tue, 05 Jun 2012 16:46:08 -0700 (PDT) Received: from dirtysouth.mtv.corp.google.com (dirtysouth.mtv.corp.google.com [172.18.104.93]) by wpzn4.hot.corp.google.com (Postfix) with ESMTP id 842E51E0058; Tue, 5 Jun 2012 16:46:08 -0700 (PDT) Received: by dirtysouth.mtv.corp.google.com (Postfix, from userid 94083) id 3944940EA8; Tue, 5 Jun 2012 16:46:08 -0700 (PDT) From: Erik Gilling To: linaro-mm-sig@lists.linaro.org Date: Tue, 5 Jun 2012 16:45:54 -0700 Message-Id: <1338939956-17312-10-git-send-email-konkers@android.com> X-Mailer: git-send-email 1.7.7.3 In-Reply-To: <1338939956-17312-1-git-send-email-konkers@android.com> References: <1338939956-17312-1-git-send-email-konkers@android.com> Subject: [Linaro-mm-sig] [RFC 09/11] sync: allow async waits to be canceled X-BeenThere: linaro-mm-sig@lists.linaro.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Unified memory management interest group." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linaro-mm-sig-bounces@lists.linaro.org Errors-To: linaro-mm-sig-bounces@lists.linaro.org X-Gm-Message-State: ALoCoQneRFBQZJ3EkWeXWKnKF9L8ddEVD1gnnpcRRmymEDXq5VfTt5yHgSFts7ETRbqxfmyRYUKh In order to allow drivers to cleanly handled teardown we need to allow them to cancel pending async waits. To do this cleanly, we move allocation of sync_fence_waiter to the driver calling sync_async_wait(). Signed-off-by: Erik Gilling --- drivers/base/sync.c | 46 +++++++++++++++++++++++++++++++--------------- include/linux/sync.h | 36 +++++++++++++++++++++++++++++------- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/drivers/base/sync.c b/drivers/base/sync.c index cc40e4c..5e89195 100644 --- a/drivers/base/sync.c +++ b/drivers/base/sync.c @@ -421,33 +421,22 @@ static void sync_fence_signal_pt(struct sync_pt *pt) container_of(pos, struct sync_fence_waiter, waiter_list); - waiter->callback(fence, waiter->callback_data); list_del(pos); - kfree(waiter); + waiter->callback(fence, waiter); } wake_up(&fence->wq); } } int sync_fence_wait_async(struct sync_fence *fence, - void (*callback)(struct sync_fence *, void *data), - void *callback_data) + struct sync_fence_waiter *waiter) { - struct sync_fence_waiter *waiter; unsigned long flags; int err = 0; - waiter = kzalloc(sizeof(struct sync_fence_waiter), GFP_KERNEL); - if (waiter == NULL) - return -ENOMEM; - - waiter->callback = callback; - waiter->callback_data = callback_data; - spin_lock_irqsave(&fence->waiter_list_lock, flags); if (fence->status) { - kfree(waiter); err = fence->status; goto out; } @@ -459,6 +448,34 @@ out: return err; } +int sync_fence_cancel_async(struct sync_fence *fence, + struct sync_fence_waiter *waiter) +{ + struct list_head *pos; + struct list_head *n; + unsigned long flags; + int ret = -ENOENT; + + spin_lock_irqsave(&fence->waiter_list_lock, flags); + /* + * Make sure waiter is still in waiter_list because it is possible for + * the waiter to be removed from the list while the callback is still + * pending. + */ + list_for_each_safe(pos, n, &fence->waiter_list_head) { + struct sync_fence_waiter *list_waiter = + container_of(pos, struct sync_fence_waiter, + waiter_list); + if (list_waiter == waiter) { + list_del(pos); + ret = 0; + break; + } + } + spin_unlock_irqrestore(&fence->waiter_list_lock, flags); + return ret; +} + int sync_fence_wait(struct sync_fence *fence, long timeout) { int err; @@ -739,8 +756,7 @@ static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) container_of(pos, struct sync_fence_waiter, waiter_list); - seq_printf(s, "waiter %pF %p\n", waiter->callback, - waiter->callback_data); + seq_printf(s, "waiter %pF\n", waiter->callback); } spin_unlock_irqrestore(&fence->waiter_list_lock, flags); } diff --git a/include/linux/sync.h b/include/linux/sync.h index 6db0528..1beaa53 100644 --- a/include/linux/sync.h +++ b/include/linux/sync.h @@ -161,6 +161,10 @@ struct sync_fence { struct list_head sync_fence_list; }; +struct sync_fence_waiter; +typedef void (*sync_callback_t)(struct sync_fence *fence, + struct sync_fence_waiter *waiter); + /** * struct sync_fence_waiter - metadata for asynchronous waiter on a fence * @waiter_list: membership in sync_fence.waiter_list_head @@ -170,10 +174,15 @@ struct sync_fence { struct sync_fence_waiter { struct list_head waiter_list; - void (*callback)(struct sync_fence *fence, void *data); - void *callback_data; + sync_callback_t callback; }; +static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter, + sync_callback_t callback) +{ + waiter->callback = callback; +} + /* * API for sync_timeline implementers */ @@ -286,16 +295,29 @@ void sync_fence_install(struct sync_fence *fence, int fd); /** * sync_fence_wait_async() - registers and async wait on the fence * @fence: fence to wait on - * @callback: callback - * @callback_data data to pass to the callback + * @waiter: waiter callback struck * * Returns 1 if @fence has already signaled. * - * Registers a callback to be called when @fence signals or has an error + * Registers a callback to be called when @fence signals or has an error. + * @waiter should be initialized with sync_fence_waiter_init(). */ int sync_fence_wait_async(struct sync_fence *fence, - void (*callback)(struct sync_fence *, void *data), - void *callback_data); + struct sync_fence_waiter *waiter); + +/** + * sync_fence_cancel_async() - cancels an async wait + * @fence: fence to wait on + * @waiter: waiter callback struck + * + * returns 0 if waiter was removed from fence's async waiter list. + * returns -ENOENT if waiter was not found on fence's async waiter list. + * + * Cancels a previously registered async wait. Will fail gracefully if + * @waiter was never registered or if @fence has already signaled @waiter. + */ +int sync_fence_cancel_async(struct sync_fence *fence, + struct sync_fence_waiter *waiter); /** * sync_fence_wait() - wait on fence