On Tue, Apr 12, 2022 at 1:06 AM Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote: > > On Mon, Apr 11, 2022 at 07:16:15PM -0700, Andrew Morton wrote: > > > > +{ > > > + int gen; > > > + unsigned long old_flags, new_flags; > > > + > > > + do { > > > + new_flags = old_flags = READ_ONCE(folio->flags); > > > + if (!(new_flags & LRU_GEN_MASK)) > > > + return false; > > > + > > > + VM_BUG_ON_FOLIO(folio_test_active(folio), folio); > > > + VM_BUG_ON_FOLIO(folio_test_unevictable(folio), folio); > > > + > > > + gen = ((new_flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; > > > + > > > + new_flags &= ~LRU_GEN_MASK; > > > + /* for shrink_page_list() */ > > > + if (reclaiming) > > > + new_flags &= ~(BIT(PG_referenced) | BIT(PG_reclaim)); > > > + else if (lru_gen_is_active(lruvec, gen)) > > > + new_flags |= BIT(PG_active); > > > + } while (cmpxchg(&folio->flags, old_flags, new_flags) != old_flags); > > Also; please use the form: > > unsigned long new, old = READ_ONCE(folio->flags); > > do { > new = /* something */ old; > } while (!try_cmpxchg(&folio->flags, &old, new)) Sweet. Thanks. A related question: if I pass new = old to try_cmpxchg(), does it know that and avoid an unnecessary atomic op?