commit 626dbe5372b47aea1fe27c52b55649621ee30ff4
Author: Sergei Poselenov <sposelenov@emcraft.com>
Date:   Sun Dec 15 13:53:55 2013 +0400

    RT #91128. Implemented testandset() with ldrex/strex (not supported on SmartFusion).

diff --git a/dot_config_pthreads b/dot_config_pthreads
index 1181fde..3f5e11b 100644
--- a/dot_config_pthreads
+++ b/dot_config_pthreads
@@ -38,6 +38,7 @@ FORCE_OPTIONS_FOR_ARCH=y
 CONFIG_ARM_EABI=y
 COMPILE_IN_THUMB_MODE=y
 USE_BX=y
+USE_LDREXSTREX=y
 TARGET_SUBARCH=""
 # UCLIBC_FORMAT_ELF is not set
 # UCLIBC_FORMAT_FDPIC_ELF is not set
diff --git a/dot_config_pthreads-no-ldrex b/dot_config_pthreads-no-ldrex
new file mode 100644
index 0000000..64b147d
--- /dev/null
+++ b/dot_config_pthreads-no-ldrex
@@ -0,0 +1,230 @@
+#
+# Automatically generated make config: don't edit
+# Version: 0.9.33.2
+# Sun Mar 24 12:28:02 2013
+#
+# TARGET_alpha is not set
+TARGET_arm=y
+# TARGET_avr32 is not set
+# TARGET_bfin is not set
+# TARGET_c6x is not set
+# TARGET_cris is not set
+# TARGET_e1 is not set
+# TARGET_frv is not set
+# TARGET_h8300 is not set
+# TARGET_hppa is not set
+# TARGET_i386 is not set
+# TARGET_i960 is not set
+# TARGET_ia64 is not set
+# TARGET_m68k is not set
+# TARGET_microblaze is not set
+# TARGET_mips is not set
+# TARGET_nios is not set
+# TARGET_nios2 is not set
+# TARGET_powerpc is not set
+# TARGET_sh is not set
+# TARGET_sh64 is not set
+# TARGET_sparc is not set
+# TARGET_v850 is not set
+# TARGET_vax is not set
+# TARGET_x86_64 is not set
+# TARGET_xtensa is not set
+
+#
+# Target Architecture Features and Options
+#
+TARGET_ARCH="arm"
+FORCE_OPTIONS_FOR_ARCH=y
+CONFIG_ARM_EABI=y
+COMPILE_IN_THUMB_MODE=y
+USE_BX=y
+# USE_LDREXSTREX is not set
+TARGET_SUBARCH=""
+# UCLIBC_FORMAT_ELF is not set
+# UCLIBC_FORMAT_FDPIC_ELF is not set
+# UCLIBC_FORMAT_DSBT_ELF is not set
+UCLIBC_FORMAT_FLAT=y
+# UCLIBC_FORMAT_FLAT_SEP_DATA is not set
+# UCLIBC_FORMAT_SHARED_FLAT is not set
+ARCH_ANY_ENDIAN=y
+ARCH_LITTLE_ENDIAN=y
+# ARCH_WANTS_BIG_ENDIAN is not set
+ARCH_WANTS_LITTLE_ENDIAN=y
+# ARCH_HAS_MMU is not set
+UCLIBC_HAS_FLOATS=y
+# UCLIBC_HAS_FPU is not set
+UCLIBC_HAS_SOFT_FLOAT=y
+DO_C99_MATH=y
+# DO_XSI_MATH is not set
+# UCLIBC_HAS_FENV is not set
+KERNEL_HEADERS="KRNL_HDR"
+UCLIBC_UCLINUX_BROKEN_MUNMAP=y
+HAVE_DOT_CONFIG=y
+
+#
+# General Library Settings
+#
+# DOPIC is not set
+ARCH_HAS_NO_SHARED=y
+ARCH_HAS_NO_LDSO=y
+UCLIBC_CTOR_DTOR=y
+# HAS_NO_THREADS is not set
+LINUXTHREADS_OLD=y
+# LINUXTHREADS_NEW is not set
+# UCLIBC_HAS_THREADS_NATIVE is not set
+UCLIBC_HAS_THREADS=y
+PTHREADS_DEBUG_SUPPORT=y
+UCLIBC_HAS_SYSLOG=y
+UCLIBC_HAS_LFS=y
+MALLOC=y
+# MALLOC_SIMPLE is not set
+# MALLOC_STANDARD is not set
+# MALLOC_GLIBC_COMPAT is not set
+UCLIBC_DYNAMIC_ATEXIT=y
+# COMPAT_ATEXIT is not set
+UCLIBC_SUSV3_LEGACY=y
+# UCLIBC_SUSV3_LEGACY_MACROS is not set
+UCLIBC_SUSV4_LEGACY=y
+# UCLIBC_STRICT_HEADERS is not set
+# UCLIBC_HAS_STUBS is not set
+UCLIBC_HAS_SHADOW=y
+UCLIBC_HAS_PROGRAM_INVOCATION_NAME=y
+UCLIBC_HAS___PROGNAME=y
+UCLIBC_HAS_PTY=y
+ASSUME_DEVPTS=y
+UNIX98PTY_ONLY=y
+# UCLIBC_HAS_GETPT is not set
+# UCLIBC_HAS_LIBUTIL is not set
+UCLIBC_HAS_TM_EXTENSIONS=y
+UCLIBC_HAS_TZ_CACHING=y
+UCLIBC_HAS_TZ_FILE=y
+UCLIBC_HAS_TZ_FILE_READ_MANY=y
+UCLIBC_TZ_FILE_PATH="/etc/TZ"
+# UCLIBC_FALLBACK_TO_ETC_LOCALTIME is not set
+
+#
+# Advanced Library Settings
+#
+UCLIBC_PWD_BUFFER_SIZE=256
+UCLIBC_GRP_BUFFER_SIZE=256
+
+#
+# Support various families of functions
+#
+UCLIBC_LINUX_MODULE_26=y
+# UCLIBC_LINUX_MODULE_24 is not set
+UCLIBC_LINUX_SPECIFIC=y
+# UCLIBC_HAS_GNU_ERROR is not set
+# UCLIBC_BSD_SPECIFIC is not set
+# UCLIBC_HAS_BSD_ERR is not set
+# UCLIBC_HAS_OBSOLETE_BSD_SIGNAL is not set
+# UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL is not set
+# UCLIBC_NTP_LEGACY is not set
+# UCLIBC_SV4_DEPRECATED is not set
+UCLIBC_HAS_REALTIME=y
+# UCLIBC_HAS_ADVANCED_REALTIME is not set
+# UCLIBC_HAS_EPOLL is not set
+# UCLIBC_HAS_XATTR is not set
+# UCLIBC_HAS_PROFILING is not set
+# UCLIBC_HAS_CRYPT_IMPL is not set
+# UCLIBC_HAS_CRYPT_STUB is not set
+UCLIBC_HAS_NETWORK_SUPPORT=y
+UCLIBC_HAS_SOCKET=y
+UCLIBC_HAS_IPV4=y
+# UCLIBC_HAS_IPV6 is not set
+UCLIBC_HAS_RPC=y
+# UCLIBC_HAS_FULL_RPC is not set
+# UCLIBC_HAS_REENTRANT_RPC is not set
+# UCLIBC_USE_NETLINK is not set
+# UCLIBC_HAS_BSD_RES_CLOSE is not set
+UCLIBC_HAS_COMPAT_RES_STATE=y
+# UCLIBC_HAS_EXTRA_COMPAT_RES_STATE is not set
+UCLIBC_HAS_RESOLVER_SUPPORT=y
+UCLIBC_HAS_LIBRESOLV_STUB=y
+# UCLIBC_HAS_LIBNSL_STUB is not set
+
+#
+# String and Stdio Support
+#
+# UCLIBC_HAS_STRING_GENERIC_OPT is not set
+UCLIBC_HAS_STRING_ARCH_OPT=y
+UCLIBC_HAS_CTYPE_TABLES=y
+UCLIBC_HAS_CTYPE_SIGNED=y
+UCLIBC_HAS_CTYPE_UNSAFE=y
+# UCLIBC_HAS_CTYPE_CHECKED is not set
+# UCLIBC_HAS_CTYPE_ENFORCED is not set
+UCLIBC_HAS_WCHAR=y
+# UCLIBC_HAS_LOCALE is not set
+UCLIBC_HAS_HEXADECIMAL_FLOATS=y
+UCLIBC_HAS_GLIBC_CUSTOM_PRINTF=y
+UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS=9
+UCLIBC_HAS_SCANF_GLIBC_A_FLAG=y
+# UCLIBC_HAS_STDIO_BUFSIZ_NONE is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_256 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_512 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_1024 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_2048 is not set
+UCLIBC_HAS_STDIO_BUFSIZ_4096=y
+# UCLIBC_HAS_STDIO_BUFSIZ_8192 is not set
+UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE=y
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4 is not set
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8 is not set
+# UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT is not set
+UCLIBC_HAS_STDIO_GETC_MACRO=y
+UCLIBC_HAS_STDIO_PUTC_MACRO=y
+UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION=y
+UCLIBC_HAS_FOPEN_LARGEFILE_MODE=y
+UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE=y
+# UCLIBC_HAS_FOPEN_CLOSEEXEC_MODE is not set
+UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y
+# UCLIBC_HAS_PRINTF_M_SPEC is not set
+UCLIBC_HAS_ERRNO_MESSAGES=y
+# UCLIBC_HAS_SYS_ERRLIST is not set
+UCLIBC_HAS_SIGNUM_MESSAGES=y
+# UCLIBC_HAS_SYS_SIGLIST is not set
+UCLIBC_HAS_GNU_GETOPT=y
+UCLIBC_HAS_GNU_GETSUBOPT=y
+
+#
+# Big and Tall
+#
+# UCLIBC_HAS_REGEX is not set
+UCLIBC_HAS_FNMATCH=y
+UCLIBC_HAS_FNMATCH_OLD=y
+# UCLIBC_HAS_WORDEXP is not set
+# UCLIBC_HAS_NFTW is not set
+# UCLIBC_HAS_FTW is not set
+# UCLIBC_HAS_FTS is not set
+UCLIBC_HAS_GLOB=y
+# UCLIBC_HAS_GNU_GLOB is not set
+# UCLIBC_HAS_UTMPX is not set
+
+#
+# Library Installation Options
+#
+RUNTIME_PREFIX="/"
+DEVEL_PREFIX="/usr"
+MULTILIB_DIR="lib"
+HARDWIRED_ABSPATH=y
+
+#
+# Security options
+#
+# UCLIBC_HAS_ARC4RANDOM is not set
+# UCLIBC_HAS_SSP is not set
+UCLIBC_BUILD_NOEXECSTACK=y
+
+#
+# Development/debugging options
+#
+CROSS_COMPILER_PREFIX="arm-uclinuxeabi-"
+UCLIBC_EXTRA_CFLAGS=""
+# DODEBUG is not set
+# DODEBUG_PT is not set
+# DOSTRIP is not set
+# DOASSERTS is not set
+# UCLIBC_MALLOC_DEBUGGING is not set
+WARNINGS="-Wall"
+# EXTRA_WARNINGS is not set
+# DOMULTI is not set
+# UCLIBC_MJN3_ONLY is not set
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 0b8c0cc..dcffeb1 100644
--- a/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h
+++ b/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h
@@ -30,15 +30,50 @@
 #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)
 {
-  int unused = 0;
-  return INTERNAL_SYSCALL_ARM (atomicops, , 4, SYS_ARM_ATOMIC_SET,
-			  spinlock, 1, unused);
+  register unsigned int ret;
+
+  do {
+	  ret = ldrex(spinlock);
+  } while (strex(1, spinlock));
+
+  return ret;
 }
+#else /* USE_LDREXSTREX */
 
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+	int unused = 0;
+	return INTERNAL_SYSCALL_ARM (atomicops, , 4, SYS_ARM_ATOMIC_SET,
+				spinlock, 1, unused);
+}
+#endif
 #else
 
 /* This will not work on ARM1 or ARM2 because SWP is lacking on those
