diff options
Diffstat (limited to 'include/linux/reservation.h')
| -rw-r--r-- | include/linux/reservation.h | 82 | 
1 files changed, 81 insertions, 1 deletions
| diff --git a/include/linux/reservation.h b/include/linux/reservation.h index 813dae960ebd..5a0b64cf68b4 100644 --- a/include/linux/reservation.h +++ b/include/linux/reservation.h @@ -6,7 +6,7 @@   * Copyright (C) 2012 Texas Instruments   *   * Authors: - * Rob Clark <rob.clark@linaro.org> + * Rob Clark <robdclark@gmail.com>   * Maarten Lankhorst <maarten.lankhorst@canonical.com>   * Thomas Hellstrom <thellstrom-at-vmware-dot-com>   * @@ -40,23 +40,103 @@  #define _LINUX_RESERVATION_H  #include <linux/ww_mutex.h> +#include <linux/fence.h> +#include <linux/slab.h> +#include <linux/seqlock.h> +#include <linux/rcupdate.h>  extern struct ww_class reservation_ww_class; +extern struct lock_class_key reservation_seqcount_class; +extern const char reservation_seqcount_string[]; + +struct reservation_object_list { +	struct rcu_head rcu; +	u32 shared_count, shared_max; +	struct fence __rcu *shared[]; +};  struct reservation_object {  	struct ww_mutex lock; +	seqcount_t seq; + +	struct fence __rcu *fence_excl; +	struct reservation_object_list __rcu *fence; +	struct reservation_object_list *staged;  }; +#define reservation_object_held(obj) lockdep_is_held(&(obj)->lock.base) +#define reservation_object_assert_held(obj) \ +	lockdep_assert_held(&(obj)->lock.base) +  static inline void  reservation_object_init(struct reservation_object *obj)  {  	ww_mutex_init(&obj->lock, &reservation_ww_class); + +	__seqcount_init(&obj->seq, reservation_seqcount_string, &reservation_seqcount_class); +	RCU_INIT_POINTER(obj->fence, NULL); +	RCU_INIT_POINTER(obj->fence_excl, NULL); +	obj->staged = NULL;  }  static inline void  reservation_object_fini(struct reservation_object *obj)  { +	int i; +	struct reservation_object_list *fobj; +	struct fence *excl; + +	/* +	 * This object should be dead and all references must have +	 * been released to it, so no need to be protected with rcu. +	 */ +	excl = rcu_dereference_protected(obj->fence_excl, 1); +	if (excl) +		fence_put(excl); + +	fobj = rcu_dereference_protected(obj->fence, 1); +	if (fobj) { +		for (i = 0; i < fobj->shared_count; ++i) +			fence_put(rcu_dereference_protected(fobj->shared[i], 1)); + +		kfree(fobj); +	} +	kfree(obj->staged); +  	ww_mutex_destroy(&obj->lock);  } +static inline struct reservation_object_list * +reservation_object_get_list(struct reservation_object *obj) +{ +	return rcu_dereference_protected(obj->fence, +					 reservation_object_held(obj)); +} + +static inline struct fence * +reservation_object_get_excl(struct reservation_object *obj) +{ +	return rcu_dereference_protected(obj->fence_excl, +					 reservation_object_held(obj)); +} + +int reservation_object_reserve_shared(struct reservation_object *obj); +void reservation_object_add_shared_fence(struct reservation_object *obj, +					 struct fence *fence); + +void reservation_object_add_excl_fence(struct reservation_object *obj, +				       struct fence *fence); + +int reservation_object_get_fences_rcu(struct reservation_object *obj, +				      struct fence **pfence_excl, +				      unsigned *pshared_count, +				      struct fence ***pshared); + +long reservation_object_wait_timeout_rcu(struct reservation_object *obj, +					 bool wait_all, bool intr, +					 unsigned long timeout); + +bool reservation_object_test_signaled_rcu(struct reservation_object *obj, +					  bool test_all); +  #endif /* _LINUX_RESERVATION_H */ | 
