Re: __sync_lock_test_and_set on ARM

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Phil Endecott writes:
 > Andrew Haley wrote:
 > > this stuff really should be done by the compiler. 
 > 
 > Yes.  I've filed a bug asking for a __sync_lock_test_and_set builtin:
 > 
 > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33413

Surer, but the problem is that for most of the things we want to do
(lightweight locks, for example) __sync_lock_test_and_set() doesn't
really do what we need: we need compare_and_swap().  That's why the
kernel helper is so useful, because it's robust even if we are on
pre-ARMv6 hardware.

ARM code is like this:

/* Atomic compare and exchange.  These sequences are not actually
   atomic; there is a race if *ADDR != OLD_VAL and we are preempted
   between the two swaps.  However, they are very close to atomic, and
   are the best that a pre-ARMv6 implementation can do without
   operating system support.  LinuxThreads has been using these
   sequences for many years.  */

inline static bool
compare_and_swap(volatile obj_addr_t *addr,
		 obj_addr_t old_val,
		 obj_addr_t new_val)
{
  volatile obj_addr_t result, tmp;
  __asm__ ("\n"
	   "0:	ldr	%[tmp],[%[addr]]\n"
	   "	cmp	%[tmp],%[old_val]\n"
	   "	movne	%[result],#0\n"
	   "	bne	1f\n"
	   "	swp	%[result],%[new_val],[%[addr]]\n"
	   "	cmp	%[tmp],%[result]\n"
	   "	swpne	%[tmp],%[result],[%[addr]]\n"
	   "	bne	0b\n"
	   "	mov	%[result],#1\n"
	   "1:"
	   : [result] "=&r" (result), [tmp] "=&r" (tmp)
	   : [addr] "r" (addr), [new_val] "r" (new_val), [old_val] "r" (old_val)
	   : "cc", "memory");

  return result;
}

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux