Commit e6060b41 authored by Paul E. McKenney's avatar Paul E. McKenney

rcu/nocb: Allow lockless use of rcu_segcblist_empty()

Currently, rcu_segcblist_empty() assumes that the callback list is not
being changed by other CPUs, but upcoming changes will require it to
operate locklessly.  This commit therefore adds the needed READ_ONCE()
call, along with the WRITE_ONCE() calls when updating the callback list's
->head field.
Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.ibm.com>
parent 76c6927c
...@@ -213,7 +213,7 @@ void rcu_segcblist_extract_done_cbs(struct rcu_segcblist *rsclp, ...@@ -213,7 +213,7 @@ void rcu_segcblist_extract_done_cbs(struct rcu_segcblist *rsclp,
if (!rcu_segcblist_ready_cbs(rsclp)) if (!rcu_segcblist_ready_cbs(rsclp))
return; /* Nothing to do. */ return; /* Nothing to do. */
*rclp->tail = rsclp->head; *rclp->tail = rsclp->head;
rsclp->head = *rsclp->tails[RCU_DONE_TAIL]; WRITE_ONCE(rsclp->head, *rsclp->tails[RCU_DONE_TAIL]);
WRITE_ONCE(*rsclp->tails[RCU_DONE_TAIL], NULL); WRITE_ONCE(*rsclp->tails[RCU_DONE_TAIL], NULL);
rclp->tail = rsclp->tails[RCU_DONE_TAIL]; rclp->tail = rsclp->tails[RCU_DONE_TAIL];
for (i = RCU_CBLIST_NSEGS - 1; i >= RCU_DONE_TAIL; i--) for (i = RCU_CBLIST_NSEGS - 1; i >= RCU_DONE_TAIL; i--)
...@@ -268,7 +268,7 @@ void rcu_segcblist_insert_done_cbs(struct rcu_segcblist *rsclp, ...@@ -268,7 +268,7 @@ void rcu_segcblist_insert_done_cbs(struct rcu_segcblist *rsclp,
if (!rclp->head) if (!rclp->head)
return; /* No callbacks to move. */ return; /* No callbacks to move. */
*rclp->tail = rsclp->head; *rclp->tail = rsclp->head;
rsclp->head = rclp->head; WRITE_ONCE(rsclp->head, rclp->head);
for (i = RCU_DONE_TAIL; i < RCU_CBLIST_NSEGS; i++) for (i = RCU_DONE_TAIL; i < RCU_CBLIST_NSEGS; i++)
if (&rsclp->head == rsclp->tails[i]) if (&rsclp->head == rsclp->tails[i])
WRITE_ONCE(rsclp->tails[i], rclp->tail); WRITE_ONCE(rsclp->tails[i], rclp->tail);
......
...@@ -36,7 +36,7 @@ struct rcu_head *rcu_cblist_dequeue(struct rcu_cblist *rclp); ...@@ -36,7 +36,7 @@ struct rcu_head *rcu_cblist_dequeue(struct rcu_cblist *rclp);
*/ */
static inline bool rcu_segcblist_empty(struct rcu_segcblist *rsclp) static inline bool rcu_segcblist_empty(struct rcu_segcblist *rsclp)
{ {
return !rsclp->head; return !READ_ONCE(rsclp->head);
} }
/* Return number of callbacks in segmented callback list. */ /* Return number of callbacks in segmented callback list. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment