[PATCH 4/7] sync_file: add support for sem_file

Chris Wilson chris at chris-wilson.co.uk
Thu Apr 13 02:52:14 UTC 2017


On Thu, Apr 13, 2017 at 11:41:41AM +1000, Dave Airlie wrote:
> From: Dave Airlie <airlied at redhat.com>
> 
> This adds support for a file that has semaphore semantics
> (for Vulkan shared semaphores).
> 
> These objects are persistent objects that can have a
> fence that changes. When the object is signaled, a fence
> is attached to it, and when an object is waited on, the
> fence is removed. All interactions with these objects
> should be via command submission routines in the drm
> drivers. The sem_file is just for passing the sems between
> processes.
> 
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
>  drivers/dma-buf/sync_file.c | 101 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/sync_file.h   |  16 +++++++
>  2 files changed, 117 insertions(+)
> 
> diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
> index 2342d8b..a88d786 100644
> --- a/drivers/dma-buf/sync_file.c
> +++ b/drivers/dma-buf/sync_file.c
> @@ -468,3 +468,104 @@ static const struct file_operations sync_file_fops = {
>  	.unlocked_ioctl = sync_file_ioctl,
>  	.compat_ioctl = sync_file_ioctl,
>  };
> +
> +static int sem_file_release(struct inode *inode, struct file *file)
> +{
> +	struct sem_file *sem_file = file->private_data;
> +	struct dma_fence *fence;
> +
> +	fence = rcu_dereference_protected(sem_file->base.fence, 1);
> +	dma_fence_put(fence);
> +	kfree(sem_file);
> +
> +	return 0;
> +}
> +
> +static const struct file_operations sem_file_fops = {
> +	.release = sem_file_release,
> +};
> +
> +struct sem_file *sem_file_alloc(void)
> +{
> +	struct sem_file *sem_file;
> +	int ret;
> +
> +	sem_file = kzalloc(sizeof(*sem_file), GFP_KERNEL);
> +	if (!sem_file)
> +		return NULL;
> +
> +	ret = fence_file_init(&sem_file->base,
> +			      &sem_file_fops);
> +	if (ret)
> +		goto err;
> +
> +	RCU_INIT_POINTER(sem_file->base.fence, NULL);
> +	mutex_init(&sem_file->lock);
> +
> +	return sem_file;
> +
> +err:
> +	kfree(sem_file);
> +	return NULL;
> +}
> +EXPORT_SYMBOL(sem_file_alloc);
> +
> +struct sem_file *sem_file_fdget(int fd)
> +{
> +	struct file *file = fget(fd);
> +
> +	if (!file)
> +		return NULL;
> +
> +	if (file->f_op != &sem_file_fops)
> +		goto err;
> +
> +	return file->private_data;
> +
> +err:
> +	fput(file);
> +	return NULL;
> +}
> +EXPORT_SYMBOL(sem_file_fdget);
> +
> +#define sem_file_held(obj) lockdep_is_held(&(obj)->lock)
> +
> +struct dma_fence *sem_file_get_fence(struct sem_file *sem_file)
> +{
> +	struct dma_fence *fence;
> +
> +	if (!rcu_access_pointer(sem_file->base.fence)) {
> +		return NULL;
> +	}
> +
> +	rcu_read_lock();
> +	fence = dma_fence_get_rcu_safe(&sem_file->base.fence);
> +	rcu_read_unlock();
> +	return fence;
> +}
> +EXPORT_SYMBOL(sem_file_get_fence);
> +
> +static inline struct dma_fence *
> +sem_file_get_fence_locked(struct sem_file *sem_file)
> +{
> +	return rcu_dereference_protected(sem_file->base.fence,
> +					 sem_file_held(sem_file));
> +}
> +
> +int sem_file_replace_fence(struct sem_file *sem_file,
> +			   struct dma_fence *fence,
> +			   struct dma_fence **old_fence)
> +{
> +	struct dma_fence *ret_fence = NULL;
> +
> +	if (fence)
> +		dma_fence_get(fence);
> +
> +	mutex_lock(&sem_file->lock);
> +	ret_fence = sem_file_get_fence_locked(sem_file);
> +	RCU_INIT_POINTER(sem_file->base.fence, fence);
> +	mutex_unlock(&sem_file->lock);

Is xchg() universal?

struct dma_fence *sem_file_replace_fence(struct sem_file *sem_file,
					 struct dma_fence *fence)
{
	return xchg(&sem_file->base.fence, dma_fence_get(fence));
}

safe against the rcu read and kills off the mutex.

I think this is the cleaner approach, precisely because it stops me
having the delusion that the semaphores and sync_file are
interchangeable, and I won't ask if I can merge semaphores together, or
if I can inspect the state with the CPU.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre


More information about the amd-gfx mailing list