diff mbox

[v4,5/5] dma-buf/sync_file: only enable fence signalling on poll()

Message ID 1468346925-12774-5-git-send-email-gustavo@padovan.org (mailing list archive)
State New, archived
Headers show

Commit Message

Gustavo Padovan July 12, 2016, 6:08 p.m. UTC
From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

Signalling doesn't need to be enabled at sync_file creation, it is only
required if userspace waiting the fence to signal through poll().

Thus we delay fence_add_callback() until poll is called. It only adds the
callback the first time poll() is called. This avoid re-adding the same
callback multiple times.

v2: rebase and update to work with new fence support for sync_file

v3: use atomic operation to set enabled and protect fence_add_callback()

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 drivers/dma-buf/sync_file.c | 22 +++++++++++++---------
 include/linux/sync_file.h   |  2 ++
 2 files changed, 15 insertions(+), 9 deletions(-)

Comments

John Harrison July 14, 2016, 1:21 p.m. UTC | #1
On 12/07/2016 19:08, Gustavo Padovan wrote:
> ...
>
> +++ b/include/linux/sync_file.h
> @@ -28,6 +28,7 @@
>    * @name:		name of sync_file.  Useful for debugging
>    * @sync_file_list:	membership in global file list
>    * @wq:			wait queue for fence signaling
> + * @enabled:		wether fence signal is enabled or not
Minor typo: should be 'whether'.
Chris Wilson Aug. 3, 2016, 11:43 a.m. UTC | #2
On Tue, Jul 12, 2016 at 03:08:45PM -0300, Gustavo Padovan wrote:
> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> 
> Signalling doesn't need to be enabled at sync_file creation, it is only
> required if userspace waiting the fence to signal through poll().
> 
> Thus we delay fence_add_callback() until poll is called. It only adds the
> callback the first time poll() is called. This avoid re-adding the same
> callback multiple times.
> 
> v2: rebase and update to work with new fence support for sync_file
> 
> v3: use atomic operation to set enabled and protect fence_add_callback()

There's actually a spare bit in fence->flags you can use for this.

#define POLL_ENABLED FENCE_FLAG_USER_BITS

if (test_bit(POLL_ENABLED, &sync_file->fence->flags))
	fence_remove_callback(sync_file->fence, &sync_file->cb);

...

if (!test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) {
	if (fence_add_callback(sync_file->fence, &sync_file->cb,
			       fence_check_cb_func) < 0)
		wake_up_all(&sync_file->wq);
}

Saves adding a raw atomic.
-Chris
Gustavo Padovan Aug. 4, 2016, 9:18 p.m. UTC | #3
2016-08-03 Chris Wilson <chris@chris-wilson.co.uk>:

> On Tue, Jul 12, 2016 at 03:08:45PM -0300, Gustavo Padovan wrote:
> > From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> > 
> > Signalling doesn't need to be enabled at sync_file creation, it is only
> > required if userspace waiting the fence to signal through poll().
> > 
> > Thus we delay fence_add_callback() until poll is called. It only adds the
> > callback the first time poll() is called. This avoid re-adding the same
> > callback multiple times.
> > 
> > v2: rebase and update to work with new fence support for sync_file
> > 
> > v3: use atomic operation to set enabled and protect fence_add_callback()
> 
> There's actually a spare bit in fence->flags you can use for this.
> 
> #define POLL_ENABLED FENCE_FLAG_USER_BITS

Wouldn't it be better to add a new bit to fence_flags_bit?

	Gustavo
