On Fri, May 31, 2019 at 01:22:54PM +0200, Roman Penyaev wrote: > On 2019-05-31 11:56, Peter Zijlstra wrote: > > On Thu, May 16, 2019 at 10:58:04AM +0200, Roman Penyaev wrote: > > > +static inline bool ep_clear_public_event_bits(struct epitem *epi) > > > +{ > > > + __poll_t old, flags; > > > + > > > + /* > > > + * Here we race with ourselves and with ep_modify(), which can > > > + * change the event bits. In order not to override events updated > > > + * by ep_modify() we have to do cmpxchg. > > > + */ > > > + > > > + old = epi->event.events; > > > + do { > > > + flags = old; > > > + } while ((old = cmpxchg(&epi->event.events, flags, > > > + flags & EP_PRIVATE_BITS)) != flags); > > > + > > > + return flags & ~EP_PRIVATE_BITS; > > > +} > > > > AFAICT epi->event.events also has normal writes to it, eg. in > > ep_modify(). A number of architectures cannot handle concurrent normal > > writes and cmpxchg() to the same variable. > > Yes, we race with the current function and with ep_modify(). Then, > ep_modify() > should do something as the following: > > - epi->event.events = event->events > + xchg(&epi->event.events, event->events); > > Is that ok? That should be correct, but at that point I think we should also always read the thing with READ_ONCE() to avoid load-tearing. And I suspect it then becomes sensible to change the type to atomic_t. atomic_set() vs atomic_cmpxchg() only carries the extra overhead on those 'dodgy' platforms. > Just curious: what are these archs? Oh, lovely stuff like parisc, sparc32 and arc-eznps. See arch/parisc/lib/bitops.c:__cmpxchg_*() for example :/ Those systems only have a single truly atomic op (something from the xchg / test-and-set family) and the rest is fudged on top of that.