]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
srcu: Fill out polled grace-period APIs
authorPaul E. McKenney <paulmck@kernel.org>
Fri, 14 Jun 2024 20:26:44 +0000 (13:26 -0700)
committerPaul E. McKenney <paulmck@kernel.org>
Tue, 18 Jun 2024 17:13:37 +0000 (10:13 -0700)
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>
include/linux/srcu.h
kernel/rcu/srcutiny.c
kernel/rcu/srcutree.c

index f664cba7a80c2103d2aa58c94484bc19fa353ad7..6f6cb5fc12424c9e3096abdc67cc25c827a4e1eb 100644 (file)
@@ -57,6 +57,20 @@ void cleanup_srcu_struct(struct srcu_struct *ssp);
 int __srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp);
 void __srcu_read_unlock(struct srcu_struct *ssp, int idx) __releases(ssp);
 void synchronize_srcu(struct srcu_struct *ssp);
+
+#define SRCU_GET_STATE_COMPLETED 0x1
+
+/**
+ * get_completed_synchronize_srcu - Return a pre-completed polled state cookie
+ *
+ * Returns a value that poll_state_synchronize_srcu() will always treat
+ * as a cookie whose grace period has already completed.
+ */
+static inline unsigned long get_completed_synchronize_srcu(void)
+{
+       return SRCU_GET_STATE_COMPLETED;
+}
+
 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);
@@ -65,6 +79,23 @@ bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie);
 // not-yet-completed SRCU grace periods.
 #define NUM_ACTIVE_SRCU_POLL_OLDSTATE 2
 
+/**
+ * same_state_synchronize_srcu - Are two old-state values identical?
+ * @oldstate1: First old-state value.
+ * @oldstate2: Second old-state value.
+ *
+ * The two old-state values must have been obtained from either
+ * get_state_synchronize_srcu(), start_poll_synchronize_srcu(), or
+ * get_completed_synchronize_srcu().  Returns @true if the two values are
+ * identical and @false otherwise.  This allows structures whose lifetimes
+ * are tracked by old-state values to push these values to a list header,
+ * allowing those structures to be slightly smaller.
+ */
+static inline bool same_state_synchronize_srcu(unsigned long oldstate1, unsigned long oldstate2)
+{
+       return oldstate1 == oldstate2;
+}
+
 #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);
index 5afd5cf494dba32a6e98e9cd376c362248a2c285..549c03336ee97150598a37e4c39f981ad21c98d5 100644 (file)
@@ -277,7 +277,8 @@ bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie)
        unsigned long cur_s = READ_ONCE(ssp->srcu_idx);
 
        barrier();
-       return ULONG_CMP_GE(cur_s, cookie) || ULONG_CMP_LT(cur_s, cookie - 3);
+       return cookie == SRCU_GET_STATE_COMPLETED ||
+              ULONG_CMP_GE(cur_s, cookie) || ULONG_CMP_LT(cur_s, cookie - 3);
 }
 EXPORT_SYMBOL_GPL(poll_state_synchronize_srcu);
 
index 15dc22a8ff5ab73f2c4ce63b4250fdbdd38cd431..d6a4047719cb03364e811c5857b69133b29f73a3 100644 (file)
@@ -1543,7 +1543,8 @@ EXPORT_SYMBOL_GPL(start_poll_synchronize_srcu);
  */
 bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie)
 {
-       if (!rcu_seq_done(&ssp->srcu_sup->srcu_gp_seq, cookie))
+       if (cookie != SRCU_GET_STATE_COMPLETED &&
+           !rcu_seq_done(&ssp->srcu_sup->srcu_gp_seq, cookie))
                return false;
        // Ensure that the end of the SRCU grace period happens before
        // any subsequent code that the caller might execute.