@@ -47,7 +47,13 @@ int init_srcu_struct(struct srcu_struct *ssp);
4747#define SRCU_READ_FLAVOR_NORMAL 0x1 // srcu_read_lock().
4848#define SRCU_READ_FLAVOR_NMI 0x2 // srcu_read_lock_nmisafe().
4949#define SRCU_READ_FLAVOR_LITE 0x4 // srcu_read_lock_lite().
50- #define SRCU_READ_FLAVOR_ALL 0x7 // All of the above.
50+ #define SRCU_READ_FLAVOR_FAST 0x8 // srcu_read_lock_fast().
51+ #define SRCU_READ_FLAVOR_ALL (SRCU_READ_FLAVOR_NORMAL | SRCU_READ_FLAVOR_NMI | \
52+ SRCU_READ_FLAVOR_LITE | SRCU_READ_FLAVOR_FAST) // All of the above.
53+ #define SRCU_READ_FLAVOR_SLOWGP (SRCU_READ_FLAVOR_LITE | SRCU_READ_FLAVOR_FAST)
54+ // Flavors requiring synchronize_rcu()
55+ // instead of smp_mb().
56+ void __srcu_read_unlock (struct srcu_struct * ssp , int idx ) __releases (ssp );
5157
5258#ifdef CONFIG_TINY_SRCU
5359#include <linux/srcutiny.h>
@@ -60,15 +66,6 @@ int init_srcu_struct(struct srcu_struct *ssp);
6066void call_srcu (struct srcu_struct * ssp , struct rcu_head * head ,
6167 void (* func )(struct rcu_head * head ));
6268void cleanup_srcu_struct (struct srcu_struct * ssp );
63- int __srcu_read_lock (struct srcu_struct * ssp ) __acquires (ssp );
64- void __srcu_read_unlock (struct srcu_struct * ssp , int idx ) __releases (ssp );
65- #ifdef CONFIG_TINY_SRCU
66- #define __srcu_read_lock_lite __srcu_read_lock
67- #define __srcu_read_unlock_lite __srcu_read_unlock
68- #else // #ifdef CONFIG_TINY_SRCU
69- int __srcu_read_lock_lite (struct srcu_struct * ssp ) __acquires (ssp );
70- void __srcu_read_unlock_lite (struct srcu_struct * ssp , int idx ) __releases (ssp );
71- #endif // #else // #ifdef CONFIG_TINY_SRCU
7269void synchronize_srcu (struct srcu_struct * ssp );
7370
7471#define SRCU_GET_STATE_COMPLETED 0x1
@@ -257,6 +254,51 @@ static inline int srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp)
257254 return retval ;
258255}
259256
257+ /**
258+ * srcu_read_lock_fast - register a new reader for an SRCU-protected structure.
259+ * @ssp: srcu_struct in which to register the new reader.
260+ *
261+ * Enter an SRCU read-side critical section, but for a light-weight
262+ * smp_mb()-free reader. See srcu_read_lock() for more information.
263+ *
264+ * If srcu_read_lock_fast() is ever used on an srcu_struct structure,
265+ * then none of the other flavors may be used, whether before, during,
266+ * or after. Note that grace-period auto-expediting is disabled for _fast
267+ * srcu_struct structures because auto-expedited grace periods invoke
268+ * synchronize_rcu_expedited(), IPIs and all.
269+ *
270+ * Note that srcu_read_lock_fast() can be invoked only from those contexts
271+ * where RCU is watching, that is, from contexts where it would be legal
272+ * to invoke rcu_read_lock(). Otherwise, lockdep will complain.
273+ */
274+ static inline struct srcu_ctr __percpu * srcu_read_lock_fast (struct srcu_struct * ssp ) __acquires (ssp )
275+ {
276+ struct srcu_ctr __percpu * retval ;
277+
278+ srcu_check_read_flavor_force (ssp , SRCU_READ_FLAVOR_FAST );
279+ retval = __srcu_read_lock_fast (ssp );
280+ rcu_try_lock_acquire (& ssp -> dep_map );
281+ return retval ;
282+ }
283+
284+ /**
285+ * srcu_down_read_fast - register a new reader for an SRCU-protected structure.
286+ * @ssp: srcu_struct in which to register the new reader.
287+ *
288+ * Enter a semaphore-like SRCU read-side critical section, but for
289+ * a light-weight smp_mb()-free reader. See srcu_read_lock_fast() and
290+ * srcu_down_read() for more information.
291+ *
292+ * The same srcu_struct may be used concurrently by srcu_down_read_fast()
293+ * and srcu_read_lock_fast().
294+ */
295+ static inline struct srcu_ctr __percpu * srcu_down_read_fast (struct srcu_struct * ssp ) __acquires (ssp )
296+ {
297+ WARN_ON_ONCE (IS_ENABLED (CONFIG_PROVE_RCU ) && in_nmi ());
298+ srcu_check_read_flavor_force (ssp , SRCU_READ_FLAVOR_FAST );
299+ return __srcu_read_lock_fast (ssp );
300+ }
301+
260302/**
261303 * srcu_read_lock_lite - register a new reader for an SRCU-protected structure.
262304 * @ssp: srcu_struct in which to register the new reader.
@@ -278,7 +320,7 @@ static inline int srcu_read_lock_lite(struct srcu_struct *ssp) __acquires(ssp)
278320{
279321 int retval ;
280322
281- srcu_check_read_flavor_lite (ssp );
323+ srcu_check_read_flavor_force (ssp , SRCU_READ_FLAVOR_LITE );
282324 retval = __srcu_read_lock_lite (ssp );
283325 rcu_try_lock_acquire (& ssp -> dep_map );
284326 return retval ;
@@ -335,7 +377,8 @@ srcu_read_lock_notrace(struct srcu_struct *ssp) __acquires(ssp)
335377 * srcu_down_read() nor srcu_up_read() may be invoked from an NMI handler.
336378 *
337379 * Calls to srcu_down_read() may be nested, similar to the manner in
338- * which calls to down_read() may be nested.
380+ * which calls to down_read() may be nested. The same srcu_struct may be
381+ * used concurrently by srcu_down_read() and srcu_read_lock().
339382 */
340383static inline int srcu_down_read (struct srcu_struct * ssp ) __acquires (ssp )
341384{
@@ -360,10 +403,41 @@ static inline void srcu_read_unlock(struct srcu_struct *ssp, int idx)
360403 __srcu_read_unlock (ssp , idx );
361404}
362405
406+ /**
407+ * srcu_read_unlock_fast - unregister a old reader from an SRCU-protected structure.
408+ * @ssp: srcu_struct in which to unregister the old reader.
409+ * @scp: return value from corresponding srcu_read_lock_fast().
410+ *
411+ * Exit a light-weight SRCU read-side critical section.
412+ */
413+ static inline void srcu_read_unlock_fast (struct srcu_struct * ssp , struct srcu_ctr __percpu * scp )
414+ __releases (ssp )
415+ {
416+ srcu_check_read_flavor (ssp , SRCU_READ_FLAVOR_FAST );
417+ srcu_lock_release (& ssp -> dep_map );
418+ __srcu_read_unlock_fast (ssp , scp );
419+ }
420+
421+ /**
422+ * srcu_up_read_fast - unregister a old reader from an SRCU-protected structure.
423+ * @ssp: srcu_struct in which to unregister the old reader.
424+ * @scp: return value from corresponding srcu_read_lock_fast().
425+ *
426+ * Exit an SRCU read-side critical section, but not necessarily from
427+ * the same context as the maching srcu_down_read_fast().
428+ */
429+ static inline void srcu_up_read_fast (struct srcu_struct * ssp , struct srcu_ctr __percpu * scp )
430+ __releases (ssp )
431+ {
432+ WARN_ON_ONCE (IS_ENABLED (CONFIG_PROVE_RCU ) && in_nmi ());
433+ srcu_check_read_flavor (ssp , SRCU_READ_FLAVOR_FAST );
434+ __srcu_read_unlock_fast (ssp , scp );
435+ }
436+
363437/**
364438 * srcu_read_unlock_lite - unregister a old reader from an SRCU-protected structure.
365439 * @ssp: srcu_struct in which to unregister the old reader.
366- * @idx: return value from corresponding srcu_read_lock ().
440+ * @idx: return value from corresponding srcu_read_lock_lite ().
367441 *
368442 * Exit a light-weight SRCU read-side critical section.
369443 */
@@ -379,7 +453,7 @@ static inline void srcu_read_unlock_lite(struct srcu_struct *ssp, int idx)
379453/**
380454 * srcu_read_unlock_nmisafe - unregister a old reader from an SRCU-protected structure.
381455 * @ssp: srcu_struct in which to unregister the old reader.
382- * @idx: return value from corresponding srcu_read_lock ().
456+ * @idx: return value from corresponding srcu_read_lock_nmisafe ().
383457 *
384458 * Exit an SRCU read-side critical section, but in an NMI-safe manner.
385459 */
0 commit comments