mirror of https://github.com/OpenIPC/firmware.git
				
				
				
			
		
			
				
	
	
		
			91 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Diff
		
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Diff
		
	
	
| --- linux-4.9.37/include/linux/fence.h	2017-07-12 16:42:41.000000000 +0300
 | |
| +++ linux-4.9.y/include/linux/fence.h	2021-06-07 13:01:34.000000000 +0300
 | |
| @@ -108,6 +108,7 @@
 | |
|   * @get_driver_name: returns the driver name.
 | |
|   * @get_timeline_name: return the name of the context this fence belongs to.
 | |
|   * @enable_signaling: enable software signaling of fence.
 | |
| + * @disable_signaling: disable software signaling of fence (optional).
 | |
|   * @signaled: [optional] peek whether the fence is signaled, can be null.
 | |
|   * @wait: custom wait implementation, or fence_default_wait.
 | |
|   * @release: [optional] called on destruction of fence, can be null
 | |
| @@ -167,6 +168,7 @@
 | |
|  	const char * (*get_driver_name)(struct fence *fence);
 | |
|  	const char * (*get_timeline_name)(struct fence *fence);
 | |
|  	bool (*enable_signaling)(struct fence *fence);
 | |
| +	void (*disable_signaling)(struct fence *fence);
 | |
|  	bool (*signaled)(struct fence *fence);
 | |
|  	signed long (*wait)(struct fence *fence, bool intr, signed long timeout);
 | |
|  	void (*release)(struct fence *fence);
 | |
| @@ -183,6 +185,16 @@
 | |
|  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 +222,49 @@
 | |
|  }
 | |
|  
 | |
|  /**
 | |
| - * 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);
 |