Chris Wilson Aug. 4, 2016, 9:32 p.m. UTC | #4
On Thu, Aug 04, 2016 at 06:18:53PM -0300, Gustavo Padovan wrote:
> 2016-08-03 Chris Wilson <chris@chris-wilson.co.uk>:
> 
> > On Tue, Jul 12, 2016 at 03:08:45PM -0300, Gustavo Padovan wrote:
> > > From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> > > 
> > > Signalling doesn't need to be enabled at sync_file creation, it is only
> > > required if userspace waiting the fence to signal through poll().
> > > 
> > > Thus we delay fence_add_callback() until poll is called. It only adds the
> > > callback the first time poll() is called. This avoid re-adding the same
> > > callback multiple times.
> > > 
> > > v2: rebase and update to work with new fence support for sync_file
> > > 
> > > v3: use atomic operation to set enabled and protect fence_add_callback()
> > 
> > There's actually a spare bit in fence->flags you can use for this.
> > 
> > #define POLL_ENABLED FENCE_FLAG_USER_BITS
> 
> Wouldn't it be better to add a new bit to fence_flags_bit?

sync_file is a user of struct fence, so it should claim one of the bits
already reserved for users. Those reserved bits are meant only for the
owner of the fence, if we did indeed need to share that bit with other
consumers of the sync_file->fence_array then adding it to
fence_flags_bits make sense. I don't see any reason at present why it
should be anything other than a private bit to sync_file atm.

Promoting it later (from private to shared) would also not be an issue.
-Chris
diff mbox

Patch

diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
index 61a687c..240ef22 100644
--- a/drivers/dma-buf/sync_file.c
+++ b/drivers/dma-buf/sync_file.c
@@ -86,8 +86,6 @@  struct sync_file *sync_file_create(struct fence *fence)
 		 fence->ops->get_timeline_name(fence), fence->context,
 		 fence->seqno);
 
-	fence_add_callback(fence, &sync_file->cb, fence_check_cb_func);
-
 	return sync_file;
 }
 EXPORT_SYMBOL(sync_file_create);
@@ -269,9 +267,6 @@  static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
 		goto err;
 	}
 
-	fence_add_callback(sync_file->fence, &sync_file->cb,
-			   fence_check_cb_func);
-
 	strlcpy(sync_file->name, name, sizeof(sync_file->name));
 	return sync_file;
 
@@ -286,7 +281,8 @@  static void sync_file_free(struct kref *kref)
 	struct sync_file *sync_file = container_of(kref, struct sync_file,
 						     kref);
 
-	fence_remove_callback(sync_file->fence, &sync_file->cb);
+	if (atomic_read(&sync_file->enabled))
+		fence_remove_callback(sync_file->fence, &sync_file->cb);
 	fence_put(sync_file->fence);
 	kfree(sync_file);
 }
@@ -306,13 +302,21 @@  static unsigned int sync_file_poll(struct file *file, poll_table *wait)
 
 	poll_wait(file, &sync_file->wq, wait);
 
+	if (!atomic_xchg(&sync_file->enabled, 1)) {
+		if (fence_add_callback(sync_file->fence, &sync_file->cb,
+				   fence_check_cb_func) < 0)
+			wake_up_all(&sync_file->wq);
+	}
+
 	status = fence_is_signaled(sync_file->fence);
 
-	if (status)
-		return POLLIN;
+	if (!status)
+		return 0;
+
 	if (status < 0)
 		return POLLERR;
-	return 0;
+
+	return POLLIN;
 }
 
 static long sync_file_ioctl_merge(struct sync_file *sync_file,
diff --git a/include/linux/sync_file.h b/include/linux/sync_file.h
index f7de5a0..4ced13b 100644
--- a/include/linux/sync_file.h
+++ b/include/linux/sync_file.h
@@ -28,6 +28,7 @@ 
  * @name:		name of sync_file.  Useful for debugging
  * @sync_file_list:	membership in global file list
  * @wq:			wait queue for fence signaling
+ * @enabled:		wether fence signal is enabled or not
  * @fence:		fence with the fences in the sync_file
  * @cb:			fence callback information
  */
@@ -40,6 +41,7 @@  struct sync_file {
 #endif
 
 	wait_queue_head_t	wq;
+	atomic_t		enabled;
 
 	struct fence		*fence;
 	struct fence_cb cb;