[PATCH 3/3] Implemented testandset() for Cortex-M3

Sergei Poselenov sposelenov at emcraft.com
Sat Nov 1 09:00:19 UTC 2014


commit 683a77455f2226419fe688dd2104ef1a391bb3b2
Author: Sergei Poselenov <sposelenov at emcraft.com>
Date:   Sun Oct 26 14:54:12 2014 +0400

    Implemented testandset() for Cortex-M3
    
    Signed-off-by: Sergei Poselenov <sposelenov at emcraft.com>

diff --git a/extra/Configs/Config.arm b/extra/Configs/Config.arm
index 0bb2971..5777d3b 100644
--- a/extra/Configs/Config.arm
+++ b/extra/Configs/Config.arm
@@ -36,3 +36,10 @@ config USE_BX
 	  Say 'y' to use BX to return from functions on your thumb-aware
 	  processor. Say 'y' if you need to use interworking. Say 'n' if not.
 	  It is safe to say 'y' even if you're not doing interworking.
+
+config USE_LDREXSTREX
+	bool "Use load-store exclusive ASM ops (not supported in SmartFusion)"
+	depends on COMPILE_IN_THUMB_MODE
+	default y
+	help
+	  Say 'y' to use LDREX/STREX ASM ops.
diff --git a/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h
index 583eb68..93804ba 100644
--- a/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h
+++ b/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h
@@ -22,12 +22,50 @@
 #ifndef _PT_MACHINE_H
 #define _PT_MACHINE_H   1
 
-#include <features.h>
+#include <sys/syscall.h>
+#include <unistd.h>
 
 #ifndef PT_EI
 # define PT_EI __extern_always_inline
 #endif
 
+#if defined(__thumb__)
+#if defined(__USE_LDREXSTREX__)
+PT_EI long int ldrex(int *spinlock)
+{
+	long int ret;
+	__asm__ __volatile__(
+		"ldrex %0, [%1]\n"
+		: "=r"(ret)
+		: "r"(spinlock) : "memory");
+	return ret;
+}
+
+PT_EI long int strex(int val, int *spinlock)
+{
+	long int ret;
+	__asm__ __volatile__(
+		"strex %0, %1, [%2]\n"
+		: "=r"(ret)
+		: "r" (val), "r"(spinlock) : "memory");
+	return ret;
+}
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  register unsigned int ret;
+
+  do {
+	  ret = ldrex(spinlock);
+  } while (strex(1, spinlock));
+
+  return ret;
+}
+
+#else /* __USE_LDREXSTREX__ */
+
 /* This will not work on ARM1 or ARM2 because SWP is lacking on those
    machines.  Unfortunately we have no way to detect this at compile
    time; let's hope nobody tries to use one.  */
@@ -37,8 +75,6 @@ PT_EI long int testandset (int *spinlock);
 PT_EI long int testandset (int *spinlock)
 {
   register unsigned int ret;
-
-#if defined(__thumb__)
   void *pc;
   __asm__ __volatile__(
 	".align 0\n"
@@ -51,15 +87,21 @@ PT_EI long int testandset (int *spinlock)
 	"\t.force_thumb"
 	: "=r"(ret), "=r"(pc)
 	: "0"(1), "r"(spinlock));
-#else
+  return ret;
+}
+#endif
+#else /* __thumb__ */
+
+PT_EI long int testandset (int *spinlock);
+PT_EI long int testandset (int *spinlock)
+{
+  register unsigned int ret;
   __asm__ __volatile__("swp %0, %1, [%2]"
 		       : "=r"(ret)
 		       : "0"(1), "r"(spinlock));
-#endif
-
   return ret;
 }
-
+#endif
 
 /* Get some notion of the current stack.  Need not be exactly the top
    of the stack, just something somewhere in the current frame.  */




More information about the uClibc mailing list