History

rcu/segcblist: Add debug checks for segment lengths

This commit adds debug checks near the end of rcu_do_batch() that emit warnings if an empty rcu_segcblist structure has non-zero segment counts, or, conversely, if a non-empty structure has all-zero segment counts.

Joel Fernandes (Google) committed 5 years ago

Commit b4e60391 parent 3afe7fa3 files · +21 −2Browse files

Showing the changes to kernel (3 of 3 files). Show all

Unified · Split

3 files
  1. kernel/rcu/rcu_segcblist.c +12 −0
  2. kernel/rcu/rcu_segcblist.h +3 −0
  3. kernel/rcu/tree.c +6 −2
kernel/rcu/rcu_segcblist.c+12−0
@@ -94,6 +94,18 @@ static long rcu_segcblist_get_seglen(struct rcu_segcblist *rsclp, int seg) · 93 unmodified lines
9494 return READ_ONCE(rsclp->seglen[seg]);
9595 }
9696
97+/* Return number of callbacks in segmented callback list by summing seglen. */
98+long rcu_segcblist_n_segment_cbs(struct rcu_segcblist *rsclp)
99+{
100+ long len = 0;
101+ int i;
102+
103+ for (i = RCU_DONE_TAIL; i < RCU_CBLIST_NSEGS; i++)
104+ len += rcu_segcblist_get_seglen(rsclp, i);
105+
106+ return len;
107+}
108+
97109 /* Set the length of a segment of the rcu_segcblist structure. */
98110 static void rcu_segcblist_set_seglen(struct rcu_segcblist *rsclp, int seg, long v)
99111 {
kernel/rcu/rcu_segcblist.h+3−0
@@ -15,6 +15,9 @@ static inline long rcu_cblist_n_cbs(struct rcu_cblist *rclp) · 14 unmodified lines
1515 return READ_ONCE(rclp->len);
1616 }
1717
18+/* Return number of callbacks in segmented callback list by summing seglen. */
19+long rcu_segcblist_n_segment_cbs(struct rcu_segcblist *rsclp);
20+
1821 void rcu_cblist_init(struct rcu_cblist *rclp);
1922 void rcu_cblist_enqueue(struct rcu_cblist *rclp, struct rcu_head *rhp);
2023 void rcu_cblist_flush_enqueue(struct rcu_cblist *drclp,
kernel/rcu/tree.c+6−2
@@ -2434,6 +2434,7 @@ int rcutree_dead_cpu(unsigned int cpu) · 2433 unmodified lines
24342434 static void rcu_do_batch(struct rcu_data *rdp)
24352435 {
24362436 int div;
2437+ bool __maybe_unused empty;
24372438 unsigned long flags;
24382439 const bool offloaded = rcu_segcblist_is_offloaded(&rdp->cblist);
24392440 struct rcu_head *rhp;
@@ -2548,9 +2549,12 @@ static void rcu_do_batch(struct rcu_data *rdp) · 108 unmodified lines
25482549 * The following usually indicates a double call_rcu(). To track
25492550 * this down, try building with CONFIG_DEBUG_OBJECTS_RCU_HEAD=y.
25502551 */
2551− WARN_ON_ONCE(count == 0 && !rcu_segcblist_empty(&rdp->cblist));
2552+ empty = rcu_segcblist_empty(&rdp->cblist);
2553+ WARN_ON_ONCE(count == 0 && !empty);
25522554 WARN_ON_ONCE(!IS_ENABLED(CONFIG_RCU_NOCB_CPU) &&
2553− count != 0 && rcu_segcblist_empty(&rdp->cblist));
2555+ count != 0 && empty);
2556+ WARN_ON_ONCE(count == 0 && rcu_segcblist_n_segment_cbs(&rdp->cblist) != 0);
2557+ WARN_ON_ONCE(!empty && rcu_segcblist_n_segment_cbs(&rdp->cblist) == 0);
25542558
25552559 rcu_nocb_unlock_irqrestore(rdp, flags);
25562560

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t