Skip to content

Commit fc2897d

Browse files
paulmckrcuurezki
authored andcommitted
rcu: Inform KCSAN of one-byte cmpxchg() in rcu_trc_cmpxchg_need_qs()
Tasks Trace RCU needs a single-byte cmpxchg(), but no such thing exists. Therefore, rcu_trc_cmpxchg_need_qs() emulates one using field substitution and a four-byte cmpxchg(), such that the other three bytes are always atomically updated to their old values. This works, but results in false-positive KCSAN failures because as far as KCSAN knows, this cmpxchg() operation is updating all four bytes. This commit therefore encloses the cmpxchg() in a data_race() and adds a single-byte instrument_atomic_read_write(), thus telling KCSAN exactly what is going on so as to avoid the false positives. Signed-off-by: Paul E. McKenney <[email protected]> Cc: Marco Elver <[email protected]> Signed-off-by: Uladzislau Rezki (Sony) <[email protected]>
1 parent ae2b217 commit fc2897d

File tree

1 file changed

+9
-1
lines changed

1 file changed

+9
-1
lines changed

kernel/rcu/tasks.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,7 @@ static void rcu_st_need_qs(struct task_struct *t, u8 v)
14571457
/*
14581458
* Do a cmpxchg() on ->trc_reader_special.b.need_qs, allowing for
14591459
* the four-byte operand-size restriction of some platforms.
1460+
*
14601461
* Returns the old value, which is often ignored.
14611462
*/
14621463
u8 rcu_trc_cmpxchg_need_qs(struct task_struct *t, u8 old, u8 new)
@@ -1468,7 +1469,14 @@ u8 rcu_trc_cmpxchg_need_qs(struct task_struct *t, u8 old, u8 new)
14681469
if (trs_old.b.need_qs != old)
14691470
return trs_old.b.need_qs;
14701471
trs_new.b.need_qs = new;
1471-
ret.s = cmpxchg(&t->trc_reader_special.s, trs_old.s, trs_new.s);
1472+
1473+
// Although cmpxchg() appears to KCSAN to update all four bytes,
1474+
// only the .b.need_qs byte actually changes.
1475+
instrument_atomic_read_write(&t->trc_reader_special.b.need_qs,
1476+
sizeof(t->trc_reader_special.b.need_qs));
1477+
// Avoid false-positive KCSAN failures.
1478+
ret.s = data_race(cmpxchg(&t->trc_reader_special.s, trs_old.s, trs_new.s));
1479+
14721480
return ret.b.need_qs;
14731481
}
14741482
EXPORT_SYMBOL_GPL(rcu_trc_cmpxchg_need_qs);

0 commit comments

Comments
 (0)