summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Zankel <chris@zankel.net>2012-10-17 16:02:01 -0700
committerChris Zankel <chris@zankel.net>2012-11-03 12:57:45 -0700
commit5c0a3b60fbc3442a14169a37657b27ff3173f9db (patch)
treedf5678bbdaa4d45b7a4e2a9b352fe536dc14e0a1
parent888b232d1e6bf6819aec7f13be298226ce91bf5b (diff)
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 <chris@zankel.net>
-rw-r--r--libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h42
1 files changed, 37 insertions, 5 deletions
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 <asm/unistd.h>
#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