Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

srcu: Fill out polled grace-period APIs

This commit adds the get_completed_synchronize_srcu() and the
same_state_synchronize_srcu() functions. The first returns a cookie
that is always interpreted as corresponding to an expired grace period.
The second does an equality comparison of a pair of cookies.

Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Kent Overstreet <kent.overstreet@linux.dev>

+35 -2
+31
include/linux/srcu.h
··· 57 57 int __srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp); 58 58 void __srcu_read_unlock(struct srcu_struct *ssp, int idx) __releases(ssp); 59 59 void synchronize_srcu(struct srcu_struct *ssp); 60 + 61 + #define SRCU_GET_STATE_COMPLETED 0x1 62 + 63 + /** 64 + * get_completed_synchronize_srcu - Return a pre-completed polled state cookie 65 + * 66 + * Returns a value that poll_state_synchronize_srcu() will always treat 67 + * as a cookie whose grace period has already completed. 68 + */ 69 + static inline unsigned long get_completed_synchronize_srcu(void) 70 + { 71 + return SRCU_GET_STATE_COMPLETED; 72 + } 73 + 60 74 unsigned long get_state_synchronize_srcu(struct srcu_struct *ssp); 61 75 unsigned long start_poll_synchronize_srcu(struct srcu_struct *ssp); 62 76 bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie); ··· 78 64 // Maximum number of unsigned long values corresponding to 79 65 // not-yet-completed SRCU grace periods. 80 66 #define NUM_ACTIVE_SRCU_POLL_OLDSTATE 2 67 + 68 + /** 69 + * same_state_synchronize_srcu - Are two old-state values identical? 70 + * @oldstate1: First old-state value. 71 + * @oldstate2: Second old-state value. 72 + * 73 + * The two old-state values must have been obtained from either 74 + * get_state_synchronize_srcu(), start_poll_synchronize_srcu(), or 75 + * get_completed_synchronize_srcu(). Returns @true if the two values are 76 + * identical and @false otherwise. This allows structures whose lifetimes 77 + * are tracked by old-state values to push these values to a list header, 78 + * allowing those structures to be slightly smaller. 79 + */ 80 + static inline bool same_state_synchronize_srcu(unsigned long oldstate1, unsigned long oldstate2) 81 + { 82 + return oldstate1 == oldstate2; 83 + } 81 84 82 85 #ifdef CONFIG_NEED_SRCU_NMI_SAFE 83 86 int __srcu_read_lock_nmisafe(struct srcu_struct *ssp) __acquires(ssp);
+2 -1
kernel/rcu/srcutiny.c
··· 277 277 unsigned long cur_s = READ_ONCE(ssp->srcu_idx); 278 278 279 279 barrier(); 280 - return ULONG_CMP_GE(cur_s, cookie) || ULONG_CMP_LT(cur_s, cookie - 3); 280 + return cookie == SRCU_GET_STATE_COMPLETED || 281 + ULONG_CMP_GE(cur_s, cookie) || ULONG_CMP_LT(cur_s, cookie - 3); 281 282 } 282 283 EXPORT_SYMBOL_GPL(poll_state_synchronize_srcu); 283 284
+2 -1
kernel/rcu/srcutree.c
··· 1543 1543 */ 1544 1544 bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie) 1545 1545 { 1546 - if (!rcu_seq_done(&ssp->srcu_sup->srcu_gp_seq, cookie)) 1546 + if (cookie != SRCU_GET_STATE_COMPLETED && 1547 + !rcu_seq_done(&ssp->srcu_sup->srcu_gp_seq, cookie)) 1547 1548 return false; 1548 1549 // Ensure that the end of the SRCU grace period happens before 1549 1550 // any subsequent code that the caller might execute.