This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [committed] Use __kernel_cmpxchg for __sync_lock_release


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.

/Mikael

 > 
 > Dave
 > --
 > John David Anglin	dave.anglin@bell.net
 > 
 > 
 > 
 > 
 > ----------------------------------------------------------------------
 > 2014-07-17  John David Anglin  <danglin@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)

-- 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]