diff options
Diffstat (limited to 'include/linux/srcu.h')
| -rw-r--r-- | include/linux/srcu.h | 63 | 
1 files changed, 63 insertions, 0 deletions
diff --git a/include/linux/srcu.h b/include/linux/srcu.h index 01226e4d960a..f0814ffca34b 100644 --- a/include/linux/srcu.h +++ b/include/linux/srcu.h @@ -64,6 +64,20 @@ unsigned long get_state_synchronize_srcu(struct srcu_struct *ssp);  unsigned long start_poll_synchronize_srcu(struct srcu_struct *ssp);  bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie); +#ifdef CONFIG_NEED_SRCU_NMI_SAFE +int __srcu_read_lock_nmisafe(struct srcu_struct *ssp) __acquires(ssp); +void __srcu_read_unlock_nmisafe(struct srcu_struct *ssp, int idx) __releases(ssp); +#else +static inline int __srcu_read_lock_nmisafe(struct srcu_struct *ssp) +{ +	return __srcu_read_lock(ssp); +} +static inline void __srcu_read_unlock_nmisafe(struct srcu_struct *ssp, int idx) +{ +	__srcu_read_unlock(ssp, idx); +} +#endif /* CONFIG_NEED_SRCU_NMI_SAFE */ +  #ifdef CONFIG_SRCU  void srcu_init(void);  #else /* #ifdef CONFIG_SRCU */ @@ -104,6 +118,18 @@ static inline int srcu_read_lock_held(const struct srcu_struct *ssp)  #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ +#define SRCU_NMI_UNKNOWN	0x0 +#define SRCU_NMI_UNSAFE		0x1 +#define SRCU_NMI_SAFE		0x2 + +#if defined(CONFIG_PROVE_RCU) && defined(CONFIG_TREE_SRCU) +void srcu_check_nmi_safety(struct srcu_struct *ssp, bool nmi_safe); +#else +static inline void srcu_check_nmi_safety(struct srcu_struct *ssp, +					 bool nmi_safe) { } +#endif + +  /**   * srcu_dereference_check - fetch SRCU-protected pointer for later dereferencing   * @p: the pointer to fetch and protect for later dereferencing @@ -161,17 +187,36 @@ static inline int srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp)  {  	int retval; +	srcu_check_nmi_safety(ssp, false);  	retval = __srcu_read_lock(ssp);  	rcu_lock_acquire(&(ssp)->dep_map);  	return retval;  } +/** + * srcu_read_lock_nmisafe - register a new reader for an SRCU-protected structure. + * @ssp: srcu_struct in which to register the new reader. + * + * Enter an SRCU read-side critical section, but in an NMI-safe manner. + * See srcu_read_lock() for more information. + */ +static inline int srcu_read_lock_nmisafe(struct srcu_struct *ssp) __acquires(ssp) +{ +	int retval; + +	srcu_check_nmi_safety(ssp, true); +	retval = __srcu_read_lock_nmisafe(ssp); +	rcu_lock_acquire(&(ssp)->dep_map); +	return retval; +} +  /* Used by tracing, cannot be traced and cannot invoke lockdep. */  static inline notrace int  srcu_read_lock_notrace(struct srcu_struct *ssp) __acquires(ssp)  {  	int retval; +	srcu_check_nmi_safety(ssp, false);  	retval = __srcu_read_lock(ssp);  	return retval;  } @@ -187,14 +232,32 @@ static inline void srcu_read_unlock(struct srcu_struct *ssp, int idx)  	__releases(ssp)  {  	WARN_ON_ONCE(idx & ~0x1); +	srcu_check_nmi_safety(ssp, false);  	rcu_lock_release(&(ssp)->dep_map);  	__srcu_read_unlock(ssp, idx);  } +/** + * srcu_read_unlock_nmisafe - unregister a old reader from an SRCU-protected structure. + * @ssp: srcu_struct in which to unregister the old reader. + * @idx: return value from corresponding srcu_read_lock(). + * + * Exit an SRCU read-side critical section, but in an NMI-safe manner. + */ +static inline void srcu_read_unlock_nmisafe(struct srcu_struct *ssp, int idx) +	__releases(ssp) +{ +	WARN_ON_ONCE(idx & ~0x1); +	srcu_check_nmi_safety(ssp, true); +	rcu_lock_release(&(ssp)->dep_map); +	__srcu_read_unlock_nmisafe(ssp, idx); +} +  /* Used by tracing, cannot be traced and cannot call lockdep. */  static inline notrace void  srcu_read_unlock_notrace(struct srcu_struct *ssp, int idx) __releases(ssp)  { +	srcu_check_nmi_safety(ssp, false);  	__srcu_read_unlock(ssp, idx);  }  |