On Fri, Jul 18, 2014 at 12:28 PM, Mikael Pettersson <mikpeli...@gmail.com> wrote: > John David Anglin writes: > > Because the atomic sync functions in config/pa/linux-atomic.c are not > > lock free, we need to use > > __kernel_cmpxchg for the __sync_lock_release. This was found in > > glibc's pthread_spin_unlock > > implementation. > > > > Tested on hppa-unknown-linux-gnu. Committed to trunk. > > It seems to me that ARM's linux-atomic.c has the same problem. > CC:ing some ARM folks for clarification.
Prima-facie I'm worried about the 8 byte store case as that's not guaranteed atomic on all MP implementations (you need LPAE IIRC to guarantee this). All other cases look sane to me as the 1,2, 4 byte accesses should be atomic. Ramana > > /Mikael > > > > > Dave > > -- > > John David Anglin dave.ang...@bell.net > > > > > > > > > > ---------------------------------------------------------------------- > > 2014-07-17 John David Anglin <dang...@gcc.gnu.org> > > > > * config/pa/linux-atomic.c (__sync_lock_release_4): New. > > (SYNC_LOCK_RELEASE): Update to use __kernel_cmpxchg for release. > > Don't use SYNC_LOCK_RELEASE for int type. > > > > Index: config/pa/linux-atomic.c > > =================================================================== > > --- config/pa/linux-atomic.c (revision 210671) > > +++ config/pa/linux-atomic.c (working copy) > > @@ -293,13 +293,34 @@ > > SUBWORD_TEST_AND_SET (unsigned short, 2) > > SUBWORD_TEST_AND_SET (unsigned char, 1) > > > > +void HIDDEN > > +__sync_lock_release_4 (int *ptr) > > +{ > > + int failure, oldval; > > + > > + do { > > + oldval = *ptr; > > + failure = __kernel_cmpxchg (oldval, 0, ptr); > > + } while (failure != 0); > > +} > > + > > #define SYNC_LOCK_RELEASE(TYPE, WIDTH) > \ > > void HIDDEN > \ > > __sync_lock_release_##WIDTH (TYPE *ptr) \ > > { \ > > - *ptr = 0; > \ > > + int failure; \ > > + unsigned int oldval, newval, shift, mask; > \ > > + int *wordptr = (int *) ((unsigned long) ptr & ~3); > \ > > + \ > > + shift = (((unsigned long) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \ > > + mask = MASK_##WIDTH << shift; \ > > + \ > > + do { \ > > + oldval = *wordptr; \ > > + newval = oldval & ~mask; > \ > > + failure = __kernel_cmpxchg (oldval, newval, wordptr); \ > > + } while (failure != 0); \ > > } > > > > -SYNC_LOCK_RELEASE (int, 4) > > SYNC_LOCK_RELEASE (short, 2) > > SYNC_LOCK_RELEASE (char, 1) > > --