Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71ebc9a3 authored by Chris Wilson's avatar Chris Wilson Committed by Gustavo Padovan
Browse files

dma-buf/sync-file: Defer creation of sync_file->name



Constructing the name takes the majority of the time for allocating a
sync_file to wrap a fence, and the name is very rarely used (only via
the sync_file status user interface). To reduce the impact on the common
path (that of creating sync_file to pass around), defer the construction
of the name until it is first used.

v2: Update kerneldoc (kbuild test robot)
v3: sync_debug.c was peeking at the name
v4: Comment upon the potential race between two users of
sync_file_get_name() and claim that such a race is below the level of
notice. However, to prevent any future nuisance, use a global spinlock
to serialize the assignment of the name.
v5: Completely avoid the read/write race by only storing the name passed
in from the user inside sync_file->user_name and passing in a buffer to
dynamically construct the name otherwise.

Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Cc: Gustavo Padovan <gustavo@padovan.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: David Herrmann <dh.herrmann@gmail.com>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarGustavo Padovan <gustavo.padovan@collabora.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170516111042.24719-1-chris@chris-wilson.co.uk
parent c16f291d
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -132,9 +132,11 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
static void sync_print_sync_file(struct seq_file *s,
				  struct sync_file *sync_file)
{
	char buf[128];
	int i;

	seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name,
	seq_printf(s, "[%p] %s: %s\n", sync_file,
		   sync_file_get_name(sync_file, buf, sizeof(buf)),
		   sync_status_str(dma_fence_get_status(sync_file->fence)));

	if (dma_fence_is_array(sync_file->fence)) {
+32 −7
Original line number Diff line number Diff line
@@ -80,11 +80,6 @@ struct sync_file *sync_file_create(struct dma_fence *fence)

	sync_file->fence = dma_fence_get(fence);

	snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d",
		 fence->ops->get_driver_name(fence),
		 fence->ops->get_timeline_name(fence), fence->context,
		 fence->seqno);

	return sync_file;
}
EXPORT_SYMBOL(sync_file_create);
@@ -129,6 +124,36 @@ struct dma_fence *sync_file_get_fence(int fd)
}
EXPORT_SYMBOL(sync_file_get_fence);

/**
 * sync_file_get_name - get the name of the sync_file
 * @sync_file:		sync_file to get the fence from
 * @buf:		destination buffer to copy sync_file name into
 * @len:		available size of destination buffer.
 *
 * Each sync_file may have a name assigned either by the user (when merging
 * sync_files together) or created from the fence it contains. In the latter
 * case construction of the name is deferred until use, and so requires
 * sync_file_get_name().
 *
 * Returns: a string representing the name.
 */
char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len)
{
	if (sync_file->user_name[0]) {
		strlcpy(buf, sync_file->user_name, len);
	} else {
		struct dma_fence *fence = sync_file->fence;

		snprintf(buf, len, "%s-%s%llu-%d",
			 fence->ops->get_driver_name(fence),
			 fence->ops->get_timeline_name(fence),
			 fence->context,
			 fence->seqno);
	}

	return buf;
}

static int sync_file_set_fence(struct sync_file *sync_file,
			       struct dma_fence **fences, int num_fences)
{
@@ -266,7 +291,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
		goto err;
	}

	strlcpy(sync_file->name, name, sizeof(sync_file->name));
	strlcpy(sync_file->user_name, name, sizeof(sync_file->user_name));
	return sync_file;

err:
@@ -413,7 +438,7 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
	}

no_fences:
	strlcpy(info.name, sync_file->name, sizeof(info.name));
	sync_file_get_name(sync_file, info.name, sizeof(info.name));
	info.status = dma_fence_is_signaled(sync_file->fence);
	info.num_fences = num_fences;

+9 −2
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@
/**
 * struct sync_file - sync file to export to the userspace
 * @file:		file representing this fence
 * @name:		name of sync_file.  Useful for debugging
 * @sync_file_list:	membership in global file list
 * @wq:			wait queue for fence signaling
 * @fence:		fence with the fences in the sync_file
@@ -31,7 +30,14 @@
 */
struct sync_file {
	struct file		*file;
	char			name[32];
	/**
	 * @user_name:
	 *
	 * Name of the sync file provided by userspace, for merged fences.
	 * Otherwise generated through driver callbacks (in which case the
	 * entire array is 0).
	 */
	char			user_name[32];
#ifdef CONFIG_DEBUG_FS
	struct list_head	sync_file_list;
#endif
@@ -46,5 +52,6 @@ struct sync_file {

struct sync_file *sync_file_create(struct dma_fence *fence);
struct dma_fence *sync_file_get_fence(int fd);
char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len);

#endif /* _LINUX_SYNC_H */