summaryrefslogtreecommitdiff
path: root/libpthread/linuxthreads/sysdeps/arm/pt-machine.h
diff options
context:
space:
mode:
Diffstat (limited to 'libpthread/linuxthreads/sysdeps/arm/pt-machine.h')
-rw-r--r--libpthread/linuxthreads/sysdeps/arm/pt-machine.h57
1 files changed, 48 insertions, 9 deletions
diff --git a/libpthread/linuxthreads/sysdeps/arm/pt-machine.h b/libpthread/linuxthreads/sysdeps/arm/pt-machine.h
index 9ffc8bdc4..3250961cf 100644
--- a/libpthread/linuxthreads/sysdeps/arm/pt-machine.h
+++ b/libpthread/linuxthreads/sysdeps/arm/pt-machine.h
@@ -1,6 +1,6 @@
/* Machine-dependent pthreads configuration and inline functions.
ARM version.
- Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Philip Blundell <philb@gnu.org>.
@@ -15,36 +15,75 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
#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 __ARM_ARCH >= 7 || defined(__thumb2__)
+/* Spinlock implementation; required. */
+PT_EI long int
+testandset (int *spinlock)
+{
+ unsigned int ret, tmp, val = 1;
+
+ __asm__ __volatile__ (
+"0: ldrex %0, [%2] \n"
+" strex %1, %3, [%2] \n"
+" cmp %1, #0 \n"
+" bne 0b"
+ : "=&r" (ret), "=&r" (tmp)
+ : "r" (spinlock), "r" (val) : "memory", "cc");
+
+ return ret;
+}
+
+#elif defined(__thumb__)
+
/* 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. */
/* Spinlock implementation; required. */
-PT_EI long int
-testandset (int *spinlock)
+PT_EI long int testandset (int *spinlock);
+PT_EI long int testandset (int *spinlock)
{
register unsigned int ret;
+ void *pc;
+ __asm__ __volatile__(
+ ".align 0\n"
+ "\tbx pc\n"
+ "\tnop\n"
+ "\t.arm\n"
+ "\tswp %0, %2, [%3]\n"
+ "\torr %1, pc, #1\n"
+ "\tbx %1\n"
+ "\t.force_thumb"
+ : "=r"(ret), "=r"(pc)
+ : "0"(1), "r"(spinlock));
+ return ret;
+}
+
+#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));
-
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. */