Skip to content

Commit 34dc27f

Browse files
paulmckrcuFrederic Weisbecker
authored andcommitted
srcu: Create an srcu_expedite_current() function
This commit creates an srcu_expedite_current() function that expedites the current (and possibly the next) SRCU grace period for the specified srcu_struct structure. This functionality will be inherited by RCU Tasks Trace courtesy of its mapping to SRCU fast. If the current SRCU grace period is already waiting, that wait will complete before the expediting takes effect. If there is no SRCU grace period in flight, this function might well create one. [ paulmck: Apply Zqiang feedback for PREEMPT_RT use. ] Signed-off-by: Paul E. McKenney <paulmck@kernel.org> Cc: Andrii Nakryiko <andrii@kernel.org> Cc: Alexei Starovoitov <ast@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: <bpf@vger.kernel.org> Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
1 parent 58ac42f commit 34dc27f

3 files changed

Lines changed: 67 additions & 0 deletions

File tree

include/linux/srcutiny.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ static inline void srcu_barrier(struct srcu_struct *ssp)
103103
synchronize_srcu(ssp);
104104
}
105105

106+
static inline void srcu_expedite_current(struct srcu_struct *ssp) { }
106107
#define srcu_check_read_flavor(ssp, read_flavor) do { } while (0)
107108
#define srcu_check_read_flavor_force(ssp, read_flavor) do { } while (0)
108109

include/linux/srcutree.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ struct srcu_data {
4242
struct timer_list delay_work; /* Delay for CB invoking */
4343
struct work_struct work; /* Context for CB invoking. */
4444
struct rcu_head srcu_barrier_head; /* For srcu_barrier() use. */
45+
struct rcu_head srcu_ec_head; /* For srcu_expedite_current() use. */
46+
int srcu_ec_state; /* State for srcu_expedite_current(). */
4547
struct srcu_node *mynode; /* Leaf srcu_node. */
4648
unsigned long grpmask; /* Mask for leaf srcu_node */
4749
/* ->srcu_data_have_cbs[]. */
@@ -135,6 +137,11 @@ struct srcu_struct {
135137
#define SRCU_STATE_SCAN1 1
136138
#define SRCU_STATE_SCAN2 2
137139

140+
/* Values for srcu_expedite_current() state (->srcu_ec_state). */
141+
#define SRCU_EC_IDLE 0
142+
#define SRCU_EC_PENDING 1
143+
#define SRCU_EC_REPOST 2
144+
138145
/*
139146
* Values for initializing gp sequence fields. Higher values allow wrap arounds to
140147
* occur earlier.
@@ -210,6 +217,7 @@ struct srcu_struct {
210217
int __srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp);
211218
void synchronize_srcu_expedited(struct srcu_struct *ssp);
212219
void srcu_barrier(struct srcu_struct *ssp);
220+
void srcu_expedite_current(struct srcu_struct *ssp);
213221
void srcu_torture_stats_print(struct srcu_struct *ssp, char *tt, char *tf);
214222

215223
// Converts a per-CPU pointer to an ->srcu_ctrs[] array element to that

kernel/rcu/srcutree.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,6 +1688,64 @@ void srcu_barrier(struct srcu_struct *ssp)
16881688
}
16891689
EXPORT_SYMBOL_GPL(srcu_barrier);
16901690

1691+
/* Callback for srcu_expedite_current() usage. */
1692+
static void srcu_expedite_current_cb(struct rcu_head *rhp)
1693+
{
1694+
unsigned long flags;
1695+
bool needcb = false;
1696+
struct srcu_data *sdp = container_of(rhp, struct srcu_data, srcu_ec_head);
1697+
1698+
spin_lock_irqsave_sdp_contention(sdp, &flags);
1699+
if (sdp->srcu_ec_state == SRCU_EC_IDLE) {
1700+
WARN_ON_ONCE(1);
1701+
} else if (sdp->srcu_ec_state == SRCU_EC_PENDING) {
1702+
sdp->srcu_ec_state = SRCU_EC_IDLE;
1703+
} else {
1704+
WARN_ON_ONCE(sdp->srcu_ec_state != SRCU_EC_REPOST);
1705+
sdp->srcu_ec_state = SRCU_EC_PENDING;
1706+
needcb = true;
1707+
}
1708+
spin_unlock_irqrestore_rcu_node(sdp, flags);
1709+
// If needed, requeue ourselves as an expedited SRCU callback.
1710+
if (needcb)
1711+
__call_srcu(sdp->ssp, &sdp->srcu_ec_head, srcu_expedite_current_cb, false);
1712+
}
1713+
1714+
/**
1715+
* srcu_expedite_current - Expedite the current SRCU grace period
1716+
* @ssp: srcu_struct to expedite.
1717+
*
1718+
* Cause the current SRCU grace period to become expedited. The grace
1719+
* period following the current one might also be expedited. If there is
1720+
* no current grace period, one might be created. If the current grace
1721+
* period is currently sleeping, that sleep will complete before expediting
1722+
* will take effect.
1723+
*/
1724+
void srcu_expedite_current(struct srcu_struct *ssp)
1725+
{
1726+
unsigned long flags;
1727+
bool needcb = false;
1728+
struct srcu_data *sdp;
1729+
1730+
migrate_disable();
1731+
sdp = this_cpu_ptr(ssp->sda);
1732+
spin_lock_irqsave_sdp_contention(sdp, &flags);
1733+
if (sdp->srcu_ec_state == SRCU_EC_IDLE) {
1734+
sdp->srcu_ec_state = SRCU_EC_PENDING;
1735+
needcb = true;
1736+
} else if (sdp->srcu_ec_state == SRCU_EC_PENDING) {
1737+
sdp->srcu_ec_state = SRCU_EC_REPOST;
1738+
} else {
1739+
WARN_ON_ONCE(sdp->srcu_ec_state != SRCU_EC_REPOST);
1740+
}
1741+
spin_unlock_irqrestore_rcu_node(sdp, flags);
1742+
// If needed, queue an expedited SRCU callback.
1743+
if (needcb)
1744+
__call_srcu(ssp, &sdp->srcu_ec_head, srcu_expedite_current_cb, false);
1745+
migrate_enable();
1746+
}
1747+
EXPORT_SYMBOL_GPL(srcu_expedite_current);
1748+
16911749
/**
16921750
* srcu_batches_completed - return batches completed.
16931751
* @ssp: srcu_struct on which to report batch completion.

0 commit comments

Comments
 (0)