From 5c0a3b60fbc3442a14169a37657b27ff3173f9db Mon Sep 17 00:00:00 2001 From: Chris Zankel Date: Wed, 17 Oct 2012 16:02:01 -0700 Subject: xtensa: use atomic instructions instead of a syscall Replace system calls with atomic instructions for 'compare and swap' in linuxthreads.old. Signed-off-by: Chris Zankel --- .../linuxthreads.old/sysdeps/xtensa/pt-machine.h | 42 +++++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) (limited to 'libpthread') diff --git a/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h index acd4d109f..2ae227581 100644 --- a/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h +++ b/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h @@ -26,19 +26,51 @@ #include #ifndef PT_EI -# define PT_EI __extern_always_inline +# define PT_EI extern inline __attribute__ ((gnu_inline)) #endif -/* Memory barrier. */ #define MEMORY_BARRIER() __asm__ ("memw" : : : "memory") +#define HAS_COMPARE_AND_SWAP + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); /* Spinlock implementation; required. */ PT_EI long int testandset (int *spinlock) { - int unused = 0; - return INTERNAL_SYSCALL (xtensa, , 4, SYS_XTENSA_ATOMIC_SET, - spinlock, 1, unused); + unsigned long tmp; + __asm__ volatile ( +" movi %0, 0 \n" +" wsr %0, SCOMPARE1 \n" +" movi %0, 1 \n" +" s32c1i %0, %1, 0 \n" + : "=&a" (tmp) + : "a" (spinlock) + : "memory" + ); + return tmp; +} + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + unsigned long tmp; + unsigned long value; + __asm__ volatile ( +"1: l32i %0, %2, 0 \n" +" bne %0, %4, 2f \n" +" wsr %0, SCOMPARE1 \n" +" mov %1, %0 \n" +" mov %0, %3 \n" +" s32c1i %0, %2, 0 \n" +" bne %1, %0, 1b \n" +"2: \n" + : "=&a" (tmp), "=&a" (value) + : "a" (p), "a" (newval), "a" (oldval) + : "memory" ); + + return tmp == oldval; } /* Get some notion of the current stack. Need not be exactly the top -- cgit v1.2.3