On Mon, Mar 14, 2016 at 07:44:14PM -0700, Linus Torvalds wrote:
> On Mon, Mar 14, 2016 at 5:32 AM, Ingo Molnar <mi...@kernel.org> wrote:
> > +/**
> > + * fetch_or - perform *ptr |= mask and return old value of *ptr
> > + * @ptr: pointer to value
> > + * @mask: mask to OR on the value
> > + *
> > + * cmpxchg based fetch_or, macro so it works for different integer types
> > + */
> > +#ifndef fetch_or
> > +#define fetch_or(ptr, mask)                                            \
> > +({     typeof(*(ptr)) __old, __val = *(ptr);                           \
> > +       for (;;) {                                                      \
> > +               __old = cmpxchg((ptr), __val, __val | (mask));          \
> > +               if (__old == __val)                                     \
> > +                       break;                                          \
> > +               __val = __old;                                          \
> > +       }                                                               \
> > +       __old;                                                          \
> > +})
> > +#endif
> 
> This is garbage.
> 
> This macro re-uses the "mask" argument potentially many many times, so
> semantically it's very dubious.

So the below cures that; but do we want to maybe pull this back into
sched.c and expose a version that operates on a fixed type instead?

Although with xchg() and cmpxchg() we've already set a precedence for
multi-width operators.

The whole thread_info::flags thing is rather 'special' and I'm not sure
we even want to go clean that up, I can see why 64bit arch would very
much want a 64bit flags word etc. And TIF_flags are very arch specific.

---
 include/linux/atomic.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/linux/atomic.h b/include/linux/atomic.h
index 6c502cb13c95..114caf672b11 100644
--- a/include/linux/atomic.h
+++ b/include/linux/atomic.h
@@ -558,8 +558,9 @@ static inline int atomic_dec_if_positive(atomic_t *v)
 #ifndef fetch_or
 #define fetch_or(ptr, mask)                                            \
 ({     typeof(*(ptr)) __old, __val = *(ptr);                           \
+       typeof(mask) __mask = (mask);                                   \
        for (;;) {                                                      \
-               __old = cmpxchg((ptr), __val, __val | (mask));          \
+               __old = cmpxchg((ptr), __val, __val | __mask);          \
                if (__old == __val)                                     \
                        break;                                          \
                __val = __old;                                          \

Reply via email